1
0

feat: solve day 21 part 1 & 2

This commit is contained in:
Rokas Puzonas 2022-01-23 15:55:45 +02:00
parent 4db9c115f6
commit c59575aa99
3 changed files with 102 additions and 0 deletions

2
input/21.txt Normal file
View File

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

97
src/day21.rs Normal file
View File

@ -0,0 +1,97 @@
use std::collections::HashMap;
pub fn parse_input(input: &str) -> (u8, u8) {
let players: Vec<u8> = input.lines()
.map(|l| l.split_once(": ").unwrap().1.parse().unwrap())
.collect();
return (players[0], players[1]);
}
pub fn part1(starting_positions: &(u8, u8)) -> u32 {
let mut player1_position = starting_positions.0 as u32;
let mut player2_position = starting_positions.1 as u32;
let mut player1_score: u32 = 0;
let mut player2_score: u32 = 0;
let mut rolled_count = 0;
let mut is_player1_turn = true;
while player1_score < 1000 && player2_score < 1000 {
let position;
let score;
if is_player1_turn {
position = &mut player1_position;
score = &mut player1_score;
} else {
position = &mut player2_position;
score = &mut player2_score;
}
*position += (rolled_count + 1 - 1) % 100 + 1;
*position += (rolled_count + 2 - 1) % 100 + 1;
*position += (rolled_count + 3 - 1) % 100 + 1;
*position = (*position - 1) % 10 + 1;
*score += *position as u32;
rolled_count += 3;
is_player1_turn = !is_player1_turn;
}
player1_score.min(player2_score) * rolled_count as u32
}
fn get_wins_amount(starting_pos1: u32, starting_pos2: u32, starting_score1: u32, starting_score2: u32, memo: &mut HashMap<(u32, u32, u32, u32), (u64, u64)>) -> (u64, u64) {
let memo_key = (starting_pos1, starting_pos2, starting_score1, starting_score2);
if memo.contains_key(&memo_key) {
return *memo.get(&memo_key).unwrap()
}
let mut total_wins1 = 0;
let mut total_wins2 = 0;
for dice1 in 1..=3 {
for dice2 in 1..=3 {
for dice3 in 1..=3 {
let pos1 = (starting_pos1 + dice1 + dice2 + dice3 - 1) % 10 + 1;
let score1 = starting_score1 + pos1;
if score1 >= 21 {
total_wins1 += 1
} else {
let (wins2, wins1) = get_wins_amount(starting_pos2, pos1, starting_score2, score1, memo);
total_wins1 += wins1;
total_wins2 += wins2;
}
}
}
}
memo.insert(memo_key, (total_wins1, total_wins2));
(total_wins1, total_wins2)
}
pub fn part2(positions: &(u8, u8)) -> u64 {
let mut memo = HashMap::new();
let (wins1, wins2) = get_wins_amount(positions.0 as u32, positions.1 as u32, 0, 0, &mut memo);
wins1.max(wins2)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn part1_example() {
let input = (4, 8);
let result = part1(&input);
assert_eq!(result, 739785);
}
#[test]
fn part2_example() {
let input = (4, 8);
let result = part2(&input);
assert_eq!(result, 444356092776315);
}
}

View File

@ -18,6 +18,7 @@ mod day17;
mod day18;
mod day19;
mod day20;
mod day21;
use std::{env, process};
use std::fs::File;
@ -74,6 +75,8 @@ fn run(day: i32, part: i32, input_filename: &str) {
"19.2" => println!("{}", day19::part2(&day19::parse_input(&contents))),
"20.1" => println!("{}", day20::part1(&day20::parse_input(&contents))),
"20.2" => println!("{}", day20::part2(&day20::parse_input(&contents))),
"21.1" => println!("{}", day21::part1(&day21::parse_input(&contents))),
"21.2" => println!("{}", day21::part2(&day21::parse_input(&contents))),
_ => println!("Day {} part {} not found", day, part)
}
}