Solving
This commit is contained in:
parent
fad59a04ce
commit
be5ff660dd
123
day14/input
Normal file
123
day14/input
Normal file
|
@ -0,0 +1,123 @@
|
|||
512,122 -> 512,118 -> 512,122 -> 514,122 -> 514,120 -> 514,122 -> 516,122 -> 516,121 -> 516,122
|
||||
503,45 -> 503,41 -> 503,45 -> 505,45 -> 505,43 -> 505,45 -> 507,45 -> 507,37 -> 507,45 -> 509,45 -> 509,35 -> 509,45 -> 511,45 -> 511,37 -> 511,45
|
||||
516,125 -> 516,129 -> 515,129 -> 515,136 -> 526,136 -> 526,129 -> 519,129 -> 519,125
|
||||
503,45 -> 503,41 -> 503,45 -> 505,45 -> 505,43 -> 505,45 -> 507,45 -> 507,37 -> 507,45 -> 509,45 -> 509,35 -> 509,45 -> 511,45 -> 511,37 -> 511,45
|
||||
512,122 -> 512,118 -> 512,122 -> 514,122 -> 514,120 -> 514,122 -> 516,122 -> 516,121 -> 516,122
|
||||
511,86 -> 515,86
|
||||
485,22 -> 489,22
|
||||
508,62 -> 508,56 -> 508,62 -> 510,62 -> 510,52 -> 510,62 -> 512,62 -> 512,60 -> 512,62 -> 514,62 -> 514,58 -> 514,62 -> 516,62 -> 516,55 -> 516,62
|
||||
509,150 -> 513,150
|
||||
516,65 -> 516,69 -> 508,69 -> 508,74 -> 521,74 -> 521,69 -> 520,69 -> 520,65
|
||||
503,45 -> 503,41 -> 503,45 -> 505,45 -> 505,43 -> 505,45 -> 507,45 -> 507,37 -> 507,45 -> 509,45 -> 509,35 -> 509,45 -> 511,45 -> 511,37 -> 511,45
|
||||
494,157 -> 494,159 -> 491,159 -> 491,167 -> 503,167 -> 503,159 -> 499,159 -> 499,157
|
||||
494,157 -> 494,159 -> 491,159 -> 491,167 -> 503,167 -> 503,159 -> 499,159 -> 499,157
|
||||
512,139 -> 512,142 -> 509,142 -> 509,145 -> 521,145 -> 521,142 -> 517,142 -> 517,139
|
||||
512,139 -> 512,142 -> 509,142 -> 509,145 -> 521,145 -> 521,142 -> 517,142 -> 517,139
|
||||
503,45 -> 503,41 -> 503,45 -> 505,45 -> 505,43 -> 505,45 -> 507,45 -> 507,37 -> 507,45 -> 509,45 -> 509,35 -> 509,45 -> 511,45 -> 511,37 -> 511,45
|
||||
503,45 -> 503,41 -> 503,45 -> 505,45 -> 505,43 -> 505,45 -> 507,45 -> 507,37 -> 507,45 -> 509,45 -> 509,35 -> 509,45 -> 511,45 -> 511,37 -> 511,45
|
||||
494,24 -> 498,24
|
||||
516,65 -> 516,69 -> 508,69 -> 508,74 -> 521,74 -> 521,69 -> 520,69 -> 520,65
|
||||
494,157 -> 494,159 -> 491,159 -> 491,167 -> 503,167 -> 503,159 -> 499,159 -> 499,157
|
||||
497,154 -> 501,154
|
||||
508,62 -> 508,56 -> 508,62 -> 510,62 -> 510,52 -> 510,62 -> 512,62 -> 512,60 -> 512,62 -> 514,62 -> 514,58 -> 514,62 -> 516,62 -> 516,55 -> 516,62
|
||||
523,80 -> 527,80
|
||||
512,139 -> 512,142 -> 509,142 -> 509,145 -> 521,145 -> 521,142 -> 517,142 -> 517,139
|
||||
505,17 -> 510,17
|
||||
510,104 -> 510,96 -> 510,104 -> 512,104 -> 512,101 -> 512,104 -> 514,104 -> 514,100 -> 514,104 -> 516,104 -> 516,103 -> 516,104
|
||||
498,17 -> 503,17
|
||||
512,122 -> 512,118 -> 512,122 -> 514,122 -> 514,120 -> 514,122 -> 516,122 -> 516,121 -> 516,122
|
||||
512,139 -> 512,142 -> 509,142 -> 509,145 -> 521,145 -> 521,142 -> 517,142 -> 517,139
|
||||
494,157 -> 494,159 -> 491,159 -> 491,167 -> 503,167 -> 503,159 -> 499,159 -> 499,157
|
||||
516,125 -> 516,129 -> 515,129 -> 515,136 -> 526,136 -> 526,129 -> 519,129 -> 519,125
|
||||
510,104 -> 510,96 -> 510,104 -> 512,104 -> 512,101 -> 512,104 -> 514,104 -> 514,100 -> 514,104 -> 516,104 -> 516,103 -> 516,104
|
||||
516,125 -> 516,129 -> 515,129 -> 515,136 -> 526,136 -> 526,129 -> 519,129 -> 519,125
|
||||
509,31 -> 509,32 -> 513,32 -> 513,31
|
||||
504,90 -> 504,91 -> 513,91 -> 513,90
|
||||
493,48 -> 493,49 -> 512,49 -> 512,48
|
||||
479,26 -> 483,26
|
||||
488,24 -> 492,24
|
||||
512,152 -> 516,152
|
||||
491,26 -> 495,26
|
||||
493,48 -> 493,49 -> 512,49 -> 512,48
|
||||
503,45 -> 503,41 -> 503,45 -> 505,45 -> 505,43 -> 505,45 -> 507,45 -> 507,37 -> 507,45 -> 509,45 -> 509,35 -> 509,45 -> 511,45 -> 511,37 -> 511,45
|
||||
512,122 -> 512,118 -> 512,122 -> 514,122 -> 514,120 -> 514,122 -> 516,122 -> 516,121 -> 516,122
|
||||
517,80 -> 521,80
|
||||
510,104 -> 510,96 -> 510,104 -> 512,104 -> 512,101 -> 512,104 -> 514,104 -> 514,100 -> 514,104 -> 516,104 -> 516,103 -> 516,104
|
||||
503,45 -> 503,41 -> 503,45 -> 505,45 -> 505,43 -> 505,45 -> 507,45 -> 507,37 -> 507,45 -> 509,45 -> 509,35 -> 509,45 -> 511,45 -> 511,37 -> 511,45
|
||||
508,62 -> 508,56 -> 508,62 -> 510,62 -> 510,52 -> 510,62 -> 512,62 -> 512,60 -> 512,62 -> 514,62 -> 514,58 -> 514,62 -> 516,62 -> 516,55 -> 516,62
|
||||
494,157 -> 494,159 -> 491,159 -> 491,167 -> 503,167 -> 503,159 -> 499,159 -> 499,157
|
||||
514,83 -> 518,83
|
||||
510,104 -> 510,96 -> 510,104 -> 512,104 -> 512,101 -> 512,104 -> 514,104 -> 514,100 -> 514,104 -> 516,104 -> 516,103 -> 516,104
|
||||
510,104 -> 510,96 -> 510,104 -> 512,104 -> 512,101 -> 512,104 -> 514,104 -> 514,100 -> 514,104 -> 516,104 -> 516,103 -> 516,104
|
||||
529,86 -> 533,86
|
||||
526,83 -> 530,83
|
||||
497,13 -> 502,13
|
||||
516,108 -> 516,109 -> 520,109 -> 520,108
|
||||
512,139 -> 512,142 -> 509,142 -> 509,145 -> 521,145 -> 521,142 -> 517,142 -> 517,139
|
||||
516,125 -> 516,129 -> 515,129 -> 515,136 -> 526,136 -> 526,129 -> 519,129 -> 519,125
|
||||
508,62 -> 508,56 -> 508,62 -> 510,62 -> 510,52 -> 510,62 -> 512,62 -> 512,60 -> 512,62 -> 514,62 -> 514,58 -> 514,62 -> 516,62 -> 516,55 -> 516,62
|
||||
503,154 -> 507,154
|
||||
494,15 -> 499,15
|
||||
520,77 -> 524,77
|
||||
506,152 -> 510,152
|
||||
516,65 -> 516,69 -> 508,69 -> 508,74 -> 521,74 -> 521,69 -> 520,69 -> 520,65
|
||||
516,65 -> 516,69 -> 508,69 -> 508,74 -> 521,74 -> 521,69 -> 520,69 -> 520,65
|
||||
503,45 -> 503,41 -> 503,45 -> 505,45 -> 505,43 -> 505,45 -> 507,45 -> 507,37 -> 507,45 -> 509,45 -> 509,35 -> 509,45 -> 511,45 -> 511,37 -> 511,45
|
||||
494,157 -> 494,159 -> 491,159 -> 491,167 -> 503,167 -> 503,159 -> 499,159 -> 499,157
|
||||
512,139 -> 512,142 -> 509,142 -> 509,145 -> 521,145 -> 521,142 -> 517,142 -> 517,139
|
||||
508,62 -> 508,56 -> 508,62 -> 510,62 -> 510,52 -> 510,62 -> 512,62 -> 512,60 -> 512,62 -> 514,62 -> 514,58 -> 514,62 -> 516,62 -> 516,55 -> 516,62
|
||||
493,48 -> 493,49 -> 512,49 -> 512,48
|
||||
510,104 -> 510,96 -> 510,104 -> 512,104 -> 512,101 -> 512,104 -> 514,104 -> 514,100 -> 514,104 -> 516,104 -> 516,103 -> 516,104
|
||||
516,108 -> 516,109 -> 520,109 -> 520,108
|
||||
512,122 -> 512,118 -> 512,122 -> 514,122 -> 514,120 -> 514,122 -> 516,122 -> 516,121 -> 516,122
|
||||
508,62 -> 508,56 -> 508,62 -> 510,62 -> 510,52 -> 510,62 -> 512,62 -> 512,60 -> 512,62 -> 514,62 -> 514,58 -> 514,62 -> 516,62 -> 516,55 -> 516,62
|
||||
503,45 -> 503,41 -> 503,45 -> 505,45 -> 505,43 -> 505,45 -> 507,45 -> 507,37 -> 507,45 -> 509,45 -> 509,35 -> 509,45 -> 511,45 -> 511,37 -> 511,45
|
||||
503,45 -> 503,41 -> 503,45 -> 505,45 -> 505,43 -> 505,45 -> 507,45 -> 507,37 -> 507,45 -> 509,45 -> 509,35 -> 509,45 -> 511,45 -> 511,37 -> 511,45
|
||||
508,62 -> 508,56 -> 508,62 -> 510,62 -> 510,52 -> 510,62 -> 512,62 -> 512,60 -> 512,62 -> 514,62 -> 514,58 -> 514,62 -> 516,62 -> 516,55 -> 516,62
|
||||
508,62 -> 508,56 -> 508,62 -> 510,62 -> 510,52 -> 510,62 -> 512,62 -> 512,60 -> 512,62 -> 514,62 -> 514,58 -> 514,62 -> 516,62 -> 516,55 -> 516,62
|
||||
508,62 -> 508,56 -> 508,62 -> 510,62 -> 510,52 -> 510,62 -> 512,62 -> 512,60 -> 512,62 -> 514,62 -> 514,58 -> 514,62 -> 516,62 -> 516,55 -> 516,62
|
||||
488,20 -> 492,20
|
||||
500,152 -> 504,152
|
||||
509,31 -> 509,32 -> 513,32 -> 513,31
|
||||
509,154 -> 513,154
|
||||
503,45 -> 503,41 -> 503,45 -> 505,45 -> 505,43 -> 505,45 -> 507,45 -> 507,37 -> 507,45 -> 509,45 -> 509,35 -> 509,45 -> 511,45 -> 511,37 -> 511,45
|
||||
508,62 -> 508,56 -> 508,62 -> 510,62 -> 510,52 -> 510,62 -> 512,62 -> 512,60 -> 512,62 -> 514,62 -> 514,58 -> 514,62 -> 516,62 -> 516,55 -> 516,62
|
||||
516,125 -> 516,129 -> 515,129 -> 515,136 -> 526,136 -> 526,129 -> 519,129 -> 519,125
|
||||
523,86 -> 527,86
|
||||
516,125 -> 516,129 -> 515,129 -> 515,136 -> 526,136 -> 526,129 -> 519,129 -> 519,125
|
||||
491,22 -> 495,22
|
||||
497,26 -> 501,26
|
||||
506,148 -> 510,148
|
||||
516,65 -> 516,69 -> 508,69 -> 508,74 -> 521,74 -> 521,69 -> 520,69 -> 520,65
|
||||
512,122 -> 512,118 -> 512,122 -> 514,122 -> 514,120 -> 514,122 -> 516,122 -> 516,121 -> 516,122
|
||||
503,45 -> 503,41 -> 503,45 -> 505,45 -> 505,43 -> 505,45 -> 507,45 -> 507,37 -> 507,45 -> 509,45 -> 509,35 -> 509,45 -> 511,45 -> 511,37 -> 511,45
|
||||
510,104 -> 510,96 -> 510,104 -> 512,104 -> 512,101 -> 512,104 -> 514,104 -> 514,100 -> 514,104 -> 516,104 -> 516,103 -> 516,104
|
||||
510,104 -> 510,96 -> 510,104 -> 512,104 -> 512,101 -> 512,104 -> 514,104 -> 514,100 -> 514,104 -> 516,104 -> 516,103 -> 516,104
|
||||
503,45 -> 503,41 -> 503,45 -> 505,45 -> 505,43 -> 505,45 -> 507,45 -> 507,37 -> 507,45 -> 509,45 -> 509,35 -> 509,45 -> 511,45 -> 511,37 -> 511,45
|
||||
508,62 -> 508,56 -> 508,62 -> 510,62 -> 510,52 -> 510,62 -> 512,62 -> 512,60 -> 512,62 -> 514,62 -> 514,58 -> 514,62 -> 516,62 -> 516,55 -> 516,62
|
||||
494,157 -> 494,159 -> 491,159 -> 491,167 -> 503,167 -> 503,159 -> 499,159 -> 499,157
|
||||
516,108 -> 516,109 -> 520,109 -> 520,108
|
||||
501,15 -> 506,15
|
||||
516,125 -> 516,129 -> 515,129 -> 515,136 -> 526,136 -> 526,129 -> 519,129 -> 519,125
|
||||
491,17 -> 496,17
|
||||
516,65 -> 516,69 -> 508,69 -> 508,74 -> 521,74 -> 521,69 -> 520,69 -> 520,65
|
||||
508,62 -> 508,56 -> 508,62 -> 510,62 -> 510,52 -> 510,62 -> 512,62 -> 512,60 -> 512,62 -> 514,62 -> 514,58 -> 514,62 -> 516,62 -> 516,55 -> 516,62
|
||||
512,122 -> 512,118 -> 512,122 -> 514,122 -> 514,120 -> 514,122 -> 516,122 -> 516,121 -> 516,122
|
||||
512,139 -> 512,142 -> 509,142 -> 509,145 -> 521,145 -> 521,142 -> 517,142 -> 517,139
|
||||
504,90 -> 504,91 -> 513,91 -> 513,90
|
||||
503,45 -> 503,41 -> 503,45 -> 505,45 -> 505,43 -> 505,45 -> 507,45 -> 507,37 -> 507,45 -> 509,45 -> 509,35 -> 509,45 -> 511,45 -> 511,37 -> 511,45
|
||||
508,62 -> 508,56 -> 508,62 -> 510,62 -> 510,52 -> 510,62 -> 512,62 -> 512,60 -> 512,62 -> 514,62 -> 514,58 -> 514,62 -> 516,62 -> 516,55 -> 516,62
|
||||
482,24 -> 486,24
|
||||
510,104 -> 510,96 -> 510,104 -> 512,104 -> 512,101 -> 512,104 -> 514,104 -> 514,100 -> 514,104 -> 516,104 -> 516,103 -> 516,104
|
||||
509,31 -> 509,32 -> 513,32 -> 513,31
|
||||
516,65 -> 516,69 -> 508,69 -> 508,74 -> 521,74 -> 521,69 -> 520,69 -> 520,65
|
||||
512,122 -> 512,118 -> 512,122 -> 514,122 -> 514,120 -> 514,122 -> 516,122 -> 516,121 -> 516,122
|
||||
515,154 -> 519,154
|
||||
517,86 -> 521,86
|
||||
485,26 -> 489,26
|
||||
504,90 -> 504,91 -> 513,91 -> 513,90
|
||||
510,104 -> 510,96 -> 510,104 -> 512,104 -> 512,101 -> 512,104 -> 514,104 -> 514,100 -> 514,104 -> 516,104 -> 516,103 -> 516,104
|
||||
510,104 -> 510,96 -> 510,104 -> 512,104 -> 512,101 -> 512,104 -> 514,104 -> 514,100 -> 514,104 -> 516,104 -> 516,103 -> 516,104
|
||||
503,150 -> 507,150
|
||||
520,83 -> 524,83
|
||||
508,62 -> 508,56 -> 508,62 -> 510,62 -> 510,52 -> 510,62 -> 512,62 -> 512,60 -> 512,62 -> 514,62 -> 514,58 -> 514,62 -> 516,62 -> 516,55 -> 516,62
|
2
day14/input.test
Normal file
2
day14/input.test
Normal file
|
@ -0,0 +1,2 @@
|
|||
498,4 -> 498,6 -> 496,6
|
||||
503,4 -> 502,4 -> 502,9 -> 494,9
|
242
day14/src/cave.rs
Normal file
242
day14/src/cave.rs
Normal file
|
@ -0,0 +1,242 @@
|
|||
use std::ops::{Index, IndexMut, Sub};
|
||||
|
||||
const SOURCE: Point = Point::new(500, 0);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum Material {
|
||||
Air,
|
||||
Stone,
|
||||
Sand,
|
||||
}
|
||||
|
||||
pub enum InsertResult {
|
||||
Ok,
|
||||
Overflow,
|
||||
}
|
||||
|
||||
pub enum GravityApplyResult {
|
||||
Moved,
|
||||
Fixed,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct Point([u16; 2]);
|
||||
|
||||
impl Point {
|
||||
const MAX: Self = Point::new(u16::MAX, u16::MAX);
|
||||
const MIN: Self = Point::new(u16::MIN, u16::MIN);
|
||||
|
||||
pub const fn new(x: u16, y: u16) -> Self {
|
||||
Self::from([x, y])
|
||||
}
|
||||
|
||||
pub const fn maximize(&self, other: &Self) -> Self {
|
||||
let sx = self.0[0];
|
||||
let sy = self.0[1];
|
||||
let ox = other.0[0];
|
||||
let oy = other.0[1];
|
||||
Point::new(sx.max(ox), sy.max(oy))
|
||||
}
|
||||
|
||||
pub const fn minimize(&self, other: &Self) -> Self {
|
||||
let sx = self.0[0];
|
||||
let sy = self.0[1];
|
||||
let ox = other.0[0];
|
||||
let oy = other.0[1];
|
||||
Point::new(sx.min(ox), sy.min(oy))
|
||||
}
|
||||
|
||||
pub const fn x(&self) -> u16 {
|
||||
self.0[0]
|
||||
}
|
||||
|
||||
pub const fn y(&self) -> u16 {
|
||||
self.0[1]
|
||||
}
|
||||
|
||||
pub fn x_mut(&mut self) -> &mut u16 {
|
||||
&mut self.0[0]
|
||||
}
|
||||
|
||||
pub fn y_mut(&mut self) -> &mut u16 {
|
||||
&mut self.0[1]
|
||||
}
|
||||
|
||||
fn line_to(&self, other: &Point) -> Box<dyn Iterator<Item = Self>> {
|
||||
let sx = self.0[0];
|
||||
let sy = self.0[1];
|
||||
let ox = other.0[0];
|
||||
let oy = other.0[1];
|
||||
if sx.abs_diff(ox) > 0 {
|
||||
Box::from((sx.min(ox)..=sx.max(ox)).map(move |new_x| Point::new(new_x, sy)))
|
||||
} else {
|
||||
Box::from((sy.min(oy)..=sy.max(oy)).map(move |new_y| Point::new(sx, new_y)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Cave {
|
||||
min: Point,
|
||||
max: Point,
|
||||
grid: Vec<Material>,
|
||||
}
|
||||
|
||||
impl Cave {
|
||||
pub fn from_span(min: Point, max: Point) -> Self {
|
||||
let width = (max.x() - min.x()) as usize + 1;
|
||||
let height = (max.y() - min.y()) as usize + 1;
|
||||
let grid: Vec<Material> = ::std::iter::repeat(Material::Air)
|
||||
.take(width * height)
|
||||
.collect();
|
||||
Cave { min, max, grid }
|
||||
}
|
||||
|
||||
pub fn get(&self, index: Point) -> &Material {
|
||||
let normalized = index - self.min;
|
||||
let idx = normalized.x() as usize + normalized.y() as usize * self.width() as usize;
|
||||
&self.grid[idx]
|
||||
}
|
||||
|
||||
fn get_mut(&mut self, index: Point) -> &mut Material {
|
||||
let normalized = index - self.min;
|
||||
let idx = normalized.x() as usize + normalized.y() as usize * self.width() as usize;
|
||||
&mut self.grid[idx]
|
||||
}
|
||||
|
||||
fn width(&self) -> u16 {
|
||||
self.max.x() - self.min.x() + 1
|
||||
}
|
||||
|
||||
pub fn insert_sand(&mut self) -> InsertResult {
|
||||
let mut pos = SOURCE;
|
||||
while self.is_in_bounds(pos) {
|
||||
match self.apply_gravity(&mut pos) {
|
||||
GravityApplyResult::Moved => {}
|
||||
GravityApplyResult::Fixed => {
|
||||
self[pos] = Material::Sand;
|
||||
return InsertResult::Ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
InsertResult::Overflow
|
||||
}
|
||||
|
||||
fn is_in_bounds(&self, pos: Point) -> bool {
|
||||
self.min.x() <= pos.x()
|
||||
&& self.min.y() <= pos.y()
|
||||
&& self.max.x() >= pos.x()
|
||||
&& self.max.y() >= pos.y()
|
||||
}
|
||||
|
||||
fn apply_gravity(&self, pos: &mut Point) -> GravityApplyResult {
|
||||
if pos.y() == self.max.y() {
|
||||
*pos.y_mut() += 1;
|
||||
GravityApplyResult::Moved
|
||||
} else if let Material::Air = &self[Point::new(pos.x(), pos.y().saturating_add(1))] {
|
||||
*pos.y_mut() += 1;
|
||||
GravityApplyResult::Moved
|
||||
} else if let Material::Air =
|
||||
&self[Point::new(pos.x().saturating_sub(1), pos.y().saturating_add(1))]
|
||||
{
|
||||
*pos.y_mut() += 1;
|
||||
*pos.x_mut() -= 1;
|
||||
GravityApplyResult::Moved
|
||||
} else if let Material::Air =
|
||||
&self[Point::new(pos.x().saturating_add(1), pos.y().saturating_add(1))]
|
||||
{
|
||||
*pos.y_mut() += 1;
|
||||
*pos.x_mut() += 1;
|
||||
GravityApplyResult::Moved
|
||||
} else {
|
||||
GravityApplyResult::Fixed
|
||||
}
|
||||
}
|
||||
|
||||
fn height(&self) -> u16 {
|
||||
self.max.y() - self.min.y() + 1
|
||||
}
|
||||
}
|
||||
|
||||
impl FromIterator<Vec<Point>> for Cave {
|
||||
fn from_iter<T: IntoIterator<Item = Vec<Point>>>(iter: T) -> Self {
|
||||
let (stone_points, min, max) = iter.into_iter().fold(
|
||||
(vec![], Point::MAX, Point::MIN),
|
||||
|(mut stone_points, mut min, mut max), points| {
|
||||
let mut last: Option<Point> = None;
|
||||
for point in points {
|
||||
min = point.minimize(&min);
|
||||
max = point.maximize(&max);
|
||||
match last {
|
||||
Some(last) => stone_points.extend(last.line_to(&point)),
|
||||
// Push the first point manually
|
||||
None => stone_points.push(point.clone()),
|
||||
}
|
||||
last = Some(point);
|
||||
}
|
||||
(stone_points, min, max)
|
||||
},
|
||||
);
|
||||
let min = min.minimize(&SOURCE);
|
||||
let max = max.maximize(&SOURCE);
|
||||
let min = Point::new(min.x().saturating_sub(1), min.y().saturating_sub(1));
|
||||
let max = Point::new(max.x().saturating_add(1), max.y().saturating_add(1));
|
||||
let mut cave = Cave::from_span(min, max);
|
||||
for point in stone_points {
|
||||
cave[point] = Material::Stone;
|
||||
}
|
||||
println!("{cave}");
|
||||
cave
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<Point> for Cave {
|
||||
type Output = Material;
|
||||
|
||||
fn index(&self, index: Point) -> &Self::Output {
|
||||
self.get(index)
|
||||
}
|
||||
}
|
||||
|
||||
impl IndexMut<Point> for Cave {
|
||||
fn index_mut(&mut self, index: Point) -> &mut Self::Output {
|
||||
self.get_mut(index)
|
||||
}
|
||||
}
|
||||
|
||||
impl const From<[u16; 2]> for Point {
|
||||
fn from(raw: [u16; 2]) -> Self {
|
||||
Self(raw)
|
||||
}
|
||||
}
|
||||
|
||||
impl const Sub for Point {
|
||||
type Output = Self;
|
||||
|
||||
fn sub(self, rhs: Self) -> Self::Output {
|
||||
Self::new(self.x() - rhs.x(), self.y() - rhs.y())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Cave {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for y in self.min.y()..=self.max.y() {
|
||||
for x in self.min.x()..=self.max.x() {
|
||||
if Point::new(x, y) == SOURCE {
|
||||
write!(f, "@")?;
|
||||
} else {
|
||||
write!(
|
||||
f,
|
||||
"{}",
|
||||
match self[Point::new(x, y)] {
|
||||
Material::Air => ".",
|
||||
Material::Sand => "o",
|
||||
Material::Stone => "#",
|
||||
}
|
||||
)?;
|
||||
}
|
||||
}
|
||||
writeln!(f)?;
|
||||
}
|
||||
writeln!(f)
|
||||
}
|
||||
}
|
|
@ -1,3 +1,86 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
#![feature(iter_array_chunks)]
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufRead, BufReader},
|
||||
};
|
||||
|
||||
use cave::{Cave, InsertResult, Point};
|
||||
|
||||
mod cave;
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq)]
|
||||
enum SolvePuzzle {
|
||||
First,
|
||||
#[default]
|
||||
Second,
|
||||
}
|
||||
|
||||
fn parse_line<S: AsRef<str>>(line: S) -> Vec<Point> {
|
||||
line.as_ref()
|
||||
.split(" -> ")
|
||||
.map(|pair| pair.split_once(','))
|
||||
.map(Option::unwrap)
|
||||
.flat_map(|(x, y)| [x, y])
|
||||
.map(|value| value.parse().unwrap())
|
||||
.array_chunks::<2>()
|
||||
.map(Point::from)
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn solve_first_puzzle<R: BufRead>(reader: R) -> usize {
|
||||
let mut cave: Cave = reader
|
||||
.lines()
|
||||
.map(Result::unwrap)
|
||||
.map(|line| parse_line(&line))
|
||||
.collect();
|
||||
let mut counter = 0;
|
||||
while let InsertResult::Ok = cave.insert_sand() {
|
||||
println!("{cave}");
|
||||
counter += 1;
|
||||
}
|
||||
counter
|
||||
}
|
||||
|
||||
fn solve_second_puzzle<R: BufRead>(reader: R) -> usize {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = ::std::env::args().skip(1);
|
||||
let file = args.next().unwrap_or_else(|| String::from("./input"));
|
||||
let solve = args
|
||||
.next()
|
||||
.map(|arg| match arg.as_str() {
|
||||
"first" => SolvePuzzle::First,
|
||||
"second" => SolvePuzzle::Second,
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let file = BufReader::new(File::open(file).expect("Opening file"));
|
||||
let solution = match solve {
|
||||
SolvePuzzle::First => solve_first_puzzle(file),
|
||||
SolvePuzzle::Second => solve_second_puzzle(file),
|
||||
};
|
||||
println!("{}", solution);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io::Cursor;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn example_on_first() {
|
||||
let reader = Cursor::new(include_str!("../input.test"));
|
||||
assert_eq!(solve_first_puzzle(reader), 24);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_on_second() {
|
||||
let reader = Cursor::new(include_str!("../input.test"));
|
||||
assert_eq!(solve_second_puzzle(reader), 140);
|
||||
}
|
||||
}
|
||||
|
|
14
day15/input.test
Normal file
14
day15/input.test
Normal file
|
@ -0,0 +1,14 @@
|
|||
Sensor at x=2, y=18: closest beacon is at x=-2, y=15
|
||||
Sensor at x=9, y=16: closest beacon is at x=10, y=16
|
||||
Sensor at x=13, y=2: closest beacon is at x=15, y=3
|
||||
Sensor at x=12, y=14: closest beacon is at x=10, y=16
|
||||
Sensor at x=10, y=20: closest beacon is at x=10, y=16
|
||||
Sensor at x=14, y=17: closest beacon is at x=10, y=16
|
||||
Sensor at x=8, y=7: closest beacon is at x=2, y=10
|
||||
Sensor at x=2, y=0: closest beacon is at x=2, y=10
|
||||
Sensor at x=0, y=11: closest beacon is at x=2, y=10
|
||||
Sensor at x=20, y=14: closest beacon is at x=25, y=17
|
||||
Sensor at x=17, y=20: closest beacon is at x=21, y=22
|
||||
Sensor at x=16, y=7: closest beacon is at x=15, y=3
|
||||
Sensor at x=14, y=3: closest beacon is at x=15, y=3
|
||||
Sensor at x=20, y=1: closest beacon is at x=15, y=3
|
58
day16/input
Normal file
58
day16/input
Normal file
|
@ -0,0 +1,58 @@
|
|||
Valve YK has flow rate=0; tunnels lead to valves GL, FT
|
||||
Valve QA has flow rate=0; tunnels lead to valves JX, FD
|
||||
Valve LN has flow rate=0; tunnels lead to valves FD, FG
|
||||
Valve AU has flow rate=0; tunnels lead to valves BD, PQ
|
||||
Valve MM has flow rate=0; tunnels lead to valves UL, AA
|
||||
Valve JX has flow rate=0; tunnels lead to valves QA, NZ
|
||||
Valve CV has flow rate=0; tunnels lead to valves UP, QW
|
||||
Valve UZ has flow rate=0; tunnels lead to valves FG, NZ
|
||||
Valve BP has flow rate=0; tunnels lead to valves TI, DX
|
||||
Valve NS has flow rate=0; tunnels lead to valves ZL, CW
|
||||
Valve CO has flow rate=0; tunnels lead to valves BD, AT
|
||||
Valve RZ has flow rate=0; tunnels lead to valves AA, ZO
|
||||
Valve PQ has flow rate=0; tunnels lead to valves ML, AU
|
||||
Valve CW has flow rate=7; tunnels lead to valves UL, PH, OF, NS, GT
|
||||
Valve FG has flow rate=14; tunnels lead to valves SO, JR, IN, LN, UZ
|
||||
Valve EZ has flow rate=0; tunnels lead to valves UP, QP
|
||||
Valve GN has flow rate=0; tunnels lead to valves VQ, CH
|
||||
Valve QW has flow rate=6; tunnels lead to valves CV, PF, KH, UY, TI
|
||||
Valve UL has flow rate=0; tunnels lead to valves MM, CW
|
||||
Valve VQ has flow rate=12; tunnels lead to valves GN, LC
|
||||
Valve FT has flow rate=0; tunnels lead to valves SG, YK
|
||||
Valve SG has flow rate=21; tunnels lead to valves FT, LC, NO, QX
|
||||
Valve BD has flow rate=23; tunnels lead to valves CO, AU, AB
|
||||
Valve AB has flow rate=0; tunnels lead to valves BD, QX
|
||||
Valve QP has flow rate=0; tunnels lead to valves AD, EZ
|
||||
Valve OF has flow rate=0; tunnels lead to valves DX, CW
|
||||
Valve AA has flow rate=0; tunnels lead to valves QL, RZ, SO, MM, HW
|
||||
Valve RQ has flow rate=0; tunnels lead to valves GL, QG
|
||||
Valve ZL has flow rate=0; tunnels lead to valves NS, FD
|
||||
Valve KH has flow rate=0; tunnels lead to valves GT, QW
|
||||
Valve JR has flow rate=0; tunnels lead to valves FG, PH
|
||||
Valve PH has flow rate=0; tunnels lead to valves CW, JR
|
||||
Valve LC has flow rate=0; tunnels lead to valves VQ, SG
|
||||
Valve FD has flow rate=20; tunnels lead to valves LN, QA, ZL
|
||||
Valve NZ has flow rate=15; tunnels lead to valves UZ, JX
|
||||
Valve ML has flow rate=22; tunnels lead to valves OW, PQ, NO
|
||||
Valve PF has flow rate=0; tunnels lead to valves QW, CH
|
||||
Valve UP has flow rate=19; tunnels lead to valves RY, CV, EZ
|
||||
Valve VM has flow rate=0; tunnels lead to valves RY, CH
|
||||
Valve DX has flow rate=3; tunnels lead to valves BO, QL, BP, OF, QG
|
||||
Valve QL has flow rate=0; tunnels lead to valves AA, DX
|
||||
Valve HW has flow rate=0; tunnels lead to valves UY, AA
|
||||
Valve GL has flow rate=8; tunnels lead to valves YK, RQ
|
||||
Valve QG has flow rate=0; tunnels lead to valves DX, RQ
|
||||
Valve IN has flow rate=0; tunnels lead to valves FG, BO
|
||||
Valve NO has flow rate=0; tunnels lead to valves SG, ML
|
||||
Valve SO has flow rate=0; tunnels lead to valves FG, AA
|
||||
Valve RY has flow rate=0; tunnels lead to valves UP, VM
|
||||
Valve CH has flow rate=13; tunnels lead to valves GN, VM, PF, ZO
|
||||
Valve AD has flow rate=17; tunnel leads to valve QP
|
||||
Valve TI has flow rate=0; tunnels lead to valves BP, QW
|
||||
Valve UY has flow rate=0; tunnels lead to valves HW, QW
|
||||
Valve AT has flow rate=24; tunnels lead to valves OW, CO
|
||||
Valve GT has flow rate=0; tunnels lead to valves CW, KH
|
||||
Valve ZO has flow rate=0; tunnels lead to valves RZ, CH
|
||||
Valve QX has flow rate=0; tunnels lead to valves AB, SG
|
||||
Valve BO has flow rate=0; tunnels lead to valves IN, DX
|
||||
Valve OW has flow rate=0; tunnels lead to valves AT, ML
|
10
day16/input.test
Normal file
10
day16/input.test
Normal file
|
@ -0,0 +1,10 @@
|
|||
Valve AA has flow rate=0; tunnels lead to valves DD, II, BB
|
||||
Valve BB has flow rate=13; tunnels lead to valves CC, AA
|
||||
Valve CC has flow rate=2; tunnels lead to valves DD, BB
|
||||
Valve DD has flow rate=20; tunnels lead to valves CC, AA, EE
|
||||
Valve EE has flow rate=3; tunnels lead to valves FF, DD
|
||||
Valve FF has flow rate=0; tunnels lead to valves EE, GG
|
||||
Valve GG has flow rate=0; tunnels lead to valves FF, HH
|
||||
Valve HH has flow rate=22; tunnel leads to valve GG
|
||||
Valve II has flow rate=0; tunnels lead to valves AA, JJ
|
||||
Valve JJ has flow rate=21; tunnel leads to valve II
|
1
day17/input
Normal file
1
day17/input
Normal file
File diff suppressed because one or more lines are too long
1
day17/input.test
Normal file
1
day17/input.test
Normal file
|
@ -0,0 +1 @@
|
|||
>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>
|
|
@ -1,3 +1,214 @@
|
|||
fn main() {
|
||||
println!("Hello, world!");
|
||||
#![feature(const_trait_impl)]
|
||||
|
||||
use std::{
|
||||
fs::File,
|
||||
io::{BufRead, BufReader},
|
||||
};
|
||||
|
||||
const CAVE_WIDTH: usize = 7;
|
||||
|
||||
#[derive(Debug, Default, PartialEq, Eq)]
|
||||
enum SolvePuzzle {
|
||||
First,
|
||||
#[default]
|
||||
Second,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum Wind {
|
||||
Left,
|
||||
Right,
|
||||
}
|
||||
|
||||
struct Cave {
|
||||
height_map: [usize; CAVE_WIDTH],
|
||||
wind: Vec<Wind>,
|
||||
wind_pos: usize,
|
||||
}
|
||||
impl Cave {
|
||||
pub fn max_height(&self) -> usize {
|
||||
self.height_map.iter().max().copied().unwrap()
|
||||
}
|
||||
|
||||
pub fn use_wind(&mut self) -> Wind {
|
||||
let wind = self.wind[self.wind_pos];
|
||||
self.wind_pos = (self.wind_pos + 1) % self.wind.len();
|
||||
wind
|
||||
}
|
||||
|
||||
pub fn drop(&mut self, piece: StrangRock) {
|
||||
let mut piece_height = self.max_height() + 4;
|
||||
let mut pos = 2_usize;
|
||||
eprintln!("{piece:>10?} {pos} {piece_height}");
|
||||
loop {
|
||||
match self.use_wind() {
|
||||
Wind::Left if pos > 0 => {
|
||||
let mut collision = false;
|
||||
for (offset_idx, offset) in piece.offsets().iter().enumerate() {
|
||||
if self.height_map[pos - 1 + offset_idx] >= piece_height + offset {
|
||||
collision = true;
|
||||
}
|
||||
}
|
||||
if !collision {
|
||||
pos = pos.saturating_sub(1);
|
||||
}
|
||||
}
|
||||
Wind::Right if pos < CAVE_WIDTH.saturating_sub(piece.width()) => {
|
||||
let mut collision = false;
|
||||
for (offset_idx, offset) in piece.offsets().iter().enumerate() {
|
||||
if self.height_map[pos + 1 + offset_idx] >= piece_height + offset {
|
||||
collision = true;
|
||||
}
|
||||
}
|
||||
if !collision {
|
||||
pos += 1;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
piece_height -= 1;
|
||||
eprintln!("{piece:>10?} {pos} {piece_height}");
|
||||
eprintln!(" - {:>2?} {:>2?}", self.height_map, piece.offsets());
|
||||
for (offset_idx, &offset) in piece.offsets().iter().enumerate() {
|
||||
let height_at_pos = self.height_map[pos + offset_idx];
|
||||
let piece_height = piece_height + offset;
|
||||
eprintln!(" - {offset_idx} {offset}: {height_at_pos} {piece_height}");
|
||||
if piece_height == height_at_pos {
|
||||
for (height_idx, &height) in piece.height_offsets().iter().enumerate() {
|
||||
let total_height = piece_height + height + 1;
|
||||
self.height_map[pos + height_idx] = total_height;
|
||||
}
|
||||
eprintln!(" == {:>2?} {:>2?}", self.height_map, piece.offsets());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum StrangRock {
|
||||
// ####
|
||||
Horizontal,
|
||||
// .#.
|
||||
// ###
|
||||
// .#.
|
||||
Plus,
|
||||
// ..#
|
||||
// ..#
|
||||
// ###
|
||||
Corner,
|
||||
// #
|
||||
// #
|
||||
// #
|
||||
// #
|
||||
Vertical,
|
||||
// ##
|
||||
// ##
|
||||
Square,
|
||||
}
|
||||
|
||||
impl StrangRock {
|
||||
const fn width(&self) -> usize {
|
||||
match self {
|
||||
StrangRock::Horizontal => 4,
|
||||
StrangRock::Plus => 3,
|
||||
StrangRock::Corner => 3,
|
||||
StrangRock::Vertical => 1,
|
||||
StrangRock::Square => 2,
|
||||
}
|
||||
}
|
||||
|
||||
fn offsets(&self) -> &[usize] {
|
||||
match self {
|
||||
StrangRock::Horizontal => &[0, 0, 0, 0],
|
||||
StrangRock::Plus => &[1, 0, 1],
|
||||
StrangRock::Corner => &[0, 0, 0],
|
||||
StrangRock::Vertical => &[0],
|
||||
StrangRock::Square => &[0, 0],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn height_offsets(&self) -> &[usize] {
|
||||
match self {
|
||||
StrangRock::Horizontal => &[0, 0, 0, 0],
|
||||
StrangRock::Plus => &[1, 2, 1],
|
||||
StrangRock::Corner => &[0, 0, 2],
|
||||
StrangRock::Vertical => &[3],
|
||||
StrangRock::Square => &[1, 1],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_input<R: BufRead>(reader: R) -> Cave {
|
||||
let wind = reader
|
||||
.bytes()
|
||||
.map(Result::unwrap)
|
||||
.filter(|&b| b == b'<' || b == b'>')
|
||||
.map(Wind::from)
|
||||
.collect();
|
||||
let wind_pos = 0;
|
||||
let height_map = [0; CAVE_WIDTH];
|
||||
Cave {
|
||||
height_map,
|
||||
wind,
|
||||
wind_pos,
|
||||
}
|
||||
}
|
||||
|
||||
fn solve_first_puzzle<R: BufRead>(reader: R) -> usize {
|
||||
let mut cave = read_input(reader);
|
||||
use StrangRock::*;
|
||||
let pieces = [Horizontal, Plus, Corner, Vertical, Square];
|
||||
for piece in pieces.into_iter().cycle().take(2022) {
|
||||
cave.drop(piece);
|
||||
}
|
||||
cave.max_height()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut args = ::std::env::args().skip(1);
|
||||
let file = args.next().unwrap_or_else(|| String::from("./input"));
|
||||
let solve = args
|
||||
.next()
|
||||
.map(|arg| match arg.as_str() {
|
||||
"first" => SolvePuzzle::First,
|
||||
"second" => SolvePuzzle::Second,
|
||||
_ => unreachable!(),
|
||||
})
|
||||
.unwrap_or_default();
|
||||
let file = BufReader::new(File::open(file).expect("Opening file"));
|
||||
match solve {
|
||||
SolvePuzzle::First => println!("{}", solve_first_puzzle(file)),
|
||||
_ => todo!(),
|
||||
};
|
||||
}
|
||||
|
||||
impl const From<u8> for Wind {
|
||||
fn from(raw: u8) -> Self {
|
||||
if raw == b'>' {
|
||||
Wind::Right
|
||||
} else {
|
||||
Wind::Left
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io::Cursor;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn example_on_first() {
|
||||
let reader = Cursor::new(include_str!("../input.test"));
|
||||
assert_eq!(solve_first_puzzle(reader), 3068);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn example_on_second() {
|
||||
let reader = Cursor::new(include_str!("../input.test"));
|
||||
// todo!()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue