diff --git a/src/days/d06.rs b/src/days/d06.rs index 3031890..9865ce3 100644 --- a/src/days/d06.rs +++ b/src/days/d06.rs @@ -1,7 +1,14 @@ -use std::fs; +use std::{ + collections::{HashMap, HashSet}, + fs, +}; + +use rayon::iter::{ + IndexedParallelIterator, IntoParallelRefIterator, ParallelBridge, ParallelIterator, +}; pub fn solve() { - let path = "res/06/example"; + let path = "res/06/input"; let contents = fs::read_to_string(path).expect("Something went wrong reading the file"); @@ -17,22 +24,117 @@ pub fn solve() { }) .collect(); - let mut pos: (usize, usize) = contents + let init_pos: (isize, isize) = contents .lines() .enumerate() .find(|(_, line)| line.contains("^")) - .map(|(x, line)| (x, line.chars().position(|c| c == '^').unwrap())) + .map(|(x, line)| { + ( + x as isize, + line.chars().position(|c| c == '^').unwrap() as isize, + ) + }) .unwrap(); + let mut pos = init_pos; let mut dir: (isize, isize) = (-1, 0); - let mut guard_positions: Vec<(usize, usize)> = vec![]; + let mut guard_positions: HashSet<(isize, isize)> = HashSet::new(); // let the guard move until he leaves the map + while pos.0 >= 0 && pos.0 < map.len() as isize && pos.1 >= 0 && pos.1 < map[0].len() as isize { + // check if we need to turn right + if map[pos.0 as usize][pos.1 as usize] { + pos.0 = pos.0 - dir.0; + pos.1 = pos.1 - dir.1; + dir = match dir { + (-1, 0) => (0, 1), + (0, 1) => (1, 0), + (1, 0) => (0, -1), + (0, -1) => (-1, 0), + _ => panic!(), + }; + } - let result: usize = 0; + // add guard position + guard_positions.insert(pos); + // move guard + pos.0 += dir.0; + pos.1 += dir.1; + } + + let result: usize = guard_positions.len(); println!("Result 1: {}", result); + let mut obstacle_positions: HashSet<(isize, isize)> = HashSet::new(); + + let obstacle_positions: Vec> = map + .iter() + .enumerate() + .par_bridge() + .map(|(i, row)| { + row.iter() + .enumerate() + .filter(|(j, cell)| { + if !*cell && (i as isize, *j as isize) != init_pos { + let mut new_map = map.clone(); + new_map[i][*j] = true; + + let mut dir: (isize, isize) = (-1, 0); + let mut pos = init_pos; + + let mut positions: HashMap<(isize, isize), usize> = HashMap::new(); + let mut cyclic = false; + + while pos.0 >= 0 + && pos.0 < map.len() as isize + && pos.1 >= 0 + && pos.1 < map[0].len() as isize + { + // check if we need to turn right + if new_map[pos.0 as usize][pos.1 as usize] { + pos.0 = pos.0 - dir.0; + pos.1 = pos.1 - dir.1; + dir = match dir { + (-1, 0) => (0, 1), + (0, 1) => (1, 0), + (1, 0) => (0, -1), + (0, -1) => (-1, 0), + _ => panic!(), + }; + } + + // move guard + pos.0 += dir.0; + pos.1 += dir.1; + + if positions.contains_key(&pos) { + *positions.get_mut(&pos).unwrap() += 1; + } else { + positions.insert(pos, 1); + } + + if *positions.get(&pos).unwrap() == 5 { + cyclic = true; + break; + } + } + if cyclic { + return true; + } + } + false + }) + .map(|(j, _)| (i as isize, j as isize)) + .collect() + }) + .collect(); + + let obstacle_positions: HashSet<(isize, isize)> = + obstacle_positions.into_iter().flatten().collect(); + + let result: usize = obstacle_positions.len(); + println!("Result 2: {}", result); }