-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday06.rs
123 lines (108 loc) · 3.03 KB
/
day06.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::{Direction, Point};
use std::collections::HashMap;
#[derive(Debug)]
struct Guard {
pos: Point,
dir: Direction,
}
fn find_guard(input: &[Vec<char>]) -> Option<Guard> {
for (y, _) in input.iter().enumerate() {
for (x, item) in input[y].iter().enumerate() {
if let Ok(dir) = Direction::try_from(*item) {
return Some(Guard {
dir,
pos: Point {
x: x as i32,
y: y as i32,
},
});
}
}
}
None
}
fn process_input(input: &str) -> Vec<Vec<char>> {
input
.trim()
.lines()
.map(|line| line.chars().collect())
.collect()
}
pub fn part_one(input: &str) -> i32 {
let grid = process_input(input);
let mut guard = find_guard(&grid).expect("didn't find guard");
let mut visited: HashMap<Point, i32> = HashMap::new();
*visited.entry(guard.pos).or_insert(0) += 1;
while let Some(movement) = guard.pos.attempt_move(guard.dir, &grid) {
guard.pos = movement;
*visited.entry(guard.pos).or_insert(0) += 1;
if let Some(value_in_next_position) = guard.pos.value_in_direction(guard.dir, &grid) {
if value_in_next_position == '#' {
guard.dir = guard.dir.turn('R');
}
}
}
visited.keys().count() as i32
}
fn simulate(guard: &mut Guard, grid: &[Vec<char>]) -> bool {
let mut visited = HashMap::new();
let mut steps = 0;
visited.insert((guard.pos, guard.dir), steps);
while let Some(movement) = guard.pos.attempt_move(guard.dir, grid) {
steps += 1;
guard.pos = movement;
if visited.contains_key(&(guard.pos, guard.dir)) {
return true;
}
visited.insert((guard.pos, guard.dir), steps);
if let Some(value_in_next_position) = guard.pos.value_in_direction(guard.dir, grid) {
if value_in_next_position == '#' || value_in_next_position == 'O' {
guard.dir = guard.dir.turn('R');
}
}
}
false
}
pub fn part_two(input: &str) -> i32 {
let grid = process_input(input);
let mut count = 0;
for (y, row) in grid.iter().enumerate() {
for (x, &item) in row.iter().enumerate() {
if item == '.' {
let mut new_grid = grid.clone();
new_grid[y][x] = 'O';
if let Some(mut guard) = find_guard(&new_grid) {
if simulate(&mut guard, &new_grid) {
count += 1;
}
}
}
}
}
count
}
#[cfg(test)]
mod tests {
use super::*;
const INPUT: &str = "
....#.....
.........#
..........
..#.......
.......#..
..........
.#..^.....
........#.
#.........
......#...";
#[test]
fn test_part_one() {
let result = part_one(INPUT);
assert_eq!(result, 41);
}
#[test]
fn test_part_two() {
let result = part_two(INPUT);
assert_eq!(result, 6);
}
}