From 1f901849d63b49ff2c5133d554ea0b0124daf946 Mon Sep 17 00:00:00 2001 From: Mathis Date: Mon, 25 Dec 2023 00:46:35 +0100 Subject: [PATCH] 2023-17: Start implementing part one --- input/2023/day_17/input_test.txt | 13 +++ .../day_17_clumsy_crucible/common.rs | 7 ++ src/year_2023/day_17_clumsy_crucible/mod.rs | 25 +++++ .../day_17_clumsy_crucible/part_one.rs | 105 ++++++++++++++++++ src/year_2023/mod.rs | 2 + 5 files changed, 152 insertions(+) create mode 100644 input/2023/day_17/input_test.txt create mode 100644 src/year_2023/day_17_clumsy_crucible/common.rs create mode 100644 src/year_2023/day_17_clumsy_crucible/mod.rs create mode 100644 src/year_2023/day_17_clumsy_crucible/part_one.rs diff --git a/input/2023/day_17/input_test.txt b/input/2023/day_17/input_test.txt new file mode 100644 index 0000000..3c85086 --- /dev/null +++ b/input/2023/day_17/input_test.txt @@ -0,0 +1,13 @@ +2413432311323 +3215453535623 +3255245654254 +3446585845452 +4546657867536 +1438598798454 +4457876987766 +3637877979653 +4654967986887 +4564679986453 +1224686865563 +2546548887735 +4322674655533 \ No newline at end of file diff --git a/src/year_2023/day_17_clumsy_crucible/common.rs b/src/year_2023/day_17_clumsy_crucible/common.rs new file mode 100644 index 0000000..59f7457 --- /dev/null +++ b/src/year_2023/day_17_clumsy_crucible/common.rs @@ -0,0 +1,7 @@ +#[derive(Debug, Clone, Copy)] +pub enum Direction { + Up, + Down, + Left, + Right, +} \ No newline at end of file diff --git a/src/year_2023/day_17_clumsy_crucible/mod.rs b/src/year_2023/day_17_clumsy_crucible/mod.rs new file mode 100644 index 0000000..261c39a --- /dev/null +++ b/src/year_2023/day_17_clumsy_crucible/mod.rs @@ -0,0 +1,25 @@ +pub mod part_one; +// pub mod part_two; +pub mod common; + +use crate::utils::solution::Solution; +use crate::utils::input_reader; + +pub struct DaySolution ; + + +impl Solution for DaySolution { + + fn input_path(&self) -> &'static str { + "input/2023/day_17/input_test.txt" + } + + fn part_one(&self) -> String { + input_reader::read_input_file(self.input_path(), part_one::part_one) + } + + fn part_two(&self) -> String { + // input_reader::read_input_file(self.input_path(), part_two::part_two) + String::from("Not implemented") + } +} \ No newline at end of file diff --git a/src/year_2023/day_17_clumsy_crucible/part_one.rs b/src/year_2023/day_17_clumsy_crucible/part_one.rs new file mode 100644 index 0000000..caaec58 --- /dev/null +++ b/src/year_2023/day_17_clumsy_crucible/part_one.rs @@ -0,0 +1,105 @@ +use std::{collections::{HashMap, HashSet}, cmp}; + +use super::common::Direction; + +pub fn part_one(input_lines: Vec) -> String { + + let mut map: Vec> = Vec::new(); + for line in input_lines { + let mut row: Vec = Vec::new(); + for c in line.chars() { + row.push(c.to_digit(10).unwrap() as i32); + } + map.push(row); + } + + let mut cache: HashMap<(i32, i32), i32> = HashMap::new(); + let current_path: HashSet<(i32, i32)> = HashSet::new(); + + let cost = min_cost_path(&map, &mut cache, current_path, Direction::Right, 0, 0, 0) - map[0][0]; + cost.to_string() +} + +fn min_cost_path( + map: &Vec>, + cache: &mut HashMap<(i32, i32), i32>, + mut current_path: HashSet<(i32, i32)>, + dir: Direction, + step_count: i32, + i: i32, + j: i32) -> i32 { + + // println!("{}: {} {} {:?}", step_count, i, j, dir); + + if i < 0 || j < 0 || i >= map.len() as i32 || j >= map[0].len() as i32 { + return i32::MAX; + } + + if step_count >= 3 { + return i32::MAX; + } + + if current_path.contains(&(i,j)) { + return i32::MAX; + } else { + current_path.insert((i,j)); + } + + if i == map.len() as i32 - 1 && j == map[0].len() as i32 - 1 { + println!("Final path: {:?}", current_path); + return map[i as usize][j as usize]; + } + + if cache.contains_key(&(i,j)) { + return *cache.get(&(i,j)).unwrap(); + } + + let mut cost = map[i as usize][j as usize]; + let res: i32; + + match dir { + Direction::Up => { + res = min( + min_cost_path(map, cache, current_path.clone(), Direction::Up, step_count + 1, i - 1, j), + min_cost_path(map, cache, current_path.clone(), Direction::Left, 0, i, j - 1), + min_cost_path(map, cache, current_path.clone(), Direction::Right, 0, i, j + 1) + ); + }, + Direction::Down => { + res = min( + min_cost_path(map, cache, current_path.clone(), Direction::Down, step_count + 1, i + 1, j), + min_cost_path(map, cache, current_path.clone(), Direction::Left, 0, i, j - 1), + min_cost_path(map, cache, current_path.clone(), Direction::Right, 0, i, j + 1) + ); + }, + Direction::Left => { + res = min( + min_cost_path(map, cache, current_path.clone(), Direction::Left, step_count + 1, i, j - 1), + min_cost_path(map, cache, current_path.clone(), Direction::Up, 0, i - 1, j), + min_cost_path(map, cache, current_path.clone(), Direction::Down, 0, i + 1, j) + ); + }, + Direction::Right => { + res = min( + min_cost_path(map, cache, current_path.clone(), Direction::Right, step_count + 1, i, j + 1), + min_cost_path(map, cache, current_path.clone(), Direction::Up, 0, i - 1, j), + min_cost_path(map, cache, current_path.clone(), Direction::Down, 0, i + 1, j) + ); + }, + } + + current_path.remove(&(i, j)); + + if let Some(new_cost) = cost.checked_add(res) { + cost = new_cost; + } else { + cost = i32::MAX; + } + + cache.insert((i,j), cost); + cost +} + +fn min(a: i32, b: i32 ,c: i32) -> i32 { + cmp::min(a, cmp::min(b, c)) +} \ No newline at end of file diff --git a/src/year_2023/mod.rs b/src/year_2023/mod.rs index 3550bd7..7b03bcc 100644 --- a/src/year_2023/mod.rs +++ b/src/year_2023/mod.rs @@ -14,6 +14,7 @@ pub mod day_13_point_of_incidence; pub mod day_14_parabolic_reflector_dish; pub mod day_15_lens_library; pub mod day_16_the_floor_will_be_lava; +pub mod day_17_clumsy_crucible; pub fn run(day: &str) { let solution: Box = match day { @@ -31,6 +32,7 @@ pub fn run(day: &str) { "14" => Box::new(day_14_parabolic_reflector_dish::DaySolution), "15" => Box::new(day_15_lens_library::DaySolution), "16" => Box::new(day_16_the_floor_will_be_lava::DaySolution), + "17" => Box::new(day_17_clumsy_crucible::DaySolution), _ => panic!("Invalid day specified"), };