diff --git a/src/day14.rs b/src/day14.rs index 60159b7..efb959f 100644 --- a/src/day14.rs +++ b/src/day14.rs @@ -1,5 +1,9 @@ +use std::collections::hash_map::DefaultHasher; +use std::collections::{HashMap, HashSet}; +use std::hash::Hash; use std::time::Instant; use itertools::Itertools; +use std::hash::Hasher; enum Direction{ North, @@ -12,7 +16,7 @@ pub fn execute_task01(content: &str) { let gravity_1 = solve_01(content).unwrap(); let duration = start.elapsed(); - //assert_eq!(10165598, gravity_1); + assert_eq!(108955, gravity_1); println!("Day14 - Task01 - Duration: {duration:?} - One time gravity: {}", gravity_1) } @@ -21,31 +25,81 @@ pub fn execute_task02(content: &str) { let gravity_1000000 = solve_02(content).unwrap(); let duration = start.elapsed(); - //assert_eq!(678728808158, gravity_1000000); + assert_eq!(106689, gravity_1000000); println!("Day14 - Task02 - Duration: {duration:?} - 1 Million time gravity: {}", gravity_1000000) } fn solve_01(content: &str) -> anyhow::Result { - let map = content + let mut map = content .lines() .map(|chars| chars.chars().collect_vec()) .collect_vec(); + move_direction(&mut map, Direction::North); - - - todo!() + Ok(map + .iter() + .rev() + .enumerate() + .map(|(i, row)| row.iter().filter(|c| c == &&'O').count() * (i+1)) + .sum()) } fn solve_02(content: &str) -> anyhow::Result { - todo!() + let mut map = content + .lines() + .map(|chars| chars.chars().collect_vec()) + .collect_vec(); + + let mut set: HashMap = HashMap::new(); + let circles = 1_000_000_000; + let mut from = 0; + let mut to = 0; + + for i in 1..=circles { + move_direction(&mut map, Direction::North); + move_direction(&mut map, Direction::West); + move_direction(&mut map, Direction::South); + move_direction(&mut map, Direction::East); + + let hash = calculate_hash(&map); + if let Some(step) = set.get(&hash) { + from = step.clone(); + to = i; + break; + } else { + set.insert(hash, i); + } + } + + let new_start = (circles - to) / (to - from) * (to -from); + + for i in new_start+from+1 ..=circles { + move_direction(&mut map, Direction::North); + move_direction(&mut map, Direction::West); + move_direction(&mut map, Direction::South); + move_direction(&mut map, Direction::East); + } + + Ok(map + .iter() + .rev() + .enumerate() + .map(|(i, row)| row.iter().filter(|c| c == &&'O').count() * (i+1)) + .sum()) } -fn move_direction(map: &Vec>, direction: Direction) { +fn calculate_hash(t: &T) -> u64 { + let mut s = DefaultHasher::new(); + t.hash(&mut s); + s.finish() +} + +fn move_direction(map: &mut Vec>, direction: Direction) { match direction { Direction::North => { - let mut stones = vec![0; map.len()]; + let mut stones = vec![0; map[0].len()]; for row in 0..map.len() { let width = map[row].len(); @@ -53,23 +107,103 @@ fn move_direction(map: &Vec>, direction: Direction) { let char = map[row][col].clone(); match char { - '0' => { - if stones[col] != row - 1 { - + 'O' => { + if row > 0 && stones[col] != row { + map[stones[col]][col] = 'O'; + map[row][col] = '.'; + stones[col] += 1; + } else { + stones[col] = row +1; } }, - '#' => stones[col] = row, + '#' => stones[col] = row + 1, + '.' => (), + _ => unreachable!() + }; + } + } + } + Direction::South => { + let mut stones = vec![map.len() - 1; map[0].len()]; + + for i in 0..map.len() { + let row = map.len() -1 - i; + let width = map[row].len(); + for col in 0..width { + let char = map[row][col].clone(); + + match char { + 'O' => { + if stones[col] != row { + map[stones[col]][col] = 'O'; + map[row][col] = '.'; + stones[col] -= 1; + } else if row > 0 { + stones[col] = row - 1; + } + }, + '#' => if row > 0 { stones[col] = row - 1 }, + '.' => (), + _ => unreachable!() + }; + } + } + } + Direction::West => { + let width = map[0].len(); + let height = map.len(); + + let mut stones = vec![0; height]; + + for col in 0..width { + for row in 0..height { + let char = map[row][col].clone(); + + match char { + 'O' => { + if col > 0 && stones[row] != col { + map[row][stones[row]] = 'O'; + map[row][col] = '.'; + stones[row] += 1; + } else { + stones[row] = col + 1; + } + }, + '#' => stones[row] = col + 1, + '.' => (), + _ => unreachable!() + }; + } + } + } + Direction::East => { + let width = map[0].len(); + let height = map.len(); + + let mut stones = vec![width - 1; height]; + + for i in 0..width { + let col = width - 1 - i; + for row in 0..height { + let char = map[row][col].clone(); + + match char { + 'O' => { + if stones[row] != col { + map[row][stones[row]] = 'O'; + map[row][col] = '.'; + stones[row] -= 1; + } else if col > 0 { + stones[row] = col - 1; + } + }, + '#' => if col > 0 { stones[row] = col - 1 }, '.' => (), _ => unreachable!() }; } } - - } - Direction::South => {} - Direction::East => {} - Direction::West => {} } } @@ -94,18 +228,18 @@ O.#..O.#.# #[test] fn test_solve_02() { - let example = r#"...#...... -.......#.. -#......... -.......... -......#... -.#........ -.........# -.......... -.......#.. -#...#....."#; + let example = r#"O....#.... +O.OO#....# +.....##... +OO.#O....O +.O.....O#. +O.#..O.#.# +..O..#O..O +.......O.. +#....###.. +#OO..#...."#; let result = solve_02(example).unwrap(); - assert_eq!(1030, result); + assert_eq!(64, result); } diff --git a/src/day15.rs b/src/day15.rs index 1a3e2e1..14d6fe5 100644 --- a/src/day15.rs +++ b/src/day15.rs @@ -1,6 +1,4 @@ -use std::hash::Hash; use std::time::Instant; -use itertools::Itertools; #[derive(Debug, Clone)] struct Lens { @@ -51,7 +49,7 @@ fn solve_02(content: &str) -> anyhow::Result { hash: hash_string(label), value: num.parse().unwrap(), }; - let mut lable_box = &mut boxes[lens.hash as usize]; + let lable_box = &mut boxes[lens.hash as usize]; if let Some(item) = lable_box.iter_mut().filter(|box_lens| box_lens.label == lens.label).next() { // already exists item.value = lens.value @@ -62,7 +60,7 @@ fn solve_02(content: &str) -> anyhow::Result { } else { // is dash (-) let label = part.replace("-", ""); let hash = hash_string(label.as_str()); - let mut lable_box= &mut boxes[hash as usize]; + let lable_box= &mut boxes[hash as usize]; for i in 0..lable_box.len() { let lens = &lable_box[i]; diff --git a/src/main.rs b/src/main.rs index f87e584..a6239ac 100644 --- a/src/main.rs +++ b/src/main.rs @@ -61,6 +61,9 @@ fn main() { day11::execute_task01(CONTENT11); day11::execute_task02(CONTENT11); println!(); + day14::execute_task01(CONTENT14); + day14::execute_task02(CONTENT14); + println!(); day15::execute_task01(CONTENT15); day15::execute_task02(CONTENT15); }