From 30ef81cfacf5ea7356d8d73d8902c73ef158c506 Mon Sep 17 00:00:00 2001 From: Johannes Date: Sat, 27 May 2023 01:45:15 +0200 Subject: [PATCH] Day 18 part 2 --- src/main.rs | 2 +- src/tasks/day18.rs | 140 ++++++++++++++++++++++++++++++--------------- 2 files changed, 94 insertions(+), 48 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3e50f68..2a0602b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,3 @@ fn main() { - aoc_2018::tasks::day18::task1(); + aoc_2018::tasks::day18::task2(); } diff --git a/src/tasks/day18.rs b/src/tasks/day18.rs index 678a1e8..17efe83 100644 --- a/src/tasks/day18.rs +++ b/src/tasks/day18.rs @@ -5,6 +5,54 @@ use itertools::Itertools; use crate::utils; pub fn task1() { + let initial = load_initial_map(); + let fin = (0..10).fold(initial, |map, _| next_map(map)); + let (trees, lumberyards) = resource_value(fin); + println!("Part 1 - {trees} x {lumberyards} = {}", trees * lumberyards); +} +pub fn task2() { + let mut map = load_initial_map(); + + const MINUTES: i32 = 1000000000; + let mut maps_at_time: HashMap = HashMap::new(); + let mut minute = 0; + while minute < MINUTES { + if let Some(time) = maps_at_time.get(&hash(&map)) { + let delta = minute - time; + let remaining_minutes = MINUTES - minute; + let remaining_cycles = remaining_minutes / delta; + minute += remaining_cycles * delta; + } + maps_at_time.insert(hash(&map), minute); + minute += 1; + map = next_map(map); + } + + let (trees, lumberyards) = resource_value(map); + println!("Part 1 - {trees} x {lumberyards} = {}", trees * lumberyards); +} + +fn hash(map: &HashMap) -> String { + let mut result = String::new(); + let (x_min, x_max) = map.keys().map(|p| p.0).minmax().into_option().unwrap(); + let (_y_min, y_max) = map.keys().map(|p| p.1).minmax().into_option().unwrap(); + + for y in 0..=y_max { + for x in x_min..=x_max { + let s = map[&Pos(x, y)]; + result.push(s); + } + } + result +} + +fn resource_value(fin: HashMap) -> (usize, usize) { + let trees = fin.values().filter(|c| **c == '|').count(); + let lumberyards = fin.values().filter(|c| **c == '#').count(); + (trees, lumberyards) +} + +fn load_initial_map() -> HashMap { let input = utils::read_file("input/day18.txt"); let initial: HashMap = input .lines() @@ -16,55 +64,53 @@ pub fn task1() { .collect_vec() }) .collect(); - let fin = (0..10).fold(initial, |map, _| { - printmap(&map); - map.keys() - .map(|p| { - let old = map[p]; - let new = match old { - '.' => { - if neighbors(&map, *p) - .into_iter() - .filter(|c| *c == '|') - .count() - >= 3 - { - '|' - } else { - '.' - } - } - '|' => { - if neighbors(&map, *p) - .into_iter() - .filter(|c| *c == '#') - .count() - >= 3 - { - '#' - } else { - '|' - } - } - '#' => { - if neighbors(&map, *p).contains(&'#') && neighbors(&map, *p).contains(&'|') - { - '#' - } else { - '.' - } - } - _ => panic!("unknown type"), - }; - (*p, new) - }) - .collect() - }); - let trees = fin.values().filter(|c| **c == '|').count(); - let lumberyards = fin.values().filter(|c| **c == '#').count(); - println!("Part 1 - {trees} x {lumberyards} = {}", trees * lumberyards); + initial } +fn next_map(map: HashMap) -> HashMap { + map.keys() + .map(|p| { + let old = map[p]; + let new = match old { + '.' => { + if neighbors(&map, *p) + .into_iter() + .filter(|c| *c == '|') + .count() + >= 3 + { + '|' + } else { + '.' + } + } + '|' => { + if neighbors(&map, *p) + .into_iter() + .filter(|c| *c == '#') + .count() + >= 3 + { + '#' + } else { + '|' + } + } + '#' => { + if neighbors(&map, *p).contains(&'#') && neighbors(&map, *p).contains(&'|') { + '#' + } else { + '.' + } + } + _ => panic!("unknown type"), + }; + (*p, new) + }) + .collect() +} + +#[allow(dead_code)] fn printmap(map: &HashMap) { println!(); let (x_min, x_max) = map.keys().map(|p| p.0).minmax().into_option().unwrap();