11advent_of_code:: solution!( 6 ) ;
22
3- use advent_of_code:: maneatingape:: hash :: * ;
3+ use advent_of_code:: maneatingape:: grid :: * ;
44use advent_of_code:: maneatingape:: point:: * ;
55
6- type Direction = Point ;
6+ struct Block { }
77
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'^' ;
1311}
1412
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 ( ) ;
2116
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)
2918}
3019
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 ! [ ] ;
6522
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 ;
6925
70- let mut visit = FastSet :: new ( ) ;
26+ let mut visit = grid . same_size_with ( false ) ;
7127
7228 loop {
73- visit. insert ( my_position) ;
29+ if !visit[ my_position] {
30+ result. push ( my_position) ;
31+ } ;
32+
33+ visit[ my_position] = true ;
7434
7535 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 ;
7838 }
7939
80- if data . obstructions . contains ( & next_position) {
40+ if grid [ next_position] == Block :: WALL {
8141 my_direction = my_direction. clockwise ( ) ;
8242 } else {
8343 my_position = next_position;
@@ -86,37 +46,45 @@ fn visited_positions(data: &DataType) -> FastSet<Point> {
8646}
8747
8848pub fn part_one ( input : & str ) -> Option < u32 > {
89- let data : DataType = parse_data ( input) ;
49+ let ( grid , start_position ) = parse_data ( input) ;
9050
91- let result = visited_positions ( & data ) . len ( ) as u32 ;
51+ let result = visited_positions ( & grid , start_position ) . len ( ) as u32 ;
9252
9353 Some ( result)
9454}
9555
9656pub fn part_two ( input : & str ) -> Option < u32 > {
97- let data : DataType = parse_data ( input) ;
57+ let ( grid , start_position ) = parse_data ( input) ;
9858
99- let result = visited_positions ( & data )
59+ let result = visited_positions ( & grid , start_position )
10060 . 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 ] ) ;
10563
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 ;
10866
10967 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 ) ;
11278 }
11379
80+ visit[ my_position] [ visit_index] = true ;
81+
11482 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 ;
11785 }
11886
119- if new_obstruction == next_position || data . obstructions . contains ( & next_position) {
87+ if new_obstruction == next_position || grid [ next_position] == Block :: WALL {
12088 my_direction = my_direction. clockwise ( ) ;
12189 } else {
12290 my_position = next_position;
@@ -134,13 +102,15 @@ mod tests {
134102
135103 #[ test]
136104 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) ;
138107 assert_eq ! ( result, Some ( 41 ) ) ;
139108 }
140109
141110 #[ test]
142111 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) ;
144114 assert_eq ! ( result, Some ( 6 ) ) ;
145115 }
146116}
0 commit comments