From 16ae19ffa877975374dd84d60f9b94e1b485d0e5 Mon Sep 17 00:00:00 2001 From: Sebastian Tobie Date: Wed, 18 Dec 2024 11:56:19 +0100 Subject: [PATCH] Day 18 2024 solved. --- Cargo.lock | 111 +++++++++++++++++++++++++++++ Cargo.toml | 1 + Makefile | 4 +- days/2024/18.rs | 161 +++++++++++++++++++++++++++++++++++++++++++ examples/2024/18.txt | 25 +++++++ 5 files changed, 300 insertions(+), 2 deletions(-) create mode 100644 days/2024/18.rs create mode 100644 examples/2024/18.txt diff --git a/Cargo.lock b/Cargo.lock index fc7b8b8..e677908 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,6 +7,7 @@ name = "advent-of-code" version = "0.1.0" dependencies = [ "advent-of-code-macros", + "console", "log", "num", "regex", @@ -37,6 +38,31 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "console" +version = "0.15.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea3c6ecd8059b57859df5c69830340ed3c41d30e3da0c1cbed90a96ac853041b" +dependencies = [ + "encode_unicode", + "libc", + "once_cell", + "unicode-width", + "windows-sys", +] + +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + +[[package]] +name = "libc" +version = "0.2.168" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" + [[package]] name = "log" version = "0.4.22" @@ -122,6 +148,12 @@ dependencies = [ "autocfg", ] +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + [[package]] name = "proc-macro2" version = "1.0.92" @@ -191,3 +223,82 @@ name = "unicode-ident" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml index 6b5ca5a..ab31104 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -312,6 +312,7 @@ name = "advent_of_code" num="0.4.*" log="0.4.*" thousands="0.2.*" +console="0.15.*" [dependencies.advent-of-code-macros] path = "macros" diff --git a/Makefile b/Makefile index 34a8563..5b512e5 100644 --- a/Makefile +++ b/Makefile @@ -7,9 +7,9 @@ fmt: %: fmt @$(CARGO) build $(CARGO_OPTS) --bin $@ - @timeout --preserve-status -v 60 ./target/$(TARGET_DIR)/$@ + @timeout --foreground --preserve-status -v 60 ./target/$(TARGET_DIR)/$@ Makefile: exit -all: 202{3,4}-{01..25} \ No newline at end of file +all: 202{3,4}-{01..25} diff --git a/days/2024/18.rs b/days/2024/18.rs new file mode 100644 index 0000000..958a892 --- /dev/null +++ b/days/2024/18.rs @@ -0,0 +1,161 @@ +use std::{cmp::Ordering, collections::HashMap}; + +use advent_of_code::{ + strings::{convert_to_array, parsenumber}, + Kartesian, Map, ToCoords, KD, +}; +#[allow(unused_imports)] +use advent_of_code_macros::{include_data, include_example}; +use log::*; + +include_data!(DATA 2024 18); + +const HEIGHT: usize = 71; +const WIDTH: usize = HEIGHT; +const BLOCKS: usize = 1024; + +fn get_coords(line: &str) -> Kartesian { + let (y, x) = line.split_once(',').unwrap(); + Kartesian::::new(parsenumber(x), parsenumber(y)).to_coords() +} + +#[inline] +fn i_to_c(i: usize) -> char { + match i % 10 { + 1 => '1', + 2 => '2', + 3 => '3', + 4 => '4', + 5 => '5', + 6 => '6', + 7 => '7', + 8 => '8', + 9 => '9', + 0 => '0', + _ => unreachable!(), + } +} + +#[derive(Debug, Default, Clone, Ord, Copy)] +struct Node { + coords: Kartesian, + score: usize, + parent: Kartesian, +} + +impl PartialEq for Node { + fn eq(&self, other: &Self) -> bool { + self.coords.eq(&other.coords) + } +} +impl Eq for Node {} + +impl PartialOrd for Node { + fn partial_cmp(&self, other: &Self) -> Option { + match self.score.partial_cmp(&other.score) { + Some(Ordering::Equal) => self.coords.partial_cmp(&other.coords), + x => x, + } + } +} + +fn astar_search(mut map: Map, start_pos: Kartesian, dest_pos: Kartesian) -> Option { + let maximum = map.size(); + let mut nodelist = HashMap::with_capacity(maximum.x * maximum.y); + let start = Node { + coords: start_pos, + score: 0, + parent: start_pos, + }; + let mut destination = Node { + coords: dest_pos, + score: maximum.x * maximum.y, + parent: dest_pos, + }; + nodelist.insert(start_pos, start); + let mut open = vec![start_pos]; + let (mut node, mut nodepos, mut coords); + loop { + nodepos = match open.pop() { + None => { + debug!("Out of possible nodes"); + break; + }, + Some(x) => x, + }; + node = *nodelist.get(&nodepos).unwrap(); + for dir in KD::iter(false, false, true) { + coords = match nodepos.move_dir_max(dir.vector(), dir, maximum) { + None => continue, + Some(x) => { + if map.get(x) == Some(WALL) { + continue; + } + x + }, + }; + let newnode = match nodelist.get_mut(&coords) { + None => { + let newnode = Node { + coords, + score: node.score + 1, + parent: node.coords, + }; + map.set(coords, i_to_c(node.score + 1)); + open.insert(0, newnode.coords); + nodelist.insert(coords, newnode); + nodelist.get_mut(&coords).unwrap() + }, + Some(node) => node, + }; + if newnode.score > node.score + 1 { + debug!("Overwriting score {} > {}: {:?}", newnode.score, node.score + 1, newnode); + newnode.parent = node.coords; + newnode.score = node.score + 1; + } + if newnode.coords == destination.coords && newnode.score < destination.score { + destination.parent = newnode.parent; + destination.score = newnode.score + } + } + open.sort(); + if open.len() > 300 { + println!("{:#?}", open); + break; + } + debug!("Open coords: {}\n{}", open.len(), map); + } + if destination.parent == dest_pos { + None + } else { + Some(destination.score) + } +} + +fn main() { + let blocks = convert_to_array::<_, _, '\n'>(DATA, get_coords); + let mut corrupted = blocks.iter().cloned(); + let mut map = Map::::empty(HEIGHT, WIDTH); + let mut fallen = 0; + map.replace_default('.'); + while let Some(coord) = corrupted.next() { + fallen += 1; + map.set(coord, '#'); + if fallen == BLOCKS { + break; + } + } + println!("Minimum Steps: {}", astar_search::<'#'>(map.clone(), map.size() - Kartesian::new(1, 1), Kartesian::default()).unwrap()); + while let Some(coord) = corrupted.next() { + map.set(coord, '#'); + if astar_search::<'#'>(map.clone(), map.size() - Kartesian::new(1, 1), Kartesian::default()).is_none() { + println!("First Block is: {},{}", coord.y, coord.x); + break; + } + } +} + +#[cfg(test)] +mod test { + use super::*; +} diff --git a/examples/2024/18.txt b/examples/2024/18.txt new file mode 100644 index 0000000..79c8583 --- /dev/null +++ b/examples/2024/18.txt @@ -0,0 +1,25 @@ +5,4 +4,2 +4,5 +3,0 +2,1 +6,3 +2,4 +1,5 +0,6 +3,3 +2,6 +5,1 +1,2 +5,5 +2,5 +6,5 +1,4 +0,4 +6,4 +1,1 +6,1 +1,0 +0,5 +1,6 +2,0