summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bin/day6.rs139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/bin/day6.rs b/src/bin/day6.rs
new file mode 100644
index 0000000..5de09c1
--- /dev/null
+++ b/src/bin/day6.rs
@@ -0,0 +1,139 @@
+use std::collections::{HashMap, HashSet};
+
+static DAY: u8 = 6;
+
+fn main() {
+ let input = advent::read_lines(DAY);
+ println!("{DAY}a: {}", Map::new(&input).distinct_positions());
+ println!("{DAY}b: {}", 0);
+}
+
+#[derive(Eq, PartialEq, Hash, Clone)]
+struct Position {
+ x: isize,
+ y: isize,
+}
+
+#[derive(Eq, PartialEq)]
+enum Object {
+ Obstruction,
+ Floor,
+ Guard,
+}
+
+enum Direction {
+ Up,
+ Down,
+ Left,
+ Right,
+}
+
+impl Direction {
+ fn turn_right(&self) -> Direction {
+ match *self {
+ Direction::Up => Direction::Right,
+ Direction::Down => Direction::Left,
+ Direction::Left => Direction::Up,
+ Direction::Right => Direction::Down,
+ }
+ }
+}
+
+impl Object {
+ fn new(c: char) -> Object {
+ match c {
+ '#' => Object::Obstruction,
+ '.' => Object::Floor,
+ '^' => Object::Guard,
+ _ => unimplemented!(),
+ }
+ }
+}
+
+struct Guard {
+ pos: Position,
+ direction: Direction,
+}
+
+impl Guard {
+ fn next_pos(&self) -> Position {
+ match self.direction {
+ Direction::Up => Position { x: self.pos.x, y: self.pos.y - 1 },
+ Direction::Down => Position { x: self.pos.x, y: self.pos.y + 1 },
+ Direction::Left => Position { x: self.pos.x - 1, y: self.pos.y },
+ Direction::Right => Position { x: self.pos.x + 1, y: self.pos.y },
+ }
+ }
+}
+
+struct Map {
+ map: HashMap<Position, Object>,
+ guard: Guard,
+ max_dimension: Position,
+}
+
+
+impl Map {
+ fn new(input: &[String]) -> Map {
+ let mut map = HashMap::new();
+ let mut guard = Guard { pos: Position { x: 0, y: 0 }, direction: Direction::Up };
+ for (y, line) in input.iter().enumerate() {
+ for (x, c) in line.chars().enumerate() {
+ let pos = Position { x: x as isize, y: y as isize };
+ let obj = Object::new(c);
+ if obj == Object::Guard {
+ guard.pos = pos.clone();
+ map.insert(pos, Object::Floor);
+ } else {
+ map.insert(pos, Object::new(c));
+ }
+ }
+ }
+
+ Map { map, guard, max_dimension: Position { x: input[0].len() as isize, y: input.len() as isize } }
+ }
+
+ fn distinct_positions(&mut self) -> usize {
+ let mut visited = HashSet::new();
+ loop {
+ let next_pos = self.guard.next_pos();
+ if next_pos.x < 0 || next_pos.x >= self.max_dimension.x || next_pos.y < 0 || next_pos.y >= self.max_dimension.y {
+ break;
+ }
+ match self.map.get(&next_pos).unwrap() {
+ Object::Floor => {
+ self.guard.pos = next_pos.clone();
+ visited.insert(next_pos);
+ },
+ Object::Obstruction => {
+ self.guard.direction = self.guard.direction.turn_right();
+ continue;
+ },
+ _ => unimplemented!(),
+ }
+ }
+ visited.len()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test() {
+ let input = [
+ "....#.....",
+ ".........#",
+ "..........",
+ "..#.......",
+ ".......#..",
+ "..........",
+ ".#..^.....",
+ "........#.",
+ "#.........",
+ "......#...",
+ ].iter().map(|&x| String::from(x)).collect::<Vec<_>>();
+ assert_eq!(Map::new(&input).distinct_positions(), 41);
+ }
+}