Solve day 7
This commit is contained in:
@@ -38,6 +38,7 @@ Timings are given as: [lower-bound **best-estimate** upper-bound]
|
||||
| 04 | [143.40 µs **144.00 µs** 144.73 µs] | [1.6165 ms **1.6258 ms** 1.6355 ms] |
|
||||
| 05 | [187.25 µs **188.93 µs** 190.74 µs] | [63.809 µs **64.204 µs** 64.606 µs] |
|
||||
| 06 | [128.44 µs **129.44 µs** 130.52 µs] | [165.05 µs **165.70 µs** 166.36 µs] |
|
||||
| 07 | [83.803 µs **84.601 µs** 85.435 µs] | [81.456 µs **82.360 µs** 83.386 µs] |
|
||||
|
||||
## Profiling
|
||||
|
||||
|
||||
16
src/day07/input/test1.txt
Normal file
16
src/day07/input/test1.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
.......S.......
|
||||
...............
|
||||
.......^.......
|
||||
...............
|
||||
......^.^......
|
||||
...............
|
||||
.....^.^.^.....
|
||||
...............
|
||||
....^.^...^....
|
||||
...............
|
||||
...^.^...^.^...
|
||||
...............
|
||||
..^...^.....^..
|
||||
...............
|
||||
.^.^.^.^.^...^.
|
||||
...............
|
||||
180
src/day07/mod.rs
Normal file
180
src/day07/mod.rs
Normal file
@@ -0,0 +1,180 @@
|
||||
use std::{
|
||||
fmt::{Display, Formatter},
|
||||
str::FromStr,
|
||||
};
|
||||
|
||||
use color_eyre::{Result, eyre::eyre};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
pub const INPUT: &str = include_str!("input/input.txt");
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum Cell {
|
||||
Source,
|
||||
Splitter,
|
||||
Beam(usize),
|
||||
Empty,
|
||||
}
|
||||
|
||||
impl FromStr for Cell {
|
||||
type Err = color_eyre::Report;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"S" => Ok(Cell::Source),
|
||||
"^" => Ok(Cell::Splitter),
|
||||
"|" => Ok(Cell::Beam(1)),
|
||||
"." => Ok(Cell::Empty),
|
||||
_ => Err(eyre!("Invalid cell character: {}", s)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Cell {
|
||||
fn from_byte(b: u8) -> Result<Self, color_eyre::Report> {
|
||||
match b {
|
||||
b'S' => Ok(Cell::Source),
|
||||
b'^' => Ok(Cell::Splitter),
|
||||
b'|' => Ok(Cell::Beam(1)),
|
||||
b'.' => Ok(Cell::Empty),
|
||||
_ => Err(eyre!("Invalid cell byte: {}", b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct Grid<const R: usize, const C: usize> {
|
||||
cells: [[Cell; C]; R],
|
||||
splits: usize,
|
||||
}
|
||||
|
||||
impl<const R: usize, const C: usize> FromStr for Grid<R, C> {
|
||||
type Err = color_eyre::Report;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut cells = [[Cell::Empty; C]; R];
|
||||
|
||||
for (row, line) in s.lines().enumerate() {
|
||||
for (col, byte) in line.bytes().enumerate() {
|
||||
cells[row][col] = Cell::from_byte(byte)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Grid { cells, splits: 0 })
|
||||
}
|
||||
}
|
||||
|
||||
impl<const R: usize, const C: usize> Display for Grid<R, C> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
for row in 0..R {
|
||||
for col in 0..C {
|
||||
let symbol = match self.cells[row][col] {
|
||||
Cell::Source => 'S',
|
||||
Cell::Splitter => '^',
|
||||
Cell::Beam(t) => (b'0' + t as u8) as char,
|
||||
Cell::Empty => '.',
|
||||
};
|
||||
write!(f, "{}", symbol)?;
|
||||
}
|
||||
writeln!(f)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<const R: usize, const C: usize> Grid<R, C> {
|
||||
fn emit_beam(&mut self) {
|
||||
for row in 1..R {
|
||||
for col in 0..C {
|
||||
if matches!(self.cells[row][col], Cell::Beam(_)) {
|
||||
// already filled by a splitter to the left
|
||||
continue;
|
||||
}
|
||||
if matches!(self.cells[row - 1][col], Cell::Source | Cell::Beam(_)) {
|
||||
let timelines = match self.cells[row - 1][col] {
|
||||
Cell::Source => 1,
|
||||
Cell::Beam(t) => t,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
if self.cells[row][col] == Cell::Splitter {
|
||||
// assumption: splitter always has empty cells on left and right
|
||||
let left = self.cells[row][col - 1];
|
||||
let left_timelines = match self.cells[row - 1][col - 1] {
|
||||
Cell::Source => 1,
|
||||
Cell::Beam(t) => t,
|
||||
_ => 0,
|
||||
};
|
||||
if let Cell::Beam(left_t) = left {
|
||||
self.cells[row][col - 1] = Cell::Beam(timelines + left_t);
|
||||
} else {
|
||||
self.cells[row][col - 1] = Cell::Beam(timelines + left_timelines);
|
||||
}
|
||||
let right = self.cells[row][col + 1];
|
||||
let right_timelines = match self.cells[row - 1][col + 1] {
|
||||
Cell::Source => 1,
|
||||
Cell::Beam(t) => t,
|
||||
_ => 0,
|
||||
};
|
||||
if let Cell::Beam(right_t) = right {
|
||||
self.cells[row][col + 1] = Cell::Beam(timelines + right_t);
|
||||
} else {
|
||||
self.cells[row][col + 1] = Cell::Beam(timelines + right_timelines);
|
||||
}
|
||||
self.splits += 1;
|
||||
} else {
|
||||
self.cells[row][col] = Cell::Beam(timelines);
|
||||
}
|
||||
}
|
||||
}
|
||||
debug!("After row {}:\n{}", row, self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn solve_part1<const R: usize, const C: usize>(input: &str) -> Result<usize> {
|
||||
let mut grid = Grid::<R, C>::from_str(input)?;
|
||||
grid.emit_beam();
|
||||
Ok(grid.splits)
|
||||
}
|
||||
|
||||
#[instrument(skip(input))]
|
||||
pub fn part1(input: &str) -> Result<usize> {
|
||||
solve_part1::<142, 141>(input)
|
||||
}
|
||||
|
||||
fn solve_part2<const R: usize, const C: usize>(input: &str) -> Result<usize> {
|
||||
let mut grid = Grid::<R, C>::from_str(input)?;
|
||||
grid.emit_beam();
|
||||
Ok(grid.cells[R - 1]
|
||||
.into_iter()
|
||||
.map(|c| {
|
||||
if let Cell::Beam(timelines) = c {
|
||||
timelines
|
||||
} else {
|
||||
0
|
||||
}
|
||||
})
|
||||
.sum::<usize>())
|
||||
}
|
||||
|
||||
#[instrument(skip(input))]
|
||||
pub fn part2(input: &str) -> Result<usize> {
|
||||
solve_part2::<142, 141>(input)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use test_log::test;
|
||||
|
||||
const TEST_INPUT1: &str = include_str!("input/test1.txt");
|
||||
|
||||
#[test]
|
||||
fn test_part1() {
|
||||
assert_eq!(solve_part1::<16, 15>(TEST_INPUT1).unwrap(), 21);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_part2() {
|
||||
assert_eq!(solve_part2::<16, 15>(TEST_INPUT1).unwrap(), 40);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ macro_rules! all_days {
|
||||
4 => day04,
|
||||
5 => day05,
|
||||
6 => day06,
|
||||
7 => day07,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,4 +4,5 @@ pub mod day03;
|
||||
pub mod day04;
|
||||
pub mod day05;
|
||||
pub mod day06;
|
||||
pub mod day07;
|
||||
pub mod days;
|
||||
|
||||
Reference in New Issue
Block a user