adventofcode

git clone https://git.ce9e.org/adventofcode.git

commit
791c7e1cb91b5745f234173dfb46eff7edb7d703
parent
4014abd9f483824f746823514973eb85f3072fef
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2021-12-21 09:26
day 21

Diffstat

A 2021/21/input.txt 2 ++
A 2021/21/part1.rs 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A 2021/21/part2.rs 111 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
A 2021/21/test.txt 2 ++

4 files changed, 172 insertions, 0 deletions


diff --git a/2021/21/input.txt b/2021/21/input.txt

@@ -0,0 +1,2 @@
   -1     1 Player 1 starting position: 9
   -1     2 Player 2 starting position: 3

diff --git a/2021/21/part1.rs b/2021/21/part1.rs

@@ -0,0 +1,57 @@
   -1     1 use std::env::args;
   -1     2 use std::fs::File;
   -1     3 use std::io::BufRead;
   -1     4 use std::io::BufReader;
   -1     5 
   -1     6 fn get_data() -> (u64, u64) {
   -1     7     let path = args().nth(1).unwrap();
   -1     8     let file = File::open(path).unwrap();
   -1     9 
   -1    10     let mut state = 0;
   -1    11     let mut player1 = 0;
   -1    12     let mut player2 = 0;
   -1    13 
   -1    14     for line in BufReader::new(file).lines() {
   -1    15         match state {
   -1    16             0 => {
   -1    17                 player1 = line.unwrap()[28..].parse::<u64>().unwrap();
   -1    18                 state = 1;
   -1    19             },
   -1    20             1 => {
   -1    21                 player2 = line.unwrap()[28..].parse::<u64>().unwrap();
   -1    22                 state = 2;
   -1    23             },
   -1    24             _ => unreachable!(),
   -1    25         }
   -1    26     }
   -1    27 
   -1    28     return (player1, player2);
   -1    29 }
   -1    30 
   -1    31 fn main() {
   -1    32     let (mut player1, mut player2) = get_data();
   -1    33 
   -1    34     let mut die: u64 = 0;
   -1    35     let mut score1: u64 = 0;
   -1    36     let mut score2: u64 = 0;
   -1    37 
   -1    38     loop {
   -1    39         let d1 = 3 * (die % 100) + 6;
   -1    40         player1 = (player1 + d1 - 1) % 10 + 1;
   -1    41         score1 += player1;
   -1    42         die += 3;
   -1    43         if score1 >= 1000 {
   -1    44             println!("{}", score2 * die);
   -1    45             break;
   -1    46         }
   -1    47 
   -1    48         let d2 = 3 * (die % 100) + 6;
   -1    49         player2 = (player2 + d2 - 1) % 10 + 1;
   -1    50         score2 += player2;
   -1    51         die += 3;
   -1    52         if score2 >= 1000 {
   -1    53             println!("{}", score1 * die);
   -1    54             break;
   -1    55         }
   -1    56     }
   -1    57 }

diff --git a/2021/21/part2.rs b/2021/21/part2.rs

@@ -0,0 +1,111 @@
   -1     1 use std::env::args;
   -1     2 use std::fs::File;
   -1     3 use std::io::BufRead;
   -1     4 use std::io::BufReader;
   -1     5 
   -1     6 const TURNS: usize = 11;
   -1     7 
   -1     8 fn get_data() -> (usize, usize) {
   -1     9     let path = args().nth(1).unwrap();
   -1    10     let file = File::open(path).unwrap();
   -1    11 
   -1    12     let mut state = 0;
   -1    13     let mut player1 = 0;
   -1    14     let mut player2 = 0;
   -1    15 
   -1    16     for line in BufReader::new(file).lines() {
   -1    17         match state {
   -1    18             0 => {
   -1    19                 player1 = line.unwrap()[28..].parse::<usize>().unwrap();
   -1    20                 state = 1;
   -1    21             },
   -1    22             1 => {
   -1    23                 player2 = line.unwrap()[28..].parse::<usize>().unwrap();
   -1    24                 state = 2;
   -1    25             },
   -1    26             _ => unreachable!(),
   -1    27         }
   -1    28     }
   -1    29 
   -1    30     return (player1 - 1, player2 - 1);
   -1    31 }
   -1    32 
   -1    33 fn index(turn: usize, score: usize, position: usize) -> usize {
   -1    34     assert!(turn < TURNS);
   -1    35     assert!(score < 21);
   -1    36     assert!(position < 10);
   -1    37 
   -1    38     return turn + score * TURNS + position * TURNS * 21;
   -1    39 }
   -1    40 
   -1    41 fn main() {
   -1    42     let (player1, player2) = get_data();
   -1    43 
   -1    44     let mut counts1 = [0u64; TURNS * 21 * 10];
   -1    45     let mut counts2 = [0u64; TURNS * 21 * 10];
   -1    46     let mut finishes1 = [0u64; TURNS];
   -1    47     let mut finishes2 = [0u64; TURNS];
   -1    48 
   -1    49     counts1[index(0, 0, player1)] += 1;
   -1    50     counts2[index(0, 0, player2)] += 1;
   -1    51 
   -1    52     for turn in 1..TURNS {
   -1    53         for score in 0..21 {
   -1    54             for position in 0..10 {
   -1    55                 if score > position {
   -1    56                     let i = index(turn, score, position);
   -1    57                     let old_score = score - (position + 1);
   -1    58                     for a in [1, 2, 3].iter() {
   -1    59                         for b in [1, 2, 3].iter() {
   -1    60                             for c in [1, 2, 3].iter() {
   -1    61                                 let old_position = (position + 10 - (a + b + c)) % 10;
   -1    62                                 let j = index(turn - 1, old_score, old_position);
   -1    63                                 counts1[i] += counts1[j];
   -1    64                                 counts2[i] += counts2[j];
   -1    65                             }
   -1    66                         }
   -1    67                     }
   -1    68                 }
   -1    69             }
   -1    70         }
   -1    71 
   -1    72         for position in 0..10 {
   -1    73             for old_score in (21 - (position + 1))..21 {
   -1    74                 for a in [1, 2, 3].iter() {
   -1    75                     for b in [1, 2, 3].iter() {
   -1    76                         for c in [1, 2, 3].iter() {
   -1    77                             let old_position = (position + 10 - (a + b + c)) % 10;
   -1    78                             let j = index(turn - 1, old_score, old_position);
   -1    79                             finishes1[turn] += counts1[j];
   -1    80                             finishes2[turn] += counts2[j];
   -1    81                         }
   -1    82                     }
   -1    83                 }
   -1    84             }
   -1    85         }
   -1    86     }
   -1    87 
   -1    88     // the two players can play their games independently and just
   -1    89     // multiply their universes in the end
   -1    90     let mut open1: u64 = 1;
   -1    91     let mut wins1: u64 = 0;
   -1    92 
   -1    93     let mut open2: u64 = 1;
   -1    94     let mut wins2: u64 = 0;
   -1    95 
   -1    96     for turn in 1..TURNS {
   -1    97         open1 *= 27;
   -1    98         open1 -= finishes1[turn];
   -1    99         wins1 += finishes1[turn] * open2;
   -1   100 
   -1   101         open2 *= 27;
   -1   102         open2 -= finishes2[turn];
   -1   103         wins2 += finishes2[turn] * open1;
   -1   104     }
   -1   105 
   -1   106     if wins1 > wins2 {
   -1   107         println!("{}", wins1);
   -1   108     } else {
   -1   109         println!("{}", wins2);
   -1   110     }
   -1   111 }

diff --git a/2021/21/test.txt b/2021/21/test.txt

@@ -0,0 +1,2 @@
   -1     1 Player 1 starting position: 4
   -1     2 Player 2 starting position: 8