summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2022-12-25 00:43:42 -0500
committerJesse Luehrs <doy@tozt.net>2022-12-25 00:43:42 -0500
commit18202694cfc4c715de7dab36639373f9deb1abe3 (patch)
tree37e873cb1448df5e623bfdbdd4ce633421f96e7d /src
parent67515a357519a3c2fac699ba2e8c56e671b651c5 (diff)
downloadadvent-of-code-18202694cfc4c715de7dab36639373f9deb1abe3.tar.gz
advent-of-code-18202694cfc4c715de7dab36639373f9deb1abe3.zip
day 22 part 1
Diffstat (limited to 'src')
-rw-r--r--src/bin/2022/day22.rs181
-rw-r--r--src/bin/2022/main.rs18
-rw-r--r--src/grid.rs112
-rw-r--r--src/parse.rs2
4 files changed, 265 insertions, 48 deletions
diff --git a/src/bin/2022/day22.rs b/src/bin/2022/day22.rs
new file mode 100644
index 0000000..81bf264
--- /dev/null
+++ b/src/bin/2022/day22.rs
@@ -0,0 +1,181 @@
+#![allow(dead_code)]
+#![allow(unused_variables)]
+
+use advent_of_code::prelude::*;
+
+#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug, Default)]
+enum Tile {
+ Open,
+ Wall,
+ #[default]
+ Noop,
+}
+
+#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
+enum Step {
+ Forward(usize),
+ Left,
+ Right,
+}
+
+#[derive(Clone, Copy, Eq, PartialEq, Hash, Debug)]
+enum Direction {
+ Right,
+ Down,
+ Left,
+ Up,
+}
+
+impl std::convert::From<Direction> for usize {
+ fn from(direction: Direction) -> Self {
+ match direction {
+ Direction::Right => 0,
+ Direction::Down => 1,
+ Direction::Left => 2,
+ Direction::Up => 3,
+ }
+ }
+}
+
+impl Direction {
+ fn left(&self) -> Self {
+ match self {
+ Direction::Right => Direction::Up,
+ Direction::Down => Direction::Right,
+ Direction::Left => Direction::Down,
+ Direction::Up => Direction::Left,
+ }
+ }
+
+ fn right(&self) -> Self {
+ match self {
+ Direction::Right => Direction::Down,
+ Direction::Down => Direction::Left,
+ Direction::Left => Direction::Up,
+ Direction::Up => Direction::Right,
+ }
+ }
+}
+
+#[derive(Debug)]
+pub struct Map {
+ grid: Grid<Tile>,
+ path: Vec<Step>,
+}
+
+impl Map {
+ fn step(&self, pos: (Row, Col), facing: Direction) -> (Row, Col) {
+ let (row_diff, col_diff, sub) = match facing {
+ Direction::Right => (0, 1, false),
+ Direction::Down => (1, 0, false),
+ Direction::Left => (0, 1, true),
+ Direction::Up => (1, 0, true),
+ };
+ let rows = self.grid.rows().0;
+ let cols = self.grid.cols().0;
+ let mut new_pos = pos;
+ new_pos = (
+ if sub {
+ rows + new_pos.0 - row_diff
+ } else {
+ rows + new_pos.0 + row_diff
+ } % rows,
+ if sub {
+ cols + new_pos.1 - col_diff
+ } else {
+ cols + new_pos.1 + col_diff
+ } % cols,
+ );
+ while matches!(self.grid[new_pos.0][new_pos.1], Tile::Noop) {
+ new_pos = (
+ if sub {
+ rows + new_pos.0 - row_diff
+ } else {
+ rows + new_pos.0 + row_diff
+ } % rows,
+ if sub {
+ cols + new_pos.1 - col_diff
+ } else {
+ cols + new_pos.1 + col_diff
+ } % cols,
+ );
+ }
+ if matches!(self.grid[new_pos.0][new_pos.1], Tile::Wall) {
+ pos
+ } else {
+ new_pos
+ }
+ }
+}
+
+pub fn parse(fh: File) -> Result<Map> {
+ let mut lines = parse::raw_lines(fh);
+ let grid = parse::grid(parse::chunk(&mut lines), |c, _, _| match c {
+ b' ' => Tile::Noop,
+ b'.' => Tile::Open,
+ b'#' => Tile::Wall,
+ _ => panic!("invalid map tile {}", c),
+ });
+
+ let path_str = lines.next().unwrap();
+ let mut path_str = &path_str[..];
+ let mut path = vec![];
+ while let Some(first) = path_str.chars().next() {
+ match first {
+ 'R' => {
+ path.push(Step::Right);
+ path_str = &path_str[1..];
+ }
+ 'L' => {
+ path.push(Step::Left);
+ path_str = &path_str[1..];
+ }
+ '0'..='9' => {
+ let prefix_len = path_str
+ .chars()
+ .take_while(|c| ('0'..='9').contains(c))
+ .count();
+ path.push(Step::Forward(
+ path_str[0..prefix_len].parse().unwrap(),
+ ));
+ path_str = &path_str[prefix_len..];
+ }
+ _ => panic!("invalid path char {}", first),
+ }
+ }
+
+ Ok(Map { grid, path })
+}
+
+pub fn part1(map: Map) -> Result<usize> {
+ let mut pos = (Row(0), Col(0));
+ let mut facing = Direction::Right;
+ for step in &map.path {
+ match step {
+ Step::Left => facing = facing.left(),
+ Step::Right => facing = facing.right(),
+ Step::Forward(n) => {
+ for _ in 0..*n {
+ pos = map.step(pos, facing);
+ }
+ }
+ }
+ }
+ Ok((pos.0 .0 + 1) * 1000 + (pos.1 .0 + 1) * 4 + usize::from(facing))
+}
+
+pub fn part2(map: Map) -> Result<usize> {
+ todo!()
+}
+
+#[test]
+fn test() {
+ assert_eq!(
+ part1(parse(parse::data(2022, 22).unwrap()).unwrap()).unwrap(),
+ 95358
+ );
+ // assert_eq!(
+ // part2(parse(parse::data(2022, 22).unwrap()).unwrap()).unwrap(),
+ // 0
+ // );
+}
diff --git a/src/bin/2022/main.rs b/src/bin/2022/main.rs
index 46cc3bb..efc7b22 100644
--- a/src/bin/2022/main.rs
+++ b/src/bin/2022/main.rs
@@ -14,14 +14,6 @@ use advent_of_code::prelude::*;
mod day1;
mod day10;
mod day11;
-mod day2;
-mod day3;
-mod day4;
-mod day5;
-mod day6;
-mod day7;
-mod day8;
-mod day9;
mod day12;
mod day13;
mod day14;
@@ -30,11 +22,20 @@ mod day16;
mod day17;
mod day18;
mod day19;
+mod day2;
mod day20;
mod day21;
+mod day22;
mod day23;
mod day24;
mod day25;
+mod day3;
+mod day4;
+mod day5;
+mod day6;
+mod day7;
+mod day8;
+mod day9;
// NEXT MOD
#[paw::main]
@@ -62,6 +63,7 @@ fn main(opt: Opt) -> Result<()> {
19 => advent_of_code::day!(2022, opt.day, opt.puzzle, day19),
20 => advent_of_code::day!(2022, opt.day, opt.puzzle, day20),
21 => advent_of_code::day!(2022, opt.day, opt.puzzle, day21),
+ 22 => advent_of_code::day!(2022, opt.day, opt.puzzle, day22),
23 => advent_of_code::day!(2022, opt.day, opt.puzzle, day23),
24 => advent_of_code::day!(2022, opt.day, opt.puzzle, day24),
25 => advent_of_code::day!(2022, opt.day, opt.puzzle, day25),
diff --git a/src/grid.rs b/src/grid.rs
index d988ec6..040b92b 100644
--- a/src/grid.rs
+++ b/src/grid.rs
@@ -76,6 +76,34 @@ impl std::ops::Sub<Col> for usize {
}
}
+impl std::ops::Mul<usize> for Row {
+ type Output = Self;
+ fn mul(self, other: usize) -> Self::Output {
+ Self(self.0 * other)
+ }
+}
+
+impl std::ops::Mul<Row> for usize {
+ type Output = Row;
+ fn mul(self, other: Row) -> Self::Output {
+ Row(self * other.0)
+ }
+}
+
+impl std::ops::Mul<usize> for Col {
+ type Output = Self;
+ fn mul(self, other: usize) -> Self::Output {
+ Self(self.0 * other)
+ }
+}
+
+impl std::ops::Mul<Col> for usize {
+ type Output = Col;
+ fn mul(self, other: Col) -> Self::Output {
+ Col(self * other.0)
+ }
+}
+
impl std::ops::Rem<usize> for Row {
type Output = Self;
fn rem(self, other: usize) -> Self::Output {
@@ -183,11 +211,11 @@ impl std::ops::Sub<ICol> for isize {
}
#[derive(Default, Clone, Debug, Eq, PartialEq, Hash)]
-pub struct GridRow<T: Default + Clone + Eq + PartialEq + std::hash::Hash> {
+pub struct GridRow<T: Clone + Eq + PartialEq + std::hash::Hash> {
cells: Vec<T>,
}
-impl<T: Default + Clone + Eq + PartialEq + std::hash::Hash> GridRow<T> {
+impl<T: Clone + Eq + PartialEq + std::hash::Hash> GridRow<T> {
pub fn iter(&self) -> impl Iterator<Item = &T> + Clone {
self.cells.iter()
}
@@ -197,8 +225,8 @@ impl<T: Default + Clone + Eq + PartialEq + std::hash::Hash> GridRow<T> {
}
}
-impl<T: Default + Clone + Eq + PartialEq + std::hash::Hash>
- std::ops::Index<Col> for GridRow<T>
+impl<T: Clone + Eq + PartialEq + std::hash::Hash> std::ops::Index<Col>
+ for GridRow<T>
{
type Output = T;
fn index(&self, col: Col) -> &Self::Output {
@@ -206,29 +234,26 @@ impl<T: Default + Clone + Eq + PartialEq + std::hash::Hash>
}
}
-impl<T: Default + Clone + Eq + PartialEq + std::hash::Hash>
- std::ops::IndexMut<Col> for GridRow<T>
+impl<T: Clone + Eq + PartialEq + std::hash::Hash> std::ops::IndexMut<Col>
+ for GridRow<T>
{
fn index_mut(&mut self, col: Col) -> &mut Self::Output {
&mut self.cells[col.0]
}
}
-#[derive(Default, Clone, Debug, Eq, PartialEq, Hash)]
-pub struct Grid<T: Default + Clone + Eq + PartialEq + std::hash::Hash> {
+#[derive(Clone, Debug, Eq, PartialEq, Hash)]
+pub struct Grid<T: Clone + Eq + PartialEq + std::hash::Hash> {
rows: Vec<GridRow<T>>,
}
-impl<T: Default + Clone + Eq + PartialEq + std::hash::Hash> Grid<T> {
- pub fn grow(&mut self, rows: Row, cols: Col) {
- self.rows
- .resize_with(rows.0.max(self.rows.len()), GridRow::default);
- for row in &mut self.rows {
- row.cells
- .resize_with(cols.0.max(row.cells.len()), T::default);
- }
+impl<T: Clone + Eq + PartialEq + std::hash::Hash> Default for Grid<T> {
+ fn default() -> Self {
+ Self { rows: vec![] }
}
+}
+impl<T: Clone + Eq + PartialEq + std::hash::Hash> Grid<T> {
pub fn unshift_rows(&mut self, count: usize) {
self.rows = self.rows.split_off(count);
}
@@ -299,14 +324,19 @@ impl<T: Default + Clone + Eq + PartialEq + std::hash::Hash> Grid<T> {
}
}
-impl<
- T: Default
- + Clone
- + Eq
- + PartialEq
- + std::hash::Hash
- + std::fmt::Display,
- > Grid<T>
+impl<T: Default + Clone + Eq + PartialEq + std::hash::Hash> Grid<T> {
+ pub fn grow(&mut self, rows: Row, cols: Col) {
+ self.rows
+ .resize_with(rows.0.max(self.rows.len()), GridRow::default);
+ for row in &mut self.rows {
+ row.cells
+ .resize_with(cols.0.max(row.cells.len()), T::default);
+ }
+ }
+}
+
+impl<T: Clone + Eq + PartialEq + std::hash::Hash + std::fmt::Display>
+ Grid<T>
{
pub fn display_packed<F: Fn(&T) -> char>(
&self,
@@ -316,14 +346,8 @@ impl<
}
}
-impl<
- T: Default
- + Clone
- + Eq
- + PartialEq
- + std::hash::Hash
- + std::fmt::Display,
- > std::fmt::Display for Grid<T>
+impl<T: Clone + Eq + PartialEq + std::hash::Hash + std::fmt::Display>
+ std::fmt::Display for Grid<T>
{
fn fmt(
&self,
@@ -339,8 +363,8 @@ impl<
}
}
-impl<T: Default + Clone + Eq + PartialEq + std::hash::Hash>
- std::ops::Index<Row> for Grid<T>
+impl<T: Clone + Eq + PartialEq + std::hash::Hash> std::ops::Index<Row>
+ for Grid<T>
{
type Output = GridRow<T>;
fn index(&self, row: Row) -> &Self::Output {
@@ -348,8 +372,8 @@ impl<T: Default + Clone + Eq + PartialEq + std::hash::Hash>
}
}
-impl<T: Default + Clone + Eq + PartialEq + std::hash::Hash>
- std::ops::IndexMut<Row> for Grid<T>
+impl<T: Clone + Eq + PartialEq + std::hash::Hash> std::ops::IndexMut<Row>
+ for Grid<T>
{
fn index_mut(&mut self, row: Row) -> &mut Self::Output {
&mut self.rows[row.0]
@@ -363,9 +387,19 @@ impl<T: Default + Clone + Eq + PartialEq + std::hash::Hash>
where
I: IntoIterator<Item = Vec<T>>,
{
- Self {
+ let mut self_ = Self {
rows: iter.into_iter().map(|v| GridRow { cells: v }).collect(),
- }
+ };
+ let nrows = self_.rows.len();
+ let ncols = self_
+ .rows
+ .iter()
+ .map(|row| row.cells.len())
+ .max()
+ .unwrap_or(0);
+ self_.grow(Row(nrows), Col(ncols));
+
+ self_
}
}
@@ -387,7 +421,7 @@ impl<T: Default + Clone + Eq + PartialEq + std::hash::Hash>
pub struct DisplayPacked<
'a,
- T: Default + Clone + Eq + PartialEq + std::hash::Hash + std::fmt::Display,
+ T: Clone + Eq + PartialEq + std::hash::Hash + std::fmt::Display,
F: Fn(&'a T) -> char,
>(&'a Grid<T>, F);
diff --git a/src/parse.rs b/src/parse.rs
index 6969e84..0434ec0 100644
--- a/src/parse.rs
+++ b/src/parse.rs
@@ -109,7 +109,7 @@ pub fn digit_grid(lines: impl Iterator<Item = String>) -> Grid<u8> {
pub fn grid<F, T>(lines: impl Iterator<Item = String>, mut f: F) -> Grid<T>
where
F: FnMut(u8, Row, Col) -> T,
- T: Clone + Default + Eq + PartialEq + std::hash::Hash,
+ T: Default + Clone + Eq + PartialEq + std::hash::Hash,
{
lines
.enumerate()