feat: implement day14

This commit is contained in:
Lennard Brinkhaus 2023-12-16 18:14:25 +01:00
parent b8ab75d049
commit 3dc1cddf07
3 changed files with 168 additions and 33 deletions

View File

@ -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<usize> {
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<usize> {
todo!()
let mut map = content
.lines()
.map(|chars| chars.chars().collect_vec())
.collect_vec();
let mut set: HashMap<u64, i32> = 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);
}
}
fn move_direction(map: &Vec<Vec<char>>, direction: Direction) {
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 calculate_hash<T: Hash>(t: &T) -> u64 {
let mut s = DefaultHasher::new();
t.hash(&mut s);
s.finish()
}
fn move_direction(map: &mut Vec<Vec<char>>, 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<Vec<char>>, 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);
}

View File

@ -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<usize> {
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<usize> {
} 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];

View File

@ -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);
}