summaryrefslogtreecommitdiff
path: root/2023/src/bin/day_10.rs
diff options
context:
space:
mode:
Diffstat (limited to '2023/src/bin/day_10.rs')
-rw-r--r--2023/src/bin/day_10.rs224
1 files changed, 216 insertions, 8 deletions
diff --git a/2023/src/bin/day_10.rs b/2023/src/bin/day_10.rs
index b3a610b..e351c34 100644
--- a/2023/src/bin/day_10.rs
+++ b/2023/src/bin/day_10.rs
@@ -1,19 +1,227 @@
-use nom::IResult;
+use nom::{
+ branch::alt,
+ character::complete::{char as nom_char, line_ending},
+ combinator::{map, value},
+ multi::{many1, separated_list1},
+ IResult,
+};
use std::fs;
fn main() -> Result<(), Box<dyn std::error::Error>> {
- let input = fs::read_to_string("inputs/day_2.txt")?;
- let parsed = Example::parser(&input).unwrap().1;
- dbg!(&parsed);
+ let input = fs::read_to_string("inputs/day_10.txt")?;
+ let parsed = Maze::parser(&input).unwrap().1;
+ dbg!(&parsed.find_furthest_point_in_loop());
Ok(())
}
#[derive(Debug)]
-struct Example;
+struct Maze(Vec<Vec<Pipe>>);
-impl Example {
- fn parser(_input: &str) -> IResult<&str, Self> {
- todo!()
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum Pipe {
+ Start,
+ Nothing,
+ DownLeft,
+ DownRight,
+ DownUp,
+ LeftRight,
+ UpLeft,
+ UpRight,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+enum Direction {
+ Up,
+ Down,
+ Left,
+ Right,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+struct Point {
+ x: usize,
+ y: usize,
+}
+
+impl Maze {
+ fn parser(input: &str) -> IResult<&str, Self> {
+ map(separated_list1(line_ending, many1(Pipe::parser)), Maze)(input)
+ }
+
+ fn find_furthest_point_in_loop(&self) -> usize {
+ self.measure_loop_size() / 2
+ }
+
+ fn measure_loop_size(&self) -> usize {
+ let mut position = self.find_start();
+ let mut facing = if position.y > 0
+ && self
+ .at(position.up())
+ .connections()
+ .contains(&Direction::Down)
+ {
+ position = position.up();
+ Direction::Up
+ } else if position.y < self.0.len() - 1
+ && self
+ .at(position.down())
+ .connections()
+ .contains(&Direction::Up)
+ {
+ position = position.down();
+ Direction::Down
+ } else if position.x > 0
+ && self
+ .at(position.left())
+ .connections()
+ .contains(&Direction::Right)
+ {
+ position = position.left();
+ Direction::Left
+ } else if position.x < self.0[position.y].len() - 1
+ && self
+ .at(position.right())
+ .connections()
+ .contains(&Direction::Left)
+ {
+ position = position.right();
+ Direction::Right
+ } else {
+ panic!()
+ };
+ let mut distance = 1;
+
+ while self.at(position) != Pipe::Start {
+ let current_pipe = self.at(position);
+ facing = current_pipe.exit_facing(facing).unwrap();
+ position = match facing {
+ Direction::Up => position.up(),
+ Direction::Down => position.down(),
+ Direction::Left => position.left(),
+ Direction::Right => position.right(),
+ };
+ distance += 1;
+ }
+
+ distance
+ }
+
+ fn at(&self, p: Point) -> Pipe {
+ self.0[p.y][p.x]
+ }
+
+ fn find_start(&self) -> Point {
+ for (y, row) in self.0.iter().enumerate() {
+ for (x, pipe) in row.iter().enumerate() {
+ if *pipe == Pipe::Start {
+ return Point { x, y };
+ }
+ }
+ }
+ panic!("No Start!");
+ }
+}
+
+impl Pipe {
+ fn parser(input: &str) -> IResult<&str, Self> {
+ use Pipe::*;
+
+ alt((
+ value(Start, nom_char('S')),
+ value(Nothing, nom_char('.')),
+ value(DownLeft, nom_char('7')),
+ value(DownRight, nom_char('F')),
+ value(DownUp, nom_char('|')),
+ value(LeftRight, nom_char('-')),
+ value(UpLeft, nom_char('J')),
+ value(UpRight, nom_char('L')),
+ ))(input)
+ }
+
+ fn connections(&self) -> Vec<Direction> {
+ use Direction::*;
+
+ match self {
+ Pipe::Start => vec![],
+ Pipe::Nothing => vec![],
+ Pipe::DownLeft => vec![Down, Left],
+ Pipe::DownRight => vec![Down, Right],
+ Pipe::DownUp => vec![Down, Up],
+ Pipe::LeftRight => vec![Left, Right],
+ Pipe::UpLeft => vec![Up, Left],
+ Pipe::UpRight => vec![Up, Right],
+ }
+ }
+
+ fn exit_facing(&self, facing: Direction) -> Option<Direction> {
+ use Direction::*;
+
+ match self {
+ Pipe::Start => None,
+ Pipe::Nothing => None,
+ Pipe::DownLeft => match facing {
+ Up => Some(Left),
+ Right => Some(Down),
+ _ => None,
+ },
+ Pipe::DownRight => match facing {
+ Up => Some(Right),
+ Left => Some(Down),
+ _ => None,
+ },
+ Pipe::DownUp => match facing {
+ Up => Some(Up),
+ Down => Some(Down),
+ _ => None,
+ },
+ Pipe::LeftRight => match facing {
+ Left => Some(Left),
+ Right => Some(Right),
+ _ => None,
+ },
+ Pipe::UpLeft => match facing {
+ Down => Some(Left),
+ Right => Some(Up),
+ _ => None,
+ },
+ Pipe::UpRight => match facing {
+ Down => Some(Right),
+ Left => Some(Up),
+ _ => None,
+ },
+ }
+ }
+}
+
+impl Point {
+ fn up(&self) -> Point {
+ Point {
+ x: self.x,
+ y: self.y - 1,
+ }
+ }
+
+ fn down(&self) -> Point {
+ Point {
+ x: self.x,
+ y: self.y + 1,
+ }
+ }
+
+ fn left(&self) -> Point {
+ Point {
+ x: self.x - 1,
+ y: self.y,
+ }
+ }
+
+ fn right(&self) -> Point {
+ Point {
+ x: self.x + 1,
+ y: self.y,
+ }
}
}
+
+// 6756 is too low