From 13d68eab9a1c7a0f32d6d182b60565278ed81c60 Mon Sep 17 00:00:00 2001 From: Dylan Thies Date: Sun, 20 Aug 2023 20:36:45 -0400 Subject: [PATCH] day 12 done --- day12/Cargo.lock | 32 ++++++++ day12/Cargo.toml | 10 +++ day12/src/main.rs | 201 ++++++++++++++++++++++++++++++++++++++++++++++ day12/test.txt | 41 ++++++++++ 4 files changed, 284 insertions(+) create mode 100644 day12/Cargo.lock create mode 100644 day12/Cargo.toml create mode 100644 day12/src/main.rs create mode 100644 day12/test.txt diff --git a/day12/Cargo.lock b/day12/Cargo.lock new file mode 100644 index 0000000..6bd01c9 --- /dev/null +++ b/day12/Cargo.lock @@ -0,0 +1,32 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "day12" +version = "0.1.0" +dependencies = [ + "itertools", + "log", +] + +[[package]] +name = "either" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" + +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" diff --git a/day12/Cargo.toml b/day12/Cargo.toml new file mode 100644 index 0000000..0dcdfd4 --- /dev/null +++ b/day12/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "day12" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +itertools = "0.11.0" +log = "0.4.20" diff --git a/day12/src/main.rs b/day12/src/main.rs new file mode 100644 index 0000000..b31ea9c --- /dev/null +++ b/day12/src/main.rs @@ -0,0 +1,201 @@ +#![warn(clippy::all, clippy::pedantic)] + +use std::{ + collections::VecDeque, + fs::File, + io::{prelude::*, BufReader}, +}; + +pub type BoxError = std::boxed::Box< + dyn std::error::Error // must implement Error to satisfy ? + + std::marker::Send // needed for threads + + std::marker::Sync, // needed for threads +>; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)] +struct Square { + pub height: u8, + pub pos: (usize, usize), +} +impl Square { + pub fn _index(&self, grid_size: &(usize, usize)) -> usize { + grid_size.1 * self.pos.0 + self.pos.1 + } + + pub fn can_go_to(&self, other: &Self) -> bool { + let from_height = self.height; + let to_height = other.height; + if from_height + 1 < to_height { + return false; + } + let (from_row, from_col) = self.pos; + let (to_row, to_col) = other.pos; + (from_row == to_row || from_col == to_col) + && from_row + 1 >= to_row + && from_row <= to_row + 1 + && from_col + 1 >= to_col + && from_col <= to_col + 1 + } +} + +#[derive(Debug, Default, Clone)] +struct Game { + board: Vec, + distances: Vec>, + board_size: (usize, usize), + start_pos: (usize, usize), + end_pos: (usize, usize), +} + +impl From for Game { + fn from(file: File) -> Self { + let buffer = BufReader::new(file); + let mut board = Vec::new(); + let mut board_size = (0_usize, 0_usize); + let mut start_pos = (0_usize, 0_usize); + let mut end_pos = (0_usize, 0_usize); + for (row, line) in buffer + .lines() + .enumerate() + .map(|(row, col)| (row, col.unwrap())) + { + board_size.0 += 1; + board_size.1 = if board_size.1 == 0 { + line.len() + } else { + board_size.1 + }; + for (col, val) in line.as_bytes().iter().enumerate() { + let height = match val { + b'E' => { + end_pos = (row, col); + 25 + } + b'S' => { + start_pos = (row, col); + 0 + } + x => x - b'a', + }; + board.push(Square { + pos: (row, col), + height, + }); + } + } + let mut distances = std::iter::repeat(None) + .take(board.len()) + .collect::>>(); + let index = board_size.1 * end_pos.0 + end_pos.1; + distances[index] = Some(0); + let mut game = Game { + board, + distances, + board_size, + start_pos, + end_pos, + }; + game._set_distances(); + game + } +} + +impl Game { + fn pos_to_index(&self, pos: &(usize, usize)) -> usize { + self.board_size.1 * pos.0 + pos.1 + } + fn _get_adjacent_from(&self, pos: &(usize, usize)) -> Vec<(usize, usize)> { + let mut vec = Vec::new(); + let index = self.pos_to_index(pos); + if pos.0 != 0 { + let new_pos = (pos.0 - 1, pos.1); + let new_index = self.pos_to_index(&new_pos); + if self + .board + .get(new_index) + .unwrap() + .can_go_to(self.board.get(index).unwrap()) + { + vec.push(new_pos); + } + } + if pos.0 + 1 < self.board_size.0 { + let new_pos = (pos.0 + 1, pos.1); + let new_index = self.pos_to_index(&new_pos); + if self.board[new_index].can_go_to(&self.board[index]) { + vec.push(new_pos); + } + } + if pos.1 != 0 { + let new_pos = (pos.0, pos.1 - 1); + let new_index = self.pos_to_index(&new_pos); + if self.board[new_index].can_go_to(&self.board[index]) { + vec.push(new_pos); + } + } + if pos.1 + 1 < self.board_size.1 { + let new_pos = (pos.0, pos.1 + 1); + let new_index = self.pos_to_index(&new_pos); + if self.board[new_index].can_go_to(&self.board[index]) { + vec.push(new_pos); + } + } + vec + } + fn _set_distances(&mut self) { + let mut queue = VecDeque::new(); + queue.push_back(self.end_pos); + while let Some(cur_pos) = queue.pop_front() { + let adjacent = self._get_adjacent_from(&cur_pos); + let cur_index = self.pos_to_index(&cur_pos); + let cur_dist = self.distances.get(cur_index).unwrap().unwrap(); + adjacent + .iter() + .filter(|pos| { + let index = self.pos_to_index(pos); + match self.distances.get(index).unwrap() { + None => { + self.distances[index] = Some(cur_dist + 1); + true + } + Some(check_dist) if *check_dist > cur_dist + 1 => { + self.distances[index] = Some(cur_dist + 1); + true + } + _ => false, + } + }) + .for_each(|check_pos| { + queue.push_back(*check_pos); + }); + } + } + pub fn get_distance_to_end(&self, pos: &(usize, usize)) -> Option { + *self.distances.get(self.pos_to_index(pos)).unwrap() + } + pub fn get_all_at_height(&self, height: u8) -> Vec { + self.board + .iter() + .filter(|x| x.height == height) + .copied() + .collect() + } +} +fn main() -> Result<(), BoxError> { + let file = File::open("./test.txt")?; + let game: Game = file.into(); + let start = game.start_pos; + let s = game + .get_distance_to_end(&start) + .expect("No end to this game"); + println!("Part 1: {s}"); + let shortest = game + .get_all_at_height(0) + .iter() + .filter_map(|x| game.get_distance_to_end(&x.pos)) + .min() + .expect("problem"); + println!("Part 2: {shortest}"); + + Ok(()) +} diff --git a/day12/test.txt b/day12/test.txt new file mode 100644 index 0000000..509b9ac --- /dev/null +++ b/day12/test.txt @@ -0,0 +1,41 @@ +abccccccccccccccccaaccccccccccccccccccccaaaaaaaaaaaaacccccccccccccccccccccccccccccccccccccccccccccccccccccccaaaaaa +abcccccccccccccaaaaaccccccccccccccccccccaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccccccccccccccccccccaaaaa +abccccccccccccccaaaaaccccccccccccccaaaaacccaaaaaacccccaaccccccccccccccccccccccccccccccccccccccccccccccccccccccaaaa +abccccccccccccccaaaaacccccccccaacccaaaaacccaaaaaaaccccaaaacaacaaccccccccccccccccccccccccaaaccccaaaccccccccccccaaaa +abcccccccccccccaaaaacccccccaaaaaccaaaaaacccaaaaaaaacaaaaaacaaaaaccccccccccccccccccccccccaaacccaaaaccccccccccccaaac +abccccccaacaaaccccaaccccccccaaaaacaaaaaaccaaaacaaaacaaaaaccaaaaaaccccccccccccccccccccccccaaaaaaaacccccccccccccaacc +abccccccaaaaaaccccccccccccccaaaaacaaaaaaccaaaaccaaaacaaaaacaaaaaacccccccccccccccccccccccaaaaaaaaaccccccccccccccccc +abccccccaaaaaacccccccccccccaaaaaccccaaccccaacccccaaccaacaacaaaaaccccccccccccccccccccccccccaaakkkkllllcccaaaccccccc +abccccccaaaaaaacccccccccccccccaaccccaacccccccccccccccccccccccaaaccccccaaaacccccccccjjjjkkkkkkkkkkllllccccaacaccccc +abcccccaaaaaaaacccccaaccccccccccccccaaaaaaccccccccccccccccccaaccccccccaaaaccccccccjjjjjkkkkkkkkkppllllcccaaaaacccc +abcccccaaaaaaaaccaaaacccccccccccccccaaaaaccccccccccccccccaacaaccccccccaaaacccccccjjjjjjjkkkkkppppppplllccaaaaacccc +abccccccccaaaccccaaaaaacccccccccccaaaaaaaccccccccccccccccaaaaacccccccccaacccccccjjjjoooooooppppppppplllcccaaaccccc +abccccccccaaccccccaaaaaccccaacccccaaaaaaaaccccaaacccccccccaaaaaaacccccccccccccccjjjooooooooppppuuppppllcccaaaccccc +abccccccaacccccccaaaaacccccaaaccaaaaaaaaaaccaaaaaaccccccaaaaaaaaaacaaaccccccccccjjjoooouuuoopuuuuupppllcccaaaccccc +abacccccaaccccccccccaacccccaaaaaaaccaaaaaaccaaaaaaccccccaaaaaccaaaaaaaccccaaccccjjoootuuuuuuuuuuuuvpqlllcccccccccc +abaccaaaaaaaacccccccccccccccaaaaaaccaacccccccaaaaacccccccacaaaccaaaaaaccaaaacaccjjooottuuuuuuuxyuvvqqljjccddcccccc +abcccaaaaaaaaccccccccccccaaaaaaaaacaacaaccccaaaaaccccccccccaaaaaaaaaacccaaaaaacciijootttxxxuuxyyyvvqqjjjjdddcccccc +abcccccaaaaccccaaacccccccaaaaaaaaacaaaaaccccaaaaaccccccccccccaaaaaaaaacccaaaaccciiinntttxxxxxxyyvvqqqqjjjddddccccc +abccccaaaaaccccaaaaacccccaaaaaaaaaaaaaaaaccccccccccccccccccccaaaaaaaaaaccaaaaccciiinntttxxxxxxyyvvvqqqqjjjdddccccc +abccccaaaaaaccaaaaaccccccccaaaaaaaaaaaaaacccccccccccccccccccccccaaacaaacaacaaccciiinnnttxxxxxyyyvvvvqqqqjjjdddcccc +SbccccaaccaaccaaaaacccccccccaaaaaaaaaaaaacccccccccccccccccccccccaaacccccccccccciiinnntttxxxEzzyyyyvvvqqqjjjdddcccc +abcccccccccccccaaaaacccccccaaaaaaaaacaaaccccccccccccccccccccccccaaccccccccccccciiinnnttxxxxyyyyyyyyvvvqqqjjjdddccc +abcccccccccccccaaccccccccccaaaaaaaaccccccccccccccccccccccccccccccccccccccccccciiinnntttxxyyyyyyyyyvvvvqqqjjjdddccc +abccccccccccccccccccccccccaaaaaaaacccccccccccccccccccccccccccccccccccccccccccciiinntttxxxwwwyyywwvvvvrqqjjjjdddccc +abcccccccccccccccccccccccccccaaaaaaccccccccccccccccccccccccccccccccccccccccccciinnntttxwwwwwyyywwvvvrrrqkkkeddcccc +abcccccccccccccccccccccccccccaaaaaaccccccccccccccccccccccccccccccccccccccccccchhnnntttsswwswwyywwrrrrrrkkkkeeecccc +abcccccccccccccccccccccccccccaaaaaacccccccccccccccccccaccccccccccccaaacccccccchhhnmmssssssswwwwwwrrrkkkkkeeeeecccc +abcccccccccccccccccccccccccccccaaacccccccccccccccccccaaccccccccccaaaaaacccccaahhhmmmmmsssssswwwwrrrkkkkkeeeeeccccc +abaacccccccccccccaccccccccccccccccccccccccccccccccaaaaacaacccccccaaaaaacaaaaaahhhhmmmmmmmmssswwwrrkkkkeeeeeacccccc +abacccccccccccccaaaaaaaaccccccccaaacccccccaaccccccaaaaaaaacccccccaaaaaacaaaaaaahhhhmmmmmmmmsssrrrrkkkeeeeeaacccccc +abaaaccccaaccccccaaaaaacccccccccaaacccaacaaaccccccccaaaacccccccccaaaaacccaaaaaaahhhhhhhmmmmlsssrrllkfeeeeaaaaacccc +abaaaccaaaaccccccaaaaaacccccccccaaaaaaaaaaaaaacccccaaaaacccccccccaaaaacccaaaaaaachhhhhgggmllsssrrllkffeaaaaaaacccc +abaacccaaaaaacccaaaaaaaacccccaaaaaaaaaaaaaaaaacccccaacaaacccccccccccccccaaaaaacccccchggggglllllllllfffaaaaaaaacccc +abaaccccaaaacccaaaaaaaaaaccccaaaaaaaaacaaaaaaaccaccaccaaacccccccccccccccaaaaaacccccccccgggglllllllffffaaaaaacccccc +abcccccaaaaacccaaaaaaaaaacccccaaaaaaaccaaaaacccaaaccccccccccccccccccccccccccaacccccccccagggglllllffffccccaaacccccc +abcccccaacaaccccccaaaaacaccaacccaaaaaaaaaaaaaccaaacccccccccccccccccccccccccccccccccccccaagggggffffffcccccccccccccc +abcccccccccccaaaaaaaaacccccaaccaaaaaaaccaaaaacaaaaccccccccccccccccccccccccccccccccccccaaaacgggfffffccccccccccccccc +abcccccccccccaaaaacaacccaaaaaaaaaaccaacccaaaaaaaacccaaccccccccccccccccccccccccccccccccccccccggfffccccccccccccaaaca +abccccccccccaaaaaaccccccaaaaaaaaacccccccccaaaaaaaaaaaacccccccccccccaaaccccccccccccccccccccccaaaccccccccccccccaaaaa +abccccccccccaaaaaaccccccccaaaacccccccccccccaaaaaaaaaaaaccccccccccccaaaaccccccccccccccccccccccaaaccccccccccccccaaaa +abcccccccccccaaaaacccccccaaaaaaccccccccccaaaaaaaaaaaaaaccccccccccccaaaaccccccccccccccccccccccccccccccccccccccaaaaa \ No newline at end of file