day6 part1
This commit is contained in:
parent
35ba924c1b
commit
b79d418d4e
4 changed files with 253 additions and 1 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -31,6 +31,13 @@ dependencies = [
|
|||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "day06"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.4"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[workspace]
|
||||
resolver = "2"
|
||||
members = ["day01", "day02", "day03", "day04", "day05"]
|
||||
members = ["day01", "day02", "day03", "day04", "day05", "day06"]
|
||||
|
||||
[workspace.dependencies]
|
||||
winnow = "0.6"
|
||||
|
|
7
day06/Cargo.toml
Normal file
7
day06/Cargo.toml
Normal file
|
@ -0,0 +1,7 @@
|
|||
[package]
|
||||
name = "day06"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
winnow.workspace = true
|
238
day06/src/main.rs
Normal file
238
day06/src/main.rs
Normal file
|
@ -0,0 +1,238 @@
|
|||
use std::{
|
||||
collections::HashSet,
|
||||
fmt::{Display, Write},
|
||||
};
|
||||
|
||||
use winnow::{
|
||||
PResult, Parser,
|
||||
ascii::{newline, till_line_ending},
|
||||
combinator::{alt, repeat, separated},
|
||||
};
|
||||
|
||||
fn main() {
|
||||
let input = std::fs::read_to_string("input").unwrap();
|
||||
println!("{}", pt1(&input));
|
||||
println!("{}", pt2(&input));
|
||||
}
|
||||
|
||||
fn pt1(input: &str) -> usize {
|
||||
let mut board = Board::new(input);
|
||||
|
||||
board.run()
|
||||
}
|
||||
|
||||
fn pt2(input: &str) -> usize {
|
||||
0
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
|
||||
enum Dir {
|
||||
#[default]
|
||||
N,
|
||||
S,
|
||||
E,
|
||||
W,
|
||||
}
|
||||
|
||||
impl Dir {
|
||||
fn next(&self, loc: Loc) -> Loc {
|
||||
let Loc(r, c) = loc;
|
||||
let (nr, nc) = match self {
|
||||
Dir::N => (r.wrapping_sub(1), c),
|
||||
Dir::S => (r + 1, c),
|
||||
Dir::E => (r, c + 1),
|
||||
Dir::W => (r, c.wrapping_sub(1)),
|
||||
};
|
||||
Loc(nr, nc)
|
||||
}
|
||||
|
||||
fn rot(&self) -> Self {
|
||||
use Dir::*;
|
||||
match self {
|
||||
N => E,
|
||||
E => S,
|
||||
S => W,
|
||||
W => N,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
struct Loc(usize, usize);
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum Cell {
|
||||
Obstacle,
|
||||
Empty,
|
||||
Guard(Dir),
|
||||
Visited,
|
||||
}
|
||||
|
||||
impl Display for Cell {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
use Cell::*;
|
||||
use Dir::*;
|
||||
let c = match self {
|
||||
Obstacle => '#',
|
||||
Empty => '.',
|
||||
Visited => 'X',
|
||||
Guard(d) => match d {
|
||||
N => '^',
|
||||
E => '>',
|
||||
S => 'v',
|
||||
W => '<',
|
||||
},
|
||||
};
|
||||
f.write_char(c)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, PartialEq, Eq)]
|
||||
struct Board {
|
||||
cells: Vec<Vec<Cell>>,
|
||||
guard: (Loc, Dir),
|
||||
}
|
||||
|
||||
impl Display for Board {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(
|
||||
&self
|
||||
.cells
|
||||
.iter()
|
||||
//.map(|row| row.iter().map(|c| format!("{c}")).collect::<String>())
|
||||
.map(|row| {
|
||||
row.iter().fold(String::new(), |mut out, c| {
|
||||
let _ = write!(out, "{c}");
|
||||
out
|
||||
})
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n"),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Board {
|
||||
fn new(input: &str) -> Self {
|
||||
parse(input).unwrap()
|
||||
}
|
||||
|
||||
fn step(&mut self) -> Option<Loc> {
|
||||
let (loc, dir) = &mut self.guard;
|
||||
*self
|
||||
.cells
|
||||
.get_mut(loc.0)
|
||||
.and_then(|r| r.get_mut(loc.1))
|
||||
.unwrap() = Cell::Visited;
|
||||
let nloc = dir.next(*loc);
|
||||
if let Some(next_cell) = self
|
||||
.cells
|
||||
.get_mut(nloc.0)
|
||||
.and_then(|row| row.get_mut(nloc.1))
|
||||
{
|
||||
match next_cell {
|
||||
Cell::Obstacle => {
|
||||
*dir = dir.rot();
|
||||
Some(*loc)
|
||||
}
|
||||
Cell::Empty | Cell::Visited => {
|
||||
*next_cell = Cell::Guard(*dir);
|
||||
*loc = nloc;
|
||||
Some(nloc)
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn run(&mut self) -> usize {
|
||||
let mut locs = HashSet::new();
|
||||
locs.insert(self.guard.0);
|
||||
while let Some(loc) = self.step() {
|
||||
locs.insert(loc);
|
||||
}
|
||||
locs.len()
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_cell(input: &mut &str) -> PResult<Cell> {
|
||||
alt((parse_guard, parse_floor)).parse_next(input)
|
||||
}
|
||||
|
||||
fn parse_guard(input: &mut &str) -> PResult<Cell> {
|
||||
let g = alt(('^', '>', 'v', '<')).parse_next(input)?;
|
||||
use Cell::Guard;
|
||||
use Dir::*;
|
||||
match g {
|
||||
'^' => Ok(Guard(N)),
|
||||
'>' => Ok(Guard(E)),
|
||||
'v' | 'V' => Ok(Guard(S)),
|
||||
'<' => Ok(Guard(W)),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_floor(input: &mut &str) -> PResult<Cell> {
|
||||
let g = alt(('.', '#')).parse_next(input)?;
|
||||
match g {
|
||||
'.' => Ok(Cell::Empty),
|
||||
'#' => Ok(Cell::Obstacle),
|
||||
'X' => Ok(Cell::Visited),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_line(input: &mut &str) -> PResult<Vec<Cell>> {
|
||||
let mut line = till_line_ending.parse_next(input)?;
|
||||
repeat(1.., parse_cell).parse_next(&mut line)
|
||||
}
|
||||
|
||||
fn parse(input: &str) -> PResult<Board> {
|
||||
let mut gdir = Dir::N;
|
||||
let mut loc = Loc(0, 0);
|
||||
|
||||
let mut input = input;
|
||||
let cells: Vec<Vec<Cell>> = separated(1.., parse_line, newline)
|
||||
.parse_next(&mut input)
|
||||
.unwrap();
|
||||
|
||||
for (row, line) in cells.iter().enumerate() {
|
||||
for (col, cell) in line.iter().enumerate() {
|
||||
if let Cell::Guard(d) = cell {
|
||||
gdir = *d;
|
||||
loc = Loc(row, col);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Board {
|
||||
cells,
|
||||
guard: (loc, gdir),
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
static INPUT: &str = "....#.....
|
||||
.........#
|
||||
..........
|
||||
..#.......
|
||||
.......#..
|
||||
..........
|
||||
.#..^.....
|
||||
........#.
|
||||
#.........
|
||||
......#...";
|
||||
|
||||
#[test]
|
||||
fn p1() {
|
||||
let v = pt1(INPUT);
|
||||
assert_eq!(v, 41)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn p2() {}
|
||||
}
|
Loading…
Reference in a new issue