This commit is contained in:
Malte Tammena 2022-12-18 07:32:51 +01:00
parent fad59a04ce
commit be5ff660dd
10 changed files with 749 additions and 4 deletions

123
day14/input Normal file
View 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
View 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
View 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)
}
}

View file

@ -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
View 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
View 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
View 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

File diff suppressed because one or more lines are too long

1
day17/input.test Normal file
View file

@ -0,0 +1 @@
>>><<><>><<<>><>>><<<>>><<<><<<>><>><<>>

View file

@ -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!()
}
}