diff --git a/rust/src/main.rs b/rust/src/main.rs index 944366c..8521e2a 100644 --- a/rust/src/main.rs +++ b/rust/src/main.rs @@ -263,8 +263,131 @@ mod day05 { } } +mod day06 { + use std::time::Duration; + + pub fn run(_: bool) -> Duration { + Duration::new(0, 0) + } +} + +mod day07 { + use std::time::Duration; + + pub fn run(_: bool) -> Duration { + Duration::new(0, 0) + } +} + +mod day08 { + use std::{ + collections::HashSet, + time::{Duration, Instant}, + }; + + #[derive(Debug, Copy, Clone)] + enum Instruction { + Acc(i32), + Jmp(i32), + Nop, + } + + fn part1(instructions: &[Instruction]) -> (i32, Vec) { + let mut accumulator = 0; + let mut pc = 0; + let mut pc_history = HashSet::new(); + let mut jumps = Vec::new(); + + loop { + match instructions[pc as usize] { + Instruction::Acc(i) => accumulator += i, + Instruction::Jmp(i) => { + let target = pc + i - 1; + if !pc_history.insert(target) { + break (accumulator, jumps); + } + + jumps.push(pc); + pc += i - 1 + } + Instruction::Nop => (), + }; + + pc += 1; + } + } + + fn part2(instructions: &[Instruction], skip: i32) -> Option { + let mut accumulator = 0; + let mut pc = 0; + let mut pc_history = HashSet::new(); + + loop { + if pc != skip { + match instructions.get(pc as usize) { + Some(Instruction::Acc(i)) => accumulator += i, + Some(Instruction::Jmp(i)) => { + let target = pc + i; + if !pc_history.insert(target) { + break None; + } + + pc = target - 1; + } + Some(Instruction::Nop) => (), + None => break Some(accumulator), + }; + } + + pc += 1; + } + } + + pub fn run(print: bool) -> Duration { + let input = std::fs::read_to_string("inputs/day08").unwrap(); + let instant = Instant::now(); + + let instructions: Vec<_> = input + .lines() + .map(|line| { + let operation = &line[0..3]; + let value: i32 = line[4..].parse().unwrap(); + match operation { + "acc" => Instruction::Acc(value), + "jmp" => Instruction::Jmp(value), + "nop" => Instruction::Nop, + _ => unreachable!(operation), + } + }) + .collect(); + + let (part1, jumps) = part1(&instructions); + + let part2 = jumps + .iter() + .rev() + .find_map(|skip_pc| part2(&instructions, *skip_pc)) + .unwrap(); + + let elapsed = instant.elapsed(); + if print { + dbg!(elapsed, part1, part2); + } + elapsed + } +} + fn main() { - let days = [day01::run, day02::run, day03::run, day04::run, day05::run]; + let days = [ + day01::run, + day02::run, + day03::run, + day04::run, + day05::run, + day06::run, + day07::run, + day08::run, + ]; if let Some(day) = std::env::args().nth(1) { let day: usize = day.parse().expect("day not an integer"); @@ -276,11 +399,15 @@ fn main() { let mut total = Duration::new(0, 0); for day in 0..days.len() { + let mut elapsed = Duration::new(0, 0); for _ in 0..repetitions { - total += days[day](false) / repetitions; + elapsed += days[day](false) / repetitions; } + println!("Day {:>2}: {:?}", day + 1, elapsed); + total += elapsed; } - dbg!(total); + println!("-------------------"); + println!("Total: {:?}", total); } }