use crate::prelude::*; pub fn solution() -> Solution { Solution::new(Day::new(13, 2020), part_1, part_2) .with_expected(1895, 840493039281088_i64) } fn part_1(input: &str) -> Result { let mut lines = input.lines(); let target = lines.next().map(str::parse::).unwrap().unwrap(); let busses = lines .next() .unwrap() .split(',') .filter_map(|value| value.parse().ok()) .collect::>(); let mut difference = 0; let mut earliest_bus = 0; let mut minutes = 0; for bus in busses { let rest = target % bus; if minutes < rest { difference = bus - rest; earliest_bus = bus; minutes = rest; } } Ok((earliest_bus * difference).to_string()) } fn part_2(input: &str) -> Result { // Skip the first line, as it isn't used for the second part of the puzzle. let input = input.lines().nth(1).unwrap(); let busses = input .split(',') .enumerate() .filter_map(|(offset, bus)| { if let Ok(bus) = bus.parse() { Some((offset, bus)) } else { None } }) .collect::>(); let mut timestamp = 0; // Start the increment at 1 as we'll be multiplying it with the bus numbers. let mut increment = 1; // Keep track of which busses we've gotten modulo equals 0 from. let mut used_busses = vec![]; 'outer: loop { timestamp += increment; for (offset, bus) in &busses { if (timestamp + offset) % bus != 0 { continue 'outer; } else if !used_busses.contains(&(offset, bus)) { used_busses.push((offset, bus)); increment *= bus; } } break 'outer; } Ok(timestamp.to_string()) }