add day 14, part 2

This commit is contained in:
Christian Ulrich 2022-12-15 18:03:47 +01:00
parent b9dfe81435
commit 48692bada7
No known key found for this signature in database
GPG Key ID: 8241BE099775A097
3 changed files with 63 additions and 15 deletions

View File

@ -19,6 +19,7 @@ use std::ops::Range;
pub struct CaveScan {
tiles: Vec<Vec<bool>>,
origin: (usize, usize),
bottom: Option<usize>,
x_window: Range<usize>,
y_window: Range<usize>,
}
@ -42,12 +43,13 @@ impl CaveScan {
}
}
pub fn from_stdin(origin: (usize, usize)) -> Result<CaveScan, &'static str> {
pub fn from_stdin(origin: (usize, usize), has_bottom: bool) -> Result<CaveScan, &'static str> {
const ERROR: &str = "input file contains invalid line";
let mut result = Self {
tiles: vec![vec![false]],
origin: origin,
bottom: None,
x_window: origin.0..origin.0,
y_window: origin.1..origin.1,
};
@ -78,14 +80,22 @@ impl CaveScan {
}
}
}
if has_bottom {
result.bottom = Some(result.tiles.len() + 1);
}
Ok(result)
}
fn bottom(&self) -> usize {
self.tiles.len()
fn dimensions(&self) -> (usize, usize) {
(self.tiles[0].len(), self.tiles.len())
}
fn tile(&self, pos: (usize, usize)) -> bool {
if let Some(bottom) = self.bottom {
if pos.1 == bottom {
return true;
}
}
if pos.0 < self.x_window.start
|| pos.0 > self.x_window.end
|| pos.1 < self.y_window.start
@ -120,24 +130,33 @@ impl CaveScan {
self.tiles = [&head[..], &self.tiles[..], &tail[..]].concat();
self.y_window = new_y_window;
}
self.tiles[pos.1 - self.y_window.start][pos.0 - self.x_window.start] = value;
}
fn step_down(&self, origin: (usize, usize)) -> Option<(usize, usize)> {
fn step_down(&mut self, origin: (usize, usize)) -> Option<(usize, usize)> {
let down_pos = (origin.0, origin.1.checked_add(1)?);
let down_left_pos = (origin.0.checked_sub(1)?, down_pos.1);
let down_right_pos = (origin.0.checked_add(1)?, down_pos.1);
let down = self.tile(down_pos);
let down_left = self.tile(down_left_pos);
let down_right = self.tile(down_right_pos);
let result = match (
self.tile(down_left_pos),
self.tile(down_pos),
self.tile(down_right_pos),
) {
let result = match (down_left, down, down_right) {
(_, false, _) => Some(down_pos),
(false, true, _) => Some(down_left_pos),
(true, true, false) => Some(down_right_pos),
(true, true, true) => None,
(true, true, true) => {
self.set_tile(origin, true);
None
}
};
if let (None, Some(result)) = (self.bottom, result) {
if result.1 == self.dimensions().1 {
return Some((result.0, usize::MAX));
}
}
result
}
@ -153,11 +172,7 @@ impl Iterator for Falls<'_> {
let mut result = self.scan.origin;
while let Some(pos) = self.scan.step_down(result) {
result = pos;
if result.1 == self.scan.bottom() {
return Some((result.0, usize::MAX));
}
}
self.scan.set_tile(result, true);
Some(result)
}
}

View File

@ -20,7 +20,7 @@ pub mod common;
use common::CaveScan;
fn main() -> Result<(), &'static str> {
let mut scan = CaveScan::from_stdin((500, 0))?;
let mut scan = CaveScan::from_stdin((500, 0), false)?;
let mut result = 0;
for end_pos in scan.falls() {
match end_pos {

33
day14/part2.rs Normal file
View File

@ -0,0 +1,33 @@
// Copyright 2022 Christian Ulrich
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// usage: ./part2 < input
pub mod common;
use common::CaveScan;
fn main() -> Result<(), &'static str> {
let mut scan = CaveScan::from_stdin((500, 0), true)?;
let mut result = 1;
for end_pos in scan.falls() {
match end_pos {
(500, 0) => break,
_ => result += 1,
}
}
println!("{result}");
Ok(())
}