use std::fs; #[derive(Clone, Debug)] struct Disc { pos: usize, period: usize, } fn parse(lines: Vec<&str>) -> Vec { let mut result = Vec::new(); // Add a dummy 0th disc for slightly cleaner code later result.push(Disc { pos: 0, period: 1 }); for line in lines { let words: Vec<&str> = line.split_ascii_whitespace().collect(); result.push(Disc { pos: words[11].trim_end_matches('.').parse().unwrap(), period: words[3].parse().unwrap(), }); } result } fn solve_puzzle(discs: &Vec) -> usize { let mut t_start = 0; 'outer: loop { let mut dt = 1; while dt < discs.len() { // Calculate the disc's current position. If 0, the capsule // can continue, otherwise this `t_start' must be rejected. if (discs[dt].pos + t_start + dt) % discs[dt].period != 0 { t_start += 1; continue 'outer; } dt += 1; } return t_start; } } fn main() { // Read disc stats from input text file let input = fs::read_to_string("input.txt").unwrap(); let lines = input.lines().collect(); let mut discs = parse(lines); // Part 1 gives 203660 for me println!("Part 1 solution: {}", solve_puzzle(&discs)); discs.push(Disc { pos: 0, period: 11 }); // Part 2 gives 2408135 for me println!("Part 2 solution: {}", solve_puzzle(&discs)); } #[cfg(test)] mod tests { use super::*; #[test] fn part1_example1() { let lines = vec![ "Disc #1 has 5 positions; at time=0, it is at position 4.", "Disc #2 has 2 positions; at time=0, it is at position 1.", ]; let discs = parse(lines); assert_eq!(solve_puzzle(&discs), 5); } }