Advent of Code solutions in Rust

feat: part 1 of day 22 of AoC 2020

+105 -2
+103
aoc_2020/src/day22.rs
··· 1 + use std::collections::VecDeque; 2 + 3 + use anyhow::Context as _; 4 + use anyhow::bail; 5 + use aoc_companion::prelude::*; 6 + use itertools::Itertools as _; 7 + 8 + pub(crate) struct Door { 9 + decks: [Vec<u64>; 2], 10 + } 11 + 12 + impl<'input> Solution<'input> for Door { 13 + fn parse(input: &'input str) -> Result<Self> { 14 + let Some((player1, player2)) = input.split_once("\n\n") else { 15 + bail!("missing empty line between player decks"); 16 + }; 17 + let Some(player1) = player1.strip_prefix("Player 1:\n") else { 18 + bail!("missing introducer of player 1's deck"); 19 + }; 20 + let Some(player2) = player2.strip_prefix("Player 2:\n") else { 21 + bail!("missing introducer of player 2's deck"); 22 + }; 23 + aoc_utils::array::try_map([player1, player2], |deck| { 24 + deck.lines() 25 + .map(str::parse) 26 + .try_collect() 27 + .with_context(|| "failed to parse card value") 28 + }) 29 + .map(|decks| Door { decks }) 30 + } 31 + 32 + fn part1(&self) -> u64 { 33 + score(&play_combat( 34 + self.decks.each_ref().map(|deck| deck.clone().into()), 35 + )) 36 + } 37 + } 38 + 39 + fn play_combat(mut decks: [VecDeque<u64>; 2]) -> Vec<u64> { 40 + while let Ok(top_cards) = 41 + aoc_utils::array::try_map(decks.each_mut(), |deck| deck.front().copied().ok_or(())) 42 + { 43 + for deck in &mut decks { 44 + deck.pop_front(); 45 + } 46 + match (top_cards, &mut decks) { 47 + ([high, low], [winner, _]) | ([low, high], [_, winner]) if high > low => { 48 + winner.extend([high, low]); 49 + } 50 + _ => unreachable!("same card value must not occur twice"), 51 + } 52 + } 53 + 54 + let winner = decks.into_iter().max().unwrap(); 55 + winner.into() 56 + } 57 + 58 + fn score(deck: &[u64]) -> u64 { 59 + deck.iter() 60 + .rev() 61 + .enumerate() 62 + .map(|(i, card)| (i as u64 + 1) * card) 63 + .sum() 64 + } 65 + 66 + #[cfg(test)] 67 + mod tests { 68 + use super::*; 69 + 70 + const EXAMPLE_INPUT: &str = "\ 71 + Player 1: 72 + 9 73 + 2 74 + 6 75 + 3 76 + 1 77 + 78 + Player 2: 79 + 5 80 + 8 81 + 4 82 + 7 83 + 10"; 84 + 85 + const EXAMPLE_DECKS: [[u64; 5]; 2] = [[9, 2, 6, 3, 1], [5, 8, 4, 7, 10]]; 86 + const WINNING_DECK: [u64; 10] = [3, 2, 10, 6, 8, 5, 9, 4, 7, 1]; 87 + 88 + #[test] 89 + fn parse_example_input() { 90 + let Door { decks } = Door::parse(EXAMPLE_INPUT).unwrap(); 91 + assert_eq!(decks, EXAMPLE_DECKS); 92 + } 93 + 94 + #[test] 95 + fn winning_deck_in_example() { 96 + assert_eq!(play_combat(EXAMPLE_DECKS.map(VecDeque::from)), WINNING_DECK); 97 + } 98 + 99 + #[test] 100 + fn winning_score() { 101 + assert_eq!(score(&WINNING_DECK), 306); 102 + } 103 + }
+2 -2
aoc_2020/src/main.rs
··· 21 21 mod day19; 22 22 mod day20; 23 23 mod day21; 24 - // mod day22; 24 + mod day22; 25 25 // mod day23; 26 26 // mod day24; 27 27 // mod day25; ··· 52 52 door!(2020-12-19 ~> day19), 53 53 door!(2020-12-20 ~> day20), 54 54 door!(2020-12-21 ~> day21), 55 - // door!(2020-12-22 ~> day22), 55 + door!(2020-12-22 ~> day22), 56 56 // door!(2020-12-23 ~> day23), 57 57 // door!(2020-12-24 ~> day24), 58 58 // door!(2020-12-25 ~> day25),