From 4c928e06ac138929d43efde19485630b305bbcef Mon Sep 17 00:00:00 2001 From: Antoine Martin Date: Sun, 13 Dec 2020 17:28:29 +0100 Subject: [PATCH] 2020: day13: part 2 --- aoc2020/src/day13.rs | 59 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/aoc2020/src/day13.rs b/aoc2020/src/day13.rs index 020b7c9..2dc7b8e 100644 --- a/aoc2020/src/day13.rs +++ b/aoc2020/src/day13.rs @@ -3,11 +3,13 @@ use std::fmt::Write; use aoc::err; const INPUT: &str = include_str!("../input/day13.txt"); +const PROVIDED: &str = include_str!("../input/day13_provided.txt"); pub fn run() -> aoc::Result { let mut res = String::with_capacity(128); writeln!(res, "part 1: {}", part1(INPUT)?)?; + writeln!(res, "part 2: {}", part2(INPUT)?)?; Ok(res) } @@ -46,12 +48,55 @@ fn part1(input: &str) -> aoc::Result { Ok(bus_id * (earliest_departure - earliest_timestamp)) } +fn part2(input: &str) -> aoc::Result { + let mut lines = input.lines(); + + // we don't need the first line anymore, skip it + lines.next().ok_or_else(|| err!("input was empty"))?; + + let bus_ids: Vec<(u64, u64)> = lines + .next() + .ok_or_else(|| err!("no second line"))? + .split(',') + .enumerate() + .filter_map(|(idx, num)| { + if num == "x" { + None + } else { + Some((idx as u64, num.parse::().map_err(|e| err!("{}", e)))) + } + }) + .map(|(idx, res)| match res { + Ok(num) => Ok((idx, num)), + Err(e) => Err(e), + }) + .collect::>()?; + + // previous constraints is empty for now + let mut current_solution = 0; + let mut step = 1; + + for constraint in bus_ids { + while !satisfies_constraint(current_solution, constraint) { + current_solution += step; + } + + let (_, divisor) = constraint; + + step *= divisor; + } + + Ok(current_solution) +} + +fn satisfies_constraint(solution: u64, (remainder, divisor): (u64, u64)) -> bool { + ((solution + remainder) % divisor) == 0 +} + #[cfg(test)] mod tests { use super::*; - const PROVIDED: &str = include_str!("../input/day13_provided.txt"); - #[test] fn part1_provided() { assert_eq!(part1(PROVIDED).unwrap(), 295); @@ -61,4 +106,14 @@ mod tests { fn part1_real() { assert_eq!(part1(INPUT).unwrap(), 3269); } + + #[test] + fn part2_provided() { + assert_eq!(part2(PROVIDED).unwrap(), 1068781); + } + + #[test] + fn part2_real() { + assert_eq!(part2(INPUT).unwrap(), 672754131923874); + } }