diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/bin/day6.rs | 139 |
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); + } +} |
