1
1
advent_of_code:: solution!( 6 ) ;
2
2
3
- use advent_of_code:: maneatingape:: hash :: * ;
3
+ use advent_of_code:: maneatingape:: grid :: * ;
4
4
use advent_of_code:: maneatingape:: point:: * ;
5
5
6
- type Direction = Point ;
6
+ struct Block { }
7
7
8
- struct MapSize {
9
- min_x : i32 ,
10
- max_x : i32 ,
11
- min_y : i32 ,
12
- max_y : i32 ,
8
+ impl Block {
9
+ const WALL : u8 = b'#' ;
10
+ const GUARD : u8 = b'^' ;
13
11
}
14
12
15
- struct DataType {
16
- position : Point ,
17
- direction : Direction ,
18
- obstructions : FastSet < Point > ,
19
- map_size : MapSize ,
20
- }
13
+ fn parse_data ( input : & str ) -> ( Grid < u8 > , Point ) {
14
+ let grid = Grid :: parse ( input) ;
15
+ let start_position = grid. find ( Block :: GUARD ) . unwrap ( ) ;
21
16
22
- impl MapSize {
23
- fn contains ( & self , point : & Point ) -> bool {
24
- point. x >= self . min_x
25
- && point. x <= self . max_x
26
- && point. y >= self . min_y
27
- && point. y <= self . max_y
28
- }
17
+ ( grid, start_position)
29
18
}
30
19
31
- fn parse_data ( input : & str ) -> DataType {
32
- let my_direction = UP ;
33
- let mut my_position = Point :: new ( 0 , 0 ) ;
34
- let mut obstructions = FastSet :: new ( ) ;
35
-
36
- let height = input. lines ( ) . count ( ) ;
37
- let width = input. lines ( ) . next ( ) . unwrap ( ) . len ( ) ;
38
-
39
- for ( y, line) in input. lines ( ) . enumerate ( ) {
40
- for ( x, v) in line. bytes ( ) . enumerate ( ) {
41
- match v {
42
- b'#' => {
43
- obstructions. insert ( Point :: new ( x as i32 , y as i32 ) ) ;
44
- }
45
- b'^' => {
46
- my_position = Point :: new ( x as i32 , y as i32 ) ;
47
- }
48
- _ => { }
49
- }
50
- }
51
- }
52
-
53
- DataType {
54
- position : my_position,
55
- direction : my_direction,
56
- obstructions,
57
- map_size : MapSize {
58
- min_x : 0 ,
59
- max_x : width as i32 - 1 ,
60
- min_y : 0 ,
61
- max_y : height as i32 - 1 ,
62
- } ,
63
- }
64
- }
20
+ fn visited_positions ( grid : & Grid < u8 > , start_position : Point ) -> Vec < Point > {
21
+ let mut result = vec ! [ ] ;
65
22
66
- fn visited_positions ( data : & DataType ) -> FastSet < Point > {
67
- let mut my_position = data. position ;
68
- let mut my_direction = data. direction ;
23
+ let mut my_position = start_position;
24
+ let mut my_direction = UP ;
69
25
70
- let mut visit = FastSet :: new ( ) ;
26
+ let mut visit = grid . same_size_with ( false ) ;
71
27
72
28
loop {
73
- visit. insert ( my_position) ;
29
+ if !visit[ my_position] {
30
+ result. push ( my_position) ;
31
+ } ;
32
+
33
+ visit[ my_position] = true ;
74
34
75
35
let next_position = my_position + my_direction;
76
- if !data . map_size . contains ( & next_position) {
77
- return visit ;
36
+ if !grid . contains ( next_position) {
37
+ return result ;
78
38
}
79
39
80
- if data . obstructions . contains ( & next_position) {
40
+ if grid [ next_position] == Block :: WALL {
81
41
my_direction = my_direction. clockwise ( ) ;
82
42
} else {
83
43
my_position = next_position;
@@ -86,37 +46,45 @@ fn visited_positions(data: &DataType) -> FastSet<Point> {
86
46
}
87
47
88
48
pub fn part_one ( input : & str ) -> Option < u32 > {
89
- let data : DataType = parse_data ( input) ;
49
+ let ( grid , start_position ) = parse_data ( input) ;
90
50
91
- let result = visited_positions ( & data ) . len ( ) as u32 ;
51
+ let result = visited_positions ( & grid , start_position ) . len ( ) as u32 ;
92
52
93
53
Some ( result)
94
54
}
95
55
96
56
pub fn part_two ( input : & str ) -> Option < u32 > {
97
- let data : DataType = parse_data ( input) ;
57
+ let ( grid , start_position ) = parse_data ( input) ;
98
58
99
- let result = visited_positions ( & data )
59
+ let result = visited_positions ( & grid , start_position )
100
60
. into_iter ( )
101
- . filter ( |new_obstruction| new_obstruction != & data. position )
102
- . filter ( |new_obstruction| !data. obstructions . contains ( new_obstruction) )
103
- . filter ( |& new_obstruction| {
104
- let mut visit = FastSet :: new ( ) ;
61
+ . filter_map ( |new_obstruction| {
62
+ let mut visit = grid. same_size_with ( [ false , false , false , false ] ) ;
105
63
106
- let mut my_position = data . position ;
107
- let mut my_direction = data . direction ;
64
+ let mut my_position = start_position ;
65
+ let mut my_direction = UP ;
108
66
109
67
loop {
110
- if !visit. insert ( ( my_position, my_direction) ) {
111
- break true ;
68
+ let visit_index = match my_direction {
69
+ UP => 0 ,
70
+ RIGHT => 1 ,
71
+ DOWN => 2 ,
72
+ LEFT => 3 ,
73
+ _ => unreachable ! ( ) ,
74
+ } ;
75
+
76
+ if visit[ my_position] [ visit_index] {
77
+ break Some ( true ) ;
112
78
}
113
79
80
+ visit[ my_position] [ visit_index] = true ;
81
+
114
82
let next_position = my_position + my_direction;
115
- if !data . map_size . contains ( & next_position) {
116
- break false ;
83
+ if !grid . contains ( next_position) {
84
+ break None ;
117
85
}
118
86
119
- if new_obstruction == next_position || data . obstructions . contains ( & next_position) {
87
+ if new_obstruction == next_position || grid [ next_position] == Block :: WALL {
120
88
my_direction = my_direction. clockwise ( ) ;
121
89
} else {
122
90
my_position = next_position;
@@ -134,13 +102,15 @@ mod tests {
134
102
135
103
#[ test]
136
104
fn test_part_one ( ) {
137
- let result = part_one ( & advent_of_code:: template:: read_file ( "examples" , DAY ) ) ;
105
+ let input = advent_of_code:: template:: read_file ( "examples" , DAY ) ;
106
+ let result = part_one ( & input) ;
138
107
assert_eq ! ( result, Some ( 41 ) ) ;
139
108
}
140
109
141
110
#[ test]
142
111
fn test_part_two ( ) {
143
- let result = part_two ( & advent_of_code:: template:: read_file ( "examples" , DAY ) ) ;
112
+ let input = advent_of_code:: template:: read_file ( "examples" , DAY ) ;
113
+ let result = part_two ( & input) ;
144
114
assert_eq ! ( result, Some ( 6 ) ) ;
145
115
}
146
116
}
0 commit comments