From 054ea0a2e32f20b2612758d040a18cea44657830 Mon Sep 17 00:00:00 2001 From: shoofle Date: Fri, 6 Dec 2024 09:15:52 -0500 Subject: [PATCH] days 5 and 6 --- day05/src/main.rs | 8 +-- day06/src/main.rs | 162 +++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 162 insertions(+), 8 deletions(-) diff --git a/day05/src/main.rs b/day05/src/main.rs index 0d0ed27..1db230b 100644 --- a/day05/src/main.rs +++ b/day05/src/main.rs @@ -48,7 +48,8 @@ fn main() { .filter(|p| pages.contains(p)) .collect(); - let middle: i32 = *halfway(&true_pages).expect("error finding the halfway point"); + let middle: i32 = true_pages.get((true_pages.len() - 1) / 2) + .expect("error finding the halfway point"); if iter::zip(pages.iter(), true_pages.iter()).all(|(a, b)| a==b) { // it's good! @@ -62,9 +63,4 @@ fn main() { println!("the sum of middle pages of good updates is {good_sum}"); println!("and the bad updates is {bad_sum}"); -} - -fn halfway(v: &[T]) -> Option<&T> { - if v.len() == 0 { return None; } - return v.get((v.len() - 1) / 2) } \ No newline at end of file diff --git a/day06/src/main.rs b/day06/src/main.rs index e7a11a9..fb45607 100644 --- a/day06/src/main.rs +++ b/day06/src/main.rs @@ -1,3 +1,161 @@ -fn main() { - println!("Hello, world!"); +use std::collections::HashSet; +use std::collections::HashMap; +use std::fs; +use std::env; +use crate::Dir::{North, South, East, West}; + +// nodes are (coord, direction) pairs. +// neighbors are step1+turnleft, step2+turnleft, step3+turnleft, step1+turnright, etc +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +enum Dir { North, South, East, West } + +fn step(start: &Coord, d: Dir, steps: i32) -> Coord { + match d { + North => (start.0, start.1 - steps), + South => (start.0, start.1 + steps), + East => (start.0 + steps, start.1), + West => (start.0 - steps, start.1) + } } + +fn rotate_right(direction: Dir) -> Dir { + match direction { + North => East, + East => South, + South => West, + West => North + } +} + +type Coord = (i32, i32); + +fn main() { + println!("Hello, AoC day 06!"); + + let args: Vec = env::args().collect(); + if args.len() != 2 { + println!("wrong number of arguments!"); + std::process::exit(1); + } + + let file_path = &args[1]; + + let contents = fs::read_to_string(file_path).expect("Should have been able to read the file"); + let mut grid: HashMap = HashMap::new(); + + let mut guard_position = (0,0); + let mut x; + let mut y = 0; + // build our grid! + for line in contents.lines() { + x = 0; + for c in line.chars() { + if c == '^' { + guard_position = (x,y); + grid.insert((x,y), '.'); + x += 1; + } else { + grid.insert((x,y), c); + x += 1; + } + } + y += 1; + } + + if let Ok(count) = patrol(guard_position, &grid) { + println!("visited {count} locations!"); + } else { + println!("found a loop!"); + } + + if let Ok(potential_loops) = patrol_and_count_potential_loops(guard_position, &grid) { + println!("there were {potential_loops} locations where we could make a loop.") + } +} + +struct Looped; +fn patrol(start: Coord, lab: &HashMap) -> Result { + let mut guard_position = start; + let mut guard_facing = North; + + let mut visited: HashSet = HashSet::new(); + let mut conditions: HashSet<(Coord, Dir)> = HashSet::new(); + loop { + visited.insert(guard_position); + if conditions.contains(&(guard_position, guard_facing)) { + return Err(Looped); + } + conditions.insert((guard_position, guard_facing)); + let next = step(&guard_position, guard_facing, 1); + match lab.get(&next) { + Some('.') => guard_position = next, + Some('#') => guard_facing = rotate_right(guard_facing), + Some(_) => panic!("encountered an unexpected character!"), + None => break, + } + } + + return Ok(visited.len()); +} + +fn patrol_and_count_potential_loops(start: Coord, lab: &HashMap) -> Result { + let mut guard_position = start; + let mut guard_facing = North; + + let mut candidates: HashSet = HashSet::new(); + let mut conditions: HashSet<(Coord, Dir)> = HashSet::new(); + loop { + if conditions.contains(&(guard_position, guard_facing)) { + return Err(Looped); + } + + conditions.insert((guard_position, guard_facing)); + + let next = step(&guard_position, guard_facing, 1); + + if obstacle_to_the_right(guard_position, guard_facing, lab) { + candidates.insert(next); + } + + match lab.get(&next) { + Some('.') => guard_position = next, + Some('#') => guard_facing = rotate_right(guard_facing), + Some(_) => panic!("encountered an unexpected character!"), + None => break, + } + } + + let mut loop_spots: HashSet = HashSet::new(); + for candidate_location in candidates { + let mut dream_lab = lab.clone(); + + if dream_lab.get(&candidate_location) != Some(&'.') { + continue; + } + + dream_lab.insert(candidate_location, '#'); + + if let Ok(_) = patrol(start, &dream_lab){ + continue; + } + + loop_spots.insert(candidate_location); + } + + return Ok(loop_spots.len()); +} + +fn obstacle_to_the_right(start: Coord, facing: Dir, lab: &HashMap) -> bool { + let direction = rotate_right(facing); + + let mut position = start; + while let Some(next) = lab.get(&position) { + if *next == '.' { + position = step(&position, direction, 1); + } else if *next == '#' { + return true; + } + } + + return false; +} \ No newline at end of file