Advent of Code solutions in Rust

feat: part 1 of day 13 of AoC 2020

+93 -2
+91
aoc_2020/src/day13.rs
··· 1 + use anyhow::{Context, anyhow, bail}; 2 + use aoc_companion::prelude::*; 3 + use itertools::Itertools as _; 4 + use std::str::FromStr; 5 + 6 + pub(crate) struct Door { 7 + arrival_time: u64, 8 + bus_schedule: Vec<BusLine>, 9 + } 10 + 11 + impl<'input> Solution<'input> for Door { 12 + fn parse(input: &'input str) -> Result<Self> { 13 + let Some((arrival_line, buses_line)) = input.split_once('\n') else { 14 + bail!( 15 + "expected exactly two lines, got {} lines", 16 + input.lines().count() 17 + ) 18 + }; 19 + 20 + Ok(Self { 21 + arrival_time: arrival_line.parse().context("invalid arrival time")?, 22 + bus_schedule: buses_line.split(',').map(str::parse).try_collect()?, 23 + }) 24 + } 25 + 26 + fn part1(&self) -> Result<u64> { 27 + earliest_departure(self.arrival_time, &self.bus_schedule) 28 + .ok_or_else(|| anyhow!("no buses scheduled")) 29 + } 30 + } 31 + 32 + enum BusLine { 33 + BusId(u64), 34 + Omission, 35 + } 36 + 37 + impl FromStr for BusLine { 38 + type Err = anyhow::Error; 39 + 40 + fn from_str(s: &str) -> Result<Self> { 41 + Ok(match s { 42 + "x" => BusLine::Omission, 43 + _ => BusLine::BusId( 44 + s.parse() 45 + .context("bus line must be either 'x' or a positive number")?, 46 + ), 47 + }) 48 + } 49 + } 50 + 51 + impl BusLine { 52 + fn id(&self) -> Option<u64> { 53 + match self { 54 + BusLine::BusId(id) => Some(*id), 55 + BusLine::Omission => None, 56 + } 57 + } 58 + } 59 + 60 + fn earliest_departure(arrival: u64, schedule: &[BusLine]) -> Option<u64> { 61 + schedule 62 + .iter() 63 + .filter_map(|bus| bus.id()) 64 + .min_by_key(|id| id - arrival % id) 65 + .map(|min_id| min_id * (min_id - arrival % min_id)) 66 + } 67 + 68 + #[cfg(test)] 69 + mod tests { 70 + use super::*; 71 + 72 + const EXAMPLE_ARRIVAL: u64 = 939; 73 + const EXAMPLE_SCHEDULE: [BusLine; 8] = [ 74 + BusLine::BusId(7), 75 + BusLine::BusId(13), 76 + BusLine::Omission, 77 + BusLine::Omission, 78 + BusLine::BusId(59), 79 + BusLine::Omission, 80 + BusLine::BusId(31), 81 + BusLine::BusId(19), 82 + ]; 83 + 84 + #[test] 85 + fn find_earliest_bus_in_example() { 86 + assert_eq!( 87 + earliest_departure(EXAMPLE_ARRIVAL, &EXAMPLE_SCHEDULE), 88 + Some(295) 89 + ); 90 + } 91 + }
+2 -2
aoc_2020/src/main.rs
··· 12 12 mod day10; 13 13 mod day11; 14 14 mod day12; 15 - // mod day13; 15 + mod day13; 16 16 // mod day14; 17 17 // mod day15; 18 18 // mod day16; ··· 43 43 door!(2020-12-10 ~> day10), 44 44 door!(2020-12-11 ~> day11), 45 45 door!(2020-12-12 ~> day12), 46 - // door!(2020-12-13 ~> day13), 46 + door!(2020-12-13 ~> day13), 47 47 // door!(2020-12-14 ~> day14), 48 48 // door!(2020-12-15 ~> day15), 49 49 // door!(2020-12-16 ~> day16),