diff --git a/input/day14.txt b/input/day14.txt new file mode 100644 index 0000000..a10b4e6 --- /dev/null +++ b/input/day14.txt @@ -0,0 +1,112 @@ +481,54 -> 481,47 -> 481,54 -> 483,54 -> 483,45 -> 483,54 -> 485,54 -> 485,52 -> 485,54 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +465,117 -> 465,120 -> 464,120 -> 464,123 -> 476,123 -> 476,120 -> 471,120 -> 471,117 +451,104 -> 451,103 -> 451,104 -> 453,104 -> 453,97 -> 453,104 -> 455,104 -> 455,100 -> 455,104 +501,15 -> 506,15 +481,54 -> 481,47 -> 481,54 -> 483,54 -> 483,45 -> 483,54 -> 485,54 -> 485,52 -> 485,54 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +474,73 -> 474,74 -> 486,74 -> 486,73 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +481,54 -> 481,47 -> 481,54 -> 483,54 -> 483,45 -> 483,54 -> 485,54 -> 485,52 -> 485,54 +491,29 -> 495,29 +491,17 -> 496,17 +474,36 -> 474,38 -> 468,38 -> 468,41 -> 482,41 -> 482,38 -> 478,38 -> 478,36 +454,107 -> 454,110 -> 450,110 -> 450,114 -> 467,114 -> 467,110 -> 459,110 -> 459,107 +462,84 -> 462,87 -> 455,87 -> 455,91 -> 469,91 -> 469,87 -> 466,87 -> 466,84 +462,84 -> 462,87 -> 455,87 -> 455,91 -> 469,91 -> 469,87 -> 466,87 -> 466,84 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +477,33 -> 482,33 -> 482,32 +485,29 -> 489,29 +481,54 -> 481,47 -> 481,54 -> 483,54 -> 483,45 -> 483,54 -> 485,54 -> 485,52 -> 485,54 +485,153 -> 485,145 -> 485,153 -> 487,153 -> 487,152 -> 487,153 -> 489,153 -> 489,143 -> 489,153 -> 491,153 -> 491,148 -> 491,153 +465,117 -> 465,120 -> 464,120 -> 464,123 -> 476,123 -> 476,120 -> 471,120 -> 471,117 +462,84 -> 462,87 -> 455,87 -> 455,91 -> 469,91 -> 469,87 -> 466,87 -> 466,84 +481,54 -> 481,47 -> 481,54 -> 483,54 -> 483,45 -> 483,54 -> 485,54 -> 485,52 -> 485,54 +474,36 -> 474,38 -> 468,38 -> 468,41 -> 482,41 -> 482,38 -> 478,38 -> 478,36 +485,153 -> 485,145 -> 485,153 -> 487,153 -> 487,152 -> 487,153 -> 489,153 -> 489,143 -> 489,153 -> 491,153 -> 491,148 -> 491,153 +485,153 -> 485,145 -> 485,153 -> 487,153 -> 487,152 -> 487,153 -> 489,153 -> 489,143 -> 489,153 -> 491,153 -> 491,148 -> 491,153 +477,59 -> 477,60 -> 495,60 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +481,54 -> 481,47 -> 481,54 -> 483,54 -> 483,45 -> 483,54 -> 485,54 -> 485,52 -> 485,54 +465,117 -> 465,120 -> 464,120 -> 464,123 -> 476,123 -> 476,120 -> 471,120 -> 471,117 +465,117 -> 465,120 -> 464,120 -> 464,123 -> 476,123 -> 476,120 -> 471,120 -> 471,117 +465,117 -> 465,120 -> 464,120 -> 464,123 -> 476,123 -> 476,120 -> 471,120 -> 471,117 +451,104 -> 451,103 -> 451,104 -> 453,104 -> 453,97 -> 453,104 -> 455,104 -> 455,100 -> 455,104 +477,140 -> 488,140 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +485,23 -> 489,23 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +497,65 -> 502,65 +488,26 -> 492,26 +451,104 -> 451,103 -> 451,104 -> 453,104 -> 453,97 -> 453,104 -> 455,104 -> 455,100 -> 455,104 +479,29 -> 483,29 +474,36 -> 474,38 -> 468,38 -> 468,41 -> 482,41 -> 482,38 -> 478,38 -> 478,36 +454,107 -> 454,110 -> 450,110 -> 450,114 -> 467,114 -> 467,110 -> 459,110 -> 459,107 +485,153 -> 485,145 -> 485,153 -> 487,153 -> 487,152 -> 487,153 -> 489,153 -> 489,143 -> 489,153 -> 491,153 -> 491,148 -> 491,153 +454,107 -> 454,110 -> 450,110 -> 450,114 -> 467,114 -> 467,110 -> 459,110 -> 459,107 +474,36 -> 474,38 -> 468,38 -> 468,41 -> 482,41 -> 482,38 -> 478,38 -> 478,36 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +498,17 -> 503,17 +485,153 -> 485,145 -> 485,153 -> 487,153 -> 487,152 -> 487,153 -> 489,153 -> 489,143 -> 489,153 -> 491,153 -> 491,148 -> 491,153 +474,36 -> 474,38 -> 468,38 -> 468,41 -> 482,41 -> 482,38 -> 478,38 -> 478,36 +485,153 -> 485,145 -> 485,153 -> 487,153 -> 487,152 -> 487,153 -> 489,153 -> 489,143 -> 489,153 -> 491,153 -> 491,148 -> 491,153 +488,20 -> 492,20 +494,67 -> 499,67 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +462,84 -> 462,87 -> 455,87 -> 455,91 -> 469,91 -> 469,87 -> 466,87 -> 466,84 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +454,107 -> 454,110 -> 450,110 -> 450,114 -> 467,114 -> 467,110 -> 459,110 -> 459,107 +485,153 -> 485,145 -> 485,153 -> 487,153 -> 487,152 -> 487,153 -> 489,153 -> 489,143 -> 489,153 -> 491,153 -> 491,148 -> 491,153 +505,17 -> 510,17 +487,67 -> 492,67 +451,104 -> 451,103 -> 451,104 -> 453,104 -> 453,97 -> 453,104 -> 455,104 -> 455,100 -> 455,104 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +474,36 -> 474,38 -> 468,38 -> 468,41 -> 482,41 -> 482,38 -> 478,38 -> 478,36 +490,65 -> 495,65 +485,153 -> 485,145 -> 485,153 -> 487,153 -> 487,152 -> 487,153 -> 489,153 -> 489,143 -> 489,153 -> 491,153 -> 491,148 -> 491,153 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +478,81 -> 483,81 +501,67 -> 506,67 +484,69 -> 489,69 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +454,107 -> 454,110 -> 450,110 -> 450,114 -> 467,114 -> 467,110 -> 459,110 -> 459,107 +462,84 -> 462,87 -> 455,87 -> 455,91 -> 469,91 -> 469,87 -> 466,87 -> 466,84 +485,153 -> 485,145 -> 485,153 -> 487,153 -> 487,152 -> 487,153 -> 489,153 -> 489,143 -> 489,153 -> 491,153 -> 491,148 -> 491,153 +497,29 -> 501,29 +493,63 -> 498,63 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +485,153 -> 485,145 -> 485,153 -> 487,153 -> 487,152 -> 487,153 -> 489,153 -> 489,143 -> 489,153 -> 491,153 -> 491,148 -> 491,153 +494,26 -> 498,26 +481,54 -> 481,47 -> 481,54 -> 483,54 -> 483,45 -> 483,54 -> 485,54 -> 485,52 -> 485,54 +477,59 -> 477,60 -> 495,60 +470,77 -> 475,77 +451,104 -> 451,103 -> 451,104 -> 453,104 -> 453,97 -> 453,104 -> 455,104 -> 455,100 -> 455,104 +497,13 -> 502,13 +451,104 -> 451,103 -> 451,104 -> 453,104 -> 453,97 -> 453,104 -> 455,104 -> 455,100 -> 455,104 +505,69 -> 510,69 +474,73 -> 474,74 -> 486,74 -> 486,73 +474,73 -> 474,74 -> 486,74 -> 486,73 +467,79 -> 472,79 +482,26 -> 486,26 +465,117 -> 465,120 -> 464,120 -> 464,123 -> 476,123 -> 476,120 -> 471,120 -> 471,117 +451,104 -> 451,103 -> 451,104 -> 453,104 -> 453,97 -> 453,104 -> 455,104 -> 455,100 -> 455,104 +465,117 -> 465,120 -> 464,120 -> 464,123 -> 476,123 -> 476,120 -> 471,120 -> 471,117 +454,107 -> 454,110 -> 450,110 -> 450,114 -> 467,114 -> 467,110 -> 459,110 -> 459,107 +491,69 -> 496,69 +474,36 -> 474,38 -> 468,38 -> 468,41 -> 482,41 -> 482,38 -> 478,38 -> 478,36 +498,69 -> 503,69 +464,81 -> 469,81 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +462,84 -> 462,87 -> 455,87 -> 455,91 -> 469,91 -> 469,87 -> 466,87 -> 466,84 +491,23 -> 495,23 +471,81 -> 476,81 +477,33 -> 482,33 -> 482,32 +451,104 -> 451,103 -> 451,104 -> 453,104 -> 453,97 -> 453,104 -> 455,104 -> 455,100 -> 455,104 +485,153 -> 485,145 -> 485,153 -> 487,153 -> 487,152 -> 487,153 -> 489,153 -> 489,143 -> 489,153 -> 491,153 -> 491,148 -> 491,153 +462,84 -> 462,87 -> 455,87 -> 455,91 -> 469,91 -> 469,87 -> 466,87 -> 466,84 +481,54 -> 481,47 -> 481,54 -> 483,54 -> 483,45 -> 483,54 -> 485,54 -> 485,52 -> 485,54 +471,136 -> 471,130 -> 471,136 -> 473,136 -> 473,128 -> 473,136 -> 475,136 -> 475,132 -> 475,136 -> 477,136 -> 477,133 -> 477,136 -> 479,136 -> 479,133 -> 479,136 -> 481,136 -> 481,132 -> 481,136 +454,107 -> 454,110 -> 450,110 -> 450,114 -> 467,114 -> 467,110 -> 459,110 -> 459,107 +494,15 -> 499,15 +474,79 -> 479,79 \ No newline at end of file diff --git a/input/day14_example.txt b/input/day14_example.txt new file mode 100644 index 0000000..1926028 --- /dev/null +++ b/input/day14_example.txt @@ -0,0 +1,2 @@ +498,4 -> 498,6 -> 496,6 +503,4 -> 502,4 -> 502,9 -> 494,9 \ No newline at end of file diff --git a/src/day14.rs b/src/day14.rs new file mode 100644 index 0000000..902428a --- /dev/null +++ b/src/day14.rs @@ -0,0 +1,164 @@ +use std::fmt::{Display, Formatter}; + +use crate::{day_solver::DaySolver, util::{Coord, Grid}}; + +use super::util; + +pub struct Day14 { + platforms: Vec +} + +const STARTING_COORD: Coord = Coord { x: 500, y: 0}; + +impl Day14 { + + pub fn create() -> Self { + // let lines = util::read_file("input/day14_example.txt"); + let lines = util::read_file("input/day14.txt"); + + // Put the input into the day struct + return Day14 { + platforms: lines.iter().map(|l| + Platform { + coords: l.split(" -> ") + .map(|c| { + let mut c_split = c.split(","); + Coord { + x: c_split.next().unwrap().parse::().unwrap(), + y: c_split.next().unwrap().parse::().unwrap(), + } + }).collect::>>() + }).collect() + } + } + + fn try_move_to(sand_coord: &mut Coord, target_x: &usize, target_y: &usize, grid: &Grid) -> Option { + match grid.get(target_x, target_y) { + Cell::Empty => { + sand_coord.x = target_x.to_owned(); + sand_coord.y = target_y.to_owned(); + Some(true) + }, + _ => None + } + } + + fn build_grid(&self) -> Grid { + // println!("{:?}", self.platforms); + // Build a grid from the platforms: + let max_y = self.platforms.iter().map(|p| p.coords.iter().map(|c| c.y).max().unwrap()).max().unwrap() as usize; + let mut grid = Grid { + data: vec![Cell::Empty; 1000 * (max_y + 3)], + width: 1000 + }; + + // Add the platforms to the grid + for platform in &self.platforms { + let mut coord_iter = platform.coords.iter(); + let mut from = coord_iter.next().unwrap(); + while let Some(to) = coord_iter.next() { + // println!("Adding wall from {:?} to {:?}", from, to); + for y in from.y.min(to.y)..(to.y.max(from.y) + 1) { + for x in from.x.min(to.x)..(to.x.max(from.x) + 1) { + // println!("Adding {},{}", x, y); + grid.set(&(x as usize), &(y as usize), Cell::Wall); + } + } + from = to; + } + } + // grid.print_range(495, 505, 0, max_y + 3); + + grid + } + + fn simulate_sand(&self, grid: &mut Grid) -> SimulationResult { + let grid_height = grid.height(); + let mut sand_coord = STARTING_COORD.clone(); + loop { + let target_x = sand_coord.x; + let target_y = sand_coord.y + 1; + if target_y >= grid_height { + // Falling into the abyss!! + return SimulationResult::FellOff + } + if Day14::try_move_to(&mut sand_coord, &target_x, &target_y, &grid) + .or_else(|| Day14::try_move_to(&mut sand_coord, &(target_x - 1), &target_y, &grid)) + .or_else(|| Day14::try_move_to(&mut sand_coord, &(target_x + 1), &target_y, &grid)) == None { + // If we didn't find any option, the sand stops moving: + grid.set(&sand_coord.x, &sand_coord.y, Cell::Sand); + return SimulationResult::EndedAt(sand_coord); + } + // println!("Sand is at {:?}", sand_coord) + } + } +} + +impl DaySolver for Day14 { + + + fn solve_part1(&mut self) -> String { + + let mut grid = self.build_grid(); + + + // Let's drop some sand + let mut counter = 0; + loop { + if self.simulate_sand(&mut grid) == SimulationResult::FellOff { + return counter.to_string(); + } + counter += 1; + // grid.print_range(495, 505, 0, 10); + + } + } + + fn solve_part2(&mut self) -> String { + + let mut grid = self.build_grid(); + grid.set_row(grid.height() - 1, Cell::Wall); + + // Let's drop some sand + let mut counter = 0; + loop { + self.simulate_sand(&mut grid); + counter += 1; + if grid.get(&STARTING_COORD.x, &STARTING_COORD.y) == &Cell::Sand { + return counter.to_string() + } + // grid.print_range(495, 505, 0, 10); + + } + } +} + +#[derive(Debug)] +struct Platform { + coords: Vec> +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum Cell { + Empty, Wall, Sand +} + +impl Display for Cell { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}", + match self { + Cell::Empty => ".", + Cell::Wall => "#", + Cell::Sand => "o" + } + ) + } +} + +#[derive(Debug, Clone, PartialEq, Eq)] +enum SimulationResult { + FellOff, + EndedAt(Coord) +} \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 0e12a30..81a5052 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,6 +12,7 @@ use crate::day10::Day10; use crate::day11::Day11; use crate::day12::Day12; use crate::day13::Day13; +use crate::day14::Day14; use crate::day_solver::DaySolver; mod util; @@ -29,8 +30,9 @@ mod day10; mod day11; mod day12; mod day13; +mod day14; -const MAX_DAY: u8 = 12; +const MAX_DAY: u8 = 14; const DEFAULT_BENCHMARK_AMOUNT: u32 = 100; fn main() { @@ -107,6 +109,7 @@ fn build_day_solver(day: u8) -> Option> { 11 => Some(Box::new(Day11::create())), 12 => Some(Box::new(Day12::create())), 13 => Some(Box::new(Day13::create())), + 14 => Some(Box::new(Day14::create())), _ => None } } diff --git a/src/util.rs b/src/util.rs index deb527c..c3bdbdd 100644 --- a/src/util.rs +++ b/src/util.rs @@ -22,15 +22,15 @@ pub struct Grid { impl Grid { #[allow(dead_code)] - fn set_row(&mut self, x: usize, v: T) { + pub fn set_row(&mut self, y: usize, v: T) { // let range = &mut self.data[x * self.width..(x+1) * self.width]; - for i in self.width * x..self.width * (x + 1) { + for i in self.width * y..self.width * (y + 1) { self.data[i] = v.to_owned(); } } #[allow(dead_code)] - fn set_col(&mut self, x: usize, v: T) { + pub fn set_col(&mut self, x: usize, v: T) { for y in 0..self.height() { let idx = self.idx(&x, &y); self.data[idx] = v.to_owned(); @@ -48,21 +48,37 @@ impl Grid { pub(crate) fn get(&self, x: &usize, y: &usize) -> &T { let idx = self.idx(x, y); &self.data[idx] + } + pub fn set(&mut self, x: &usize, y: &usize, v: T) { + let idx = self.idx(x, y); + self.data[idx] = v; } } impl Grid { #[allow(dead_code)] - fn print(&self) { + pub fn print(&self) { - for y in 0..self.height() { - for x in 0..self.width { + self.print_range(0, self.width, 0, self.height()); + } + + #[allow(dead_code)] + pub fn print_range(&self, from_x: usize, to_x: usize, from_y: usize, to_y: usize) { + + for y in from_y.max(0)..to_y.min(self.height()) { + for x in from_x.max(0)..to_x.min(self.width) { print!("{}", self.get(&x, &y)) } println!(); } - } -} \ No newline at end of file +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct Coord where T: Sized { + pub x: T, + pub y: T +} +