summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--2024/06/rust/Cargo.lock7
-rw-r--r--2024/06/rust/Cargo.toml3
-rw-r--r--2024/06/rust/src/main.rs107
-rw-r--r--lib/rust/Cargo.lock7
-rw-r--r--lib/rust/Cargo.toml6
-rw-r--r--lib/rust/src/grid.rs210
-rw-r--r--lib/rust/src/lib.rs1
7 files changed, 75 insertions, 266 deletions
diff --git a/2024/06/rust/Cargo.lock b/2024/06/rust/Cargo.lock
index a049cf0..01e64d2 100644
--- a/2024/06/rust/Cargo.lock
+++ b/2024/06/rust/Cargo.lock
@@ -3,12 +3,5 @@
version = 4
[[package]]
-name = "aoc"
-version = "0.1.0"
-
-[[package]]
name = "aoc_2024-06"
version = "0.1.0"
-dependencies = [
- "aoc",
-]
diff --git a/2024/06/rust/Cargo.toml b/2024/06/rust/Cargo.toml
index f478719..01c1304 100644
--- a/2024/06/rust/Cargo.toml
+++ b/2024/06/rust/Cargo.toml
@@ -2,6 +2,3 @@
name = "aoc_2024-06"
version = "0.1.0"
edition = "2021"
-
-[dependencies]
-aoc = { version = "0.1.0", path = "../../../lib/rust" }
diff --git a/2024/06/rust/src/main.rs b/2024/06/rust/src/main.rs
index 92ac02d..550e99e 100644
--- a/2024/06/rust/src/main.rs
+++ b/2024/06/rust/src/main.rs
@@ -1,43 +1,86 @@
-use std::io;
+use std::{collections::HashMap, io};
-use aoc::grid::{Direction, Grid};
-use std::collections::HashSet;
+enum Cell {
+ Empty,
+ Obstacle,
+}
+
+#[derive(Clone)]
+enum Direction {
+ L = 0b1,
+ R = 0b10,
+ U = 0b100,
+ D = 0b1000,
+}
+
+impl Direction {
+ fn shift(&self, point: (isize, isize)) -> (isize, isize) {
+ let (x, y) = point;
+ match self {
+ Direction::L => (x - 1, y),
+ Direction::R => (x + 1, y),
+ Direction::U => (x, y - 1),
+ Direction::D => (x, y + 1),
+ }
+ }
+
+ fn rotate(&self) -> Self {
+ use Direction::*;
+ match self {
+ L => U,
+ R => D,
+ U => R,
+ D => L,
+ }
+ }
+}
fn main() -> io::Result<()> {
- let grid: Vec<Vec<char>> = io::stdin()
+ let mut map = HashMap::new();
+ let mut pos = None;
+ io::stdin()
.lines()
- .map(|line| line.unwrap().chars().collect())
- .collect();
- let grid = Grid::new(grid);
- let start = grid
+ .flatten()
.enumerate()
- .filter(|(_, c)| **c == '^')
- .next()
- .unwrap()
- .0;
-
- let silver: usize = silver(&grid, start);
- let gold: usize = gold(&grid);
- println!("silver: {silver}");
- println!("gold: {gold}");
+ .flat_map(|(y, line)| {
+ line.chars()
+ .enumerate()
+ .map(|(x, ch)| ([x as isize, y as isize], ch))
+ .collect::<Vec<_>>()
+ })
+ .for_each(|([x, y], ch)| match ch {
+ '.' => {
+ map.insert((x, y), Cell::Empty);
+ }
+ '^' => {
+ map.insert((x, y), Cell::Empty);
+ pos = Some((x, y))
+ }
+ '#' => {
+ map.insert((x, y), Cell::Obstacle);
+ }
+ _ => panic!(),
+ });
- return Ok(());
-}
+ let mut visited = HashMap::new();
+ let mut pos = pos.unwrap();
+ let mut dir = Direction::U;
-fn silver(grid: &Grid<char>, start: (usize, usize)) -> usize {
- let mut pos = start;
- let mut dir = Direction { x: 0, y: -1 };
- let mut seen = HashSet::<(usize, usize)>::new();
loop {
- seen.insert(pos);
- match grid.move_pos(pos, dir, 1).and_then(|p| grid.at(p)) {
- Some(&'#') => dir = dir.cw(),
- Some(_) => pos = grid.move_pos(pos, dir, 1).unwrap(),
- None => break seen.len(),
- }
+ *visited.entry(pos).or_insert(0 as u8) |= dir.clone() as u8;
+
+ let ahead = dir.shift(pos);
+ match map.get(&ahead) {
+ Some(Cell::Empty) => pos = ahead,
+ Some(Cell::Obstacle) => dir = dir.rotate(),
+ None => break,
+ };
}
-}
-fn gold(grid: &Grid<char>) -> usize {
- 0
+ let silver: usize = visited.len();
+ let gold: usize = 0;
+ println!("silver: {silver}");
+ println!("gold: {gold}");
+
+ return Ok(());
}
diff --git a/lib/rust/Cargo.lock b/lib/rust/Cargo.lock
deleted file mode 100644
index eee204e..0000000
--- a/lib/rust/Cargo.lock
+++ /dev/null
@@ -1,7 +0,0 @@
-# This file is automatically @generated by Cargo.
-# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "aoc"
-version = "0.1.0"
diff --git a/lib/rust/Cargo.toml b/lib/rust/Cargo.toml
deleted file mode 100644
index c0838b1..0000000
--- a/lib/rust/Cargo.toml
+++ /dev/null
@@ -1,6 +0,0 @@
-[package]
-name = "aoc"
-version = "0.1.0"
-edition = "2024"
-
-[dependencies]
diff --git a/lib/rust/src/grid.rs b/lib/rust/src/grid.rs
deleted file mode 100644
index 671c7de..0000000
--- a/lib/rust/src/grid.rs
+++ /dev/null
@@ -1,210 +0,0 @@
-#[derive(Debug)]
-pub struct Grid<T> {
- data: Vec<T>,
- width: usize,
- height: usize,
-}
-
-type Point = (usize, usize);
-
-#[derive(PartialEq, Eq, Clone, Hash, Debug, Copy)]
-pub struct Direction {
- pub x: i64,
- pub y: i64,
-}
-
-impl From<(i64, i64)> for Direction {
- fn from((x, y): (i64, i64)) -> Self {
- Direction { x, y }
- }
-}
-
-impl Direction {
- pub fn cw(self) -> Self {
- (-self.y, self.x).into()
- }
- pub fn acw(self) -> Self {
- (self.y, -self.x).into()
- }
-}
-
-pub fn chebyshev_ball(n: i64) -> impl Iterator<Item = Direction> {
- (-n..=n).flat_map(move |x| (-n..=n).map(move |y| Direction { x, y }))
-}
-
-impl<T> Grid<T> {
- pub fn new(grid: Vec<Vec<T>>) -> Grid<T> {
- // unfold grid. assume that width/height are consistent
- Grid {
- height: grid.len(),
- width: grid.first().map_or(0, Vec::len),
- data: grid.into_iter().flatten().collect(),
- }
- }
-
- pub fn at(&self, (x, y): Point) -> Option<&T> {
- if x >= self.width || y >= self.height {
- None
- } else {
- self.data.get(x + y * self.width)
- }
- }
-
- pub fn is_in(&self, p: Point) -> bool {
- self.at(p).is_some()
- }
-
- pub fn points(&self) -> impl Iterator<Item = Point> {
- (0..self.width).flat_map(|x| (0..self.height).map(move |y| (x, y)))
- }
-
- pub fn enumerate(&self) -> impl Iterator<Item = (Point, &T)> {
- self.points().map(|p| (p, self.at(p).unwrap()))
- }
-
- pub fn move_pos(&self, (x, y): Point, d: Direction, n: i64) -> Option<Point> {
- let x = (i64::try_from(x).ok()? + n * d.x).try_into().ok()?;
- let y = (i64::try_from(y).ok()? + n * d.y).try_into().ok()?;
- let p = (x, y);
- if self.is_in(p) {
- Some(p)
- } else {
- None
- }
- }
-
- pub fn ray(&self, p: Point, d: Direction) -> impl Iterator<Item = &T> {
- (0..)
- .map(move |n| self.move_pos(p, d, n))
- .take_while(Option::is_some)
- .flatten()
- .map(|p| self.at(p))
- .flatten()
- }
-}
-
-#[cfg(test)]
-mod tests {
- use std::collections::HashSet;
-
- use super::*;
-
- #[test]
- fn chebyshev_ball_zero() {
- assert_eq!(
- chebyshev_ball(0).collect::<HashSet<_>>(),
- [Direction { x: 0, y: 0 }].iter().cloned().collect()
- )
- }
-
- #[test]
- fn chebyshev_ball_one() {
- assert_eq!(
- chebyshev_ball(1).collect::<HashSet<_>>(),
- [
- Direction { x: -1, y: -1 },
- Direction { x: -1, y: 0 },
- Direction { x: -1, y: 1 },
- Direction { x: 0, y: -1 },
- Direction { x: 0, y: 0 },
- Direction { x: 0, y: 1 },
- Direction { x: 1, y: -1 },
- Direction { x: 1, y: 0 },
- Direction { x: 1, y: 1 }
- ]
- .iter()
- .cloned()
- .collect()
- )
- }
-
- #[test]
- fn chebyshev_ball_two() {
- let points = chebyshev_ball(2).collect::<HashSet<_>>();
- assert_eq!(points.len(), 25);
- let norms = points
- .iter()
- .map(|Direction { x, y }| x.abs().max(y.abs()))
- .collect::<Vec<_>>();
-
- assert_eq!(norms.iter().filter(|&&n| n == 0).count(), 1);
- assert_eq!(norms.iter().filter(|&&n| n == 1).count(), 8);
- assert_eq!(norms.iter().filter(|&&n| n == 2).count(), 16);
- }
-
- #[test]
- fn create_grid() {
- let _grid = Grid::new(vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]]);
- }
-
- #[test]
- fn at_exists() {
- let grid = Grid::new(vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]]);
- assert_eq!(grid.at((1, 0)).unwrap(), &2);
- }
-
- #[test]
- fn at_not_exists() {
- let grid = Grid::new(vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]]);
- assert!(grid.at((17, 10)).is_none());
- }
-
- #[test]
- fn points_empty() {
- let grid = Grid::<u64>::new(vec![vec![]]);
- assert!(grid.points().eq(vec![]))
- }
-
- #[test]
- fn points_equal_size() {
- let grid = Grid::new(vec![vec![1, 2], vec![3, 4]]);
- let points = grid.points().collect::<HashSet<_>>();
- assert_eq!(
- points,
- [(0, 0), (0, 1), (1, 0), (1, 1)].iter().cloned().collect()
- )
- }
-
- #[test]
- fn points_unequal_size() {
- let grid = Grid::new(vec![vec![1, 2], vec![3, 4], vec![5, 6]]);
- let points = grid.points().collect::<HashSet<_>>();
- assert_eq!(
- points,
- [(0, 0), (1, 0), (0, 1), (1, 1), (0, 2), (1, 2)]
- .iter()
- .cloned()
- .collect()
- )
- }
-
- #[test]
- fn ray_empty() {
- let grid = Grid::<u64>::new(vec![vec![]]);
- assert!(grid.ray((1, 1), (1, 2).into()).eq(vec![].iter()))
- }
-
- #[test]
- fn ray_single_element() {
- let grid = Grid::<u64>::new(vec![vec![1]]);
- assert!(grid.ray((0, 0), (1, 2).into()).eq(vec![1].iter()))
- }
-
- #[test]
- fn ray_horizontal() {
- let grid = Grid::new(vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]]);
- assert!(grid.ray((0, 0), (1, 0).into()).eq(vec![1, 2, 3].iter()))
- }
-
- #[test]
- fn ray_vertical() {
- let grid = Grid::new(vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]]);
- assert!(grid.ray((1, 0), (0, 1).into()).eq(vec![2, 5, 8].iter()))
- }
-
- #[test]
- fn ray_diagonal() {
- let grid = Grid::new(vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]]);
- assert!(grid.ray((0, 0), (1, 2).into()).eq(vec![1, 8].iter()))
- }
-}
diff --git a/lib/rust/src/lib.rs b/lib/rust/src/lib.rs
deleted file mode 100644
index f7a1b46..0000000
--- a/lib/rust/src/lib.rs
+++ /dev/null
@@ -1 +0,0 @@
-pub mod grid;