diff --git a/2020/Cargo.toml b/2020/Cargo.toml index be21b76..9b5446c 100644 --- a/2020/Cargo.toml +++ b/2020/Cargo.toml @@ -7,6 +7,7 @@ edition = "2018" [dependencies] clap = "3.0.0-beta.2" itertools = "0.9" +num-integer = "0.1" regex = "1" [profile.release] diff --git a/2020/inputs/13.txt b/2020/inputs/13.txt new file mode 100644 index 0000000..c16c8bb --- /dev/null +++ b/2020/inputs/13.txt @@ -0,0 +1,2 @@ +1001612 +19,x,x,x,x,x,x,x,x,41,x,x,x,37,x,x,x,x,x,821,x,x,x,x,x,x,x,x,x,x,x,x,13,x,x,x,17,x,x,x,x,x,x,x,x,x,x,x,29,x,463,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,23 diff --git a/2020/samples/13.txt b/2020/samples/13.txt new file mode 100644 index 0000000..e473080 --- /dev/null +++ b/2020/samples/13.txt @@ -0,0 +1,2 @@ +939 +7,13,x,x,59,x,31,19 \ No newline at end of file diff --git a/2020/src/common.rs b/2020/src/common.rs index 68265ec..b0a4518 100644 --- a/2020/src/common.rs +++ b/2020/src/common.rs @@ -40,6 +40,21 @@ pub fn read_char_grid(input: &mut dyn Read) -> Vec> { .collect() } +pub fn numbers_and_stuff(input: &mut dyn Read) -> C +where + T: FromStr, + C: FromIterator, +{ + let mut buffer = String::new(); + + input.read_to_string(&mut buffer).unwrap(); + + buffer + .split(|c: char| !c.is_ascii_digit()) + .filter_map(|t| t.parse().ok()) + .collect() +} + /// An interface to count elements in particular categories. pub trait GroupingCount { /// The type of the categories under inspection diff --git a/2020/src/day13.rs b/2020/src/day13.rs index b841970..0b4e0ac 100644 --- a/2020/src/day13.rs +++ b/2020/src/day13.rs @@ -1,12 +1,69 @@ use std::io::Read; +use num_integer::Integer; + +use crate::common::numbers_and_stuff; +use crate::common::Lines; use crate::Solution; #[derive(Default)] pub struct Day13; impl Solution for Day13 { - fn part1(&mut self, _input: &mut dyn Read) -> String { - todo!() + fn part1(&mut self, input: &mut dyn Read) -> String { + let numbers: Vec = numbers_and_stuff(input); + + let departure = numbers[0]; + + let (wait, id) = numbers[1..] + .iter() + .map(|&interval| (interval - (departure % interval), interval)) + .min() + .unwrap(); + + (wait * id).to_string() + } + + fn part2(&mut self, input: &mut dyn Read) -> String { + let line = Lines::new(input).nth(1).unwrap(); + + let mut period = 1; + let mut wait = 0; + + for (offset, freq) in line + .split(',') + .enumerate() + .filter_map(|(i, s)| s.parse().ok().map(|n| (i as u64, n))) + { + let offset = (freq - (offset % freq)) % freq; + + // Modular integer division does this faster but this works. + while wait % freq != offset { + wait += period; + } + + period = period.lcm(&freq); + } + + wait.to_string() + } +} + +#[cfg(test)] +mod tests { + use crate::test_implementation; + + use super::*; + + const SAMPLE: &[u8] = include_bytes!("../samples/13.txt"); + + #[test] + fn sample_part1() { + test_implementation!(Day13, 1, SAMPLE, 295); + } + + #[test] + fn sample_part2() { + test_implementation!(Day13, 2, SAMPLE, 1068781); } }