diff --git a/inputs/day13.txt b/inputs/day13.txt new file mode 100644 index 0000000..3d3e1d3 --- /dev/null +++ b/inputs/day13.txt @@ -0,0 +1,2 @@ +1007153 +29,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,37,x,x,x,x,x,433,x,x,x,x,x,x,x,x,x,x,x,x,13,17,x,x,x,x,19,x,x,x,23,x,x,x,x,x,x,x,977,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,x,41 diff --git a/inputs/day13_test.txt b/inputs/day13_test.txt new file mode 100644 index 0000000..e473080 --- /dev/null +++ b/inputs/day13_test.txt @@ -0,0 +1,2 @@ +939 +7,13,x,x,59,x,31,19 \ No newline at end of file diff --git a/src/bin/bus.rs b/src/bin/bus.rs new file mode 100644 index 0000000..7f1dcb1 --- /dev/null +++ b/src/bin/bus.rs @@ -0,0 +1,101 @@ +use advent2020::errors::TopLevelError; +use std::env; +use std::fs; +use std::str::FromStr; + +fn find_pattern(busses: &[(usize, usize)]) -> Result { + if busses.is_empty() { + return Err(TopLevelError::NoInputFound); + } + + let mut t = 1; + let mut increment = 1; + + for (offset, factor) in busses { + while (t + offset) % factor != 0 { + t += increment; + } + increment = lcm(increment, *factor); + } + + Ok(t) +} + +fn lcm(x: usize, y: usize) -> usize { + let mut k = x; + + while k % y != 0 { + k += x; + } + + k +} + +#[test] +fn lcm_test() { + assert_eq!(9, lcm(3, 9)); + assert_eq!(12, lcm(3, 4)); + assert_eq!(60, lcm(15, 20)); + assert_eq!(7, lcm(1, 7)); + assert_eq!(7, lcm(7, 1)); +} + +#[test] +fn pattern_examples() { + assert_eq!( + 1068781, + find_pattern(&[(0, 7), (1, 13), (4, 59), (6, 31), (7, 19)]).unwrap() + ); + assert_eq!(3417, find_pattern(&[(0, 17), (2, 13), (3, 19)]).unwrap()); + assert_eq!( + 754018, + find_pattern(&[(0, 67), (1, 7), (2, 59), (3, 61)]).unwrap() + ); + assert_eq!( + 779210, + find_pattern(&[(0, 67), (2, 7), (3, 59), (4, 61)]).unwrap() + ); + assert_eq!( + 1261476, + find_pattern(&[(0, 67), (1, 7), (3, 59), (4, 61)]).unwrap() + ); + assert_eq!( + 1202161486, + find_pattern(&[(0, 1789), (1, 37), (2, 47), (3, 1889)]).unwrap() + ); +} + +fn main() -> Result<(), TopLevelError> { + let filename = env::args().nth(1).expect("No file argument given."); + let contents = fs::read_to_string(filename)?; + let mut lines = contents.lines(); + let start_time = usize::from_str(lines.next().ok_or(TopLevelError::NoInputFound)?)?; + let bus_notes = lines.next().ok_or(TopLevelError::NoInputFound)?; + let mut busses = Vec::new(); + + for (idx, bus) in bus_notes.split(',').enumerate() { + match usize::from_str(bus) { + Err(_) if bus == "x" => {} + Err(e) => return Err(TopLevelError::NumConversionError(e)), + Ok(x) => busses.push((idx, x)), + } + } + + let (next_bus, when) = busses + .iter() + .map(|(_, x)| (x, x - (start_time % x))) + .min_by(|(_, a), (_, b)| a.cmp(b)) + .ok_or(TopLevelError::NoSolutionFound)?; + println!( + "The next #{} bus is in {} minutes. [{}]", + next_bus, + when, + next_bus * when + ); + println!( + "The pattern you're looking for starts at {}", + find_pattern(&busses)? + ); + + Ok(()) +}