@@ -5,15 +5,19 @@ use std::{
5
5
6
6
use helpers:: floored_division;
7
7
8
+ struct Grid {
9
+ grid : Vec < Vec < char > > ,
10
+ }
11
+
8
12
fn main ( ) {
9
13
let message = read_file ( "crates/day04/input.txt" ) . unwrap ( ) ;
10
14
// --- Part One ---
11
- let mut count = count_word ( & message, "XMAS" ) ;
15
+ let grid = Grid :: new ( message) ;
16
+ let mut count = grid. count_word ( "XMAS" ) ;
12
17
println ! ( "Part One solution: {count}" ) ;
13
18
14
- // --- Part Two ---
15
- count = count_x_pattern ( & message, "MAS" ) . unwrap ( ) ;
16
- println ! ( "Part Two solution: {count}" ) ;
19
+ count = grid. count_x_pattern ( "XMAS" ) . unwrap ( ) ;
20
+ println ! ( "Part One solution: {count}" ) ;
17
21
}
18
22
19
23
fn read_file ( input : & str ) -> Result < Vec < Vec < char > > , Box < dyn std:: error:: Error > > {
@@ -28,118 +32,127 @@ fn read_file(input: &str) -> Result<Vec<Vec<char>>, Box<dyn std::error::Error>>
28
32
Ok ( vec_of_vecs)
29
33
}
30
34
31
- fn count_x_pattern ( grid : & [ Vec < char > ] , word : & str ) -> Result < usize , String > {
32
- let rows = grid. len ( ) ;
33
- let cols = if rows > 0 {
34
- grid[ 0 ] . len ( )
35
- } else {
36
- return Err ( "Grid must be a valid grid" . to_string ( ) ) ;
37
- } ;
38
- let word_len = word. len ( ) ;
39
- let mut count = 0 ;
40
-
41
- let bounded: usize = floored_division ( word_len. try_into ( ) . unwrap ( ) , 2 )
42
- . try_into ( )
43
- . unwrap ( ) ;
44
- let middle_char = word. chars ( ) . nth ( bounded) . unwrap ( ) ;
45
-
46
- let reverse = word. chars ( ) . rev ( ) . collect :: < String > ( ) ;
47
-
48
- for r in bounded..( rows - bounded) {
49
- for c in bounded..( cols - bounded) {
50
- if grid[ r] [ c] == middle_char {
51
- let mut first_diagonal = false ;
52
- let mut second_diagonal = false ;
53
-
54
- // Check forward diagonal \
55
- if ( 0 ..word_len)
56
- . all ( |i| grid[ r - bounded + i] [ c - bounded + i] == word. chars ( ) . nth ( i) . unwrap ( ) )
57
- {
58
- first_diagonal = true ;
59
- }
60
- // Check backward diagonal \
61
- if ( 0 ..word_len) . all ( |i| {
62
- grid[ r - bounded + i] [ c - bounded + i] == reverse. chars ( ) . nth ( i) . unwrap ( )
63
- } ) {
64
- first_diagonal = true ;
65
- }
35
+ impl Grid {
36
+ const fn new ( new_grid : Vec < Vec < char > > ) -> Self {
37
+ Self { grid : new_grid }
38
+ }
66
39
67
- if first_diagonal {
68
- // Check forward diagonal /
40
+ fn count_x_pattern ( & self , word : & str ) -> Result < usize , String > {
41
+ let rows = self . grid . len ( ) ;
42
+ let cols = if rows > 0 {
43
+ self . grid [ 0 ] . len ( )
44
+ } else {
45
+ return Err ( "Grid must be a valid grid" . to_string ( ) ) ;
46
+ } ;
47
+ let word_len = word. len ( ) ;
48
+ let mut count = 0 ;
49
+
50
+ let bounded: usize = floored_division ( word_len. try_into ( ) . unwrap ( ) , 2 )
51
+ . try_into ( )
52
+ . unwrap ( ) ;
53
+ let middle_char = word. chars ( ) . nth ( bounded) . unwrap ( ) ;
54
+
55
+ let reverse = word. chars ( ) . rev ( ) . collect :: < String > ( ) ;
56
+
57
+ for r in bounded..( rows - bounded) {
58
+ for c in bounded..( cols - bounded) {
59
+ if self . grid [ r] [ c] == middle_char {
60
+ let mut first_diagonal = false ;
61
+ let mut second_diagonal = false ;
62
+
63
+ // Check forward diagonal \
69
64
if ( 0 ..word_len) . all ( |i| {
70
- grid[ r + bounded - i] [ c - bounded + i] == word. chars ( ) . nth ( i) . unwrap ( )
65
+ self . grid [ r - bounded + i] [ c - bounded + i] == word. chars ( ) . nth ( i) . unwrap ( )
71
66
} ) {
72
- second_diagonal = true ;
67
+ first_diagonal = true ;
73
68
}
74
- // Check backward diagonal /
69
+ // Check backward diagonal \
75
70
if ( 0 ..word_len) . all ( |i| {
76
- grid[ r + bounded - i] [ c - bounded + i] == reverse. chars ( ) . nth ( i) . unwrap ( )
71
+ self . grid [ r - bounded + i] [ c - bounded + i]
72
+ == reverse. chars ( ) . nth ( i) . unwrap ( )
77
73
} ) {
78
- second_diagonal = true ;
74
+ first_diagonal = true ;
79
75
}
80
76
81
- if second_diagonal {
82
- count += 1 ;
77
+ if first_diagonal {
78
+ // Check forward diagonal /
79
+ if ( 0 ..word_len) . all ( |i| {
80
+ self . grid [ r + bounded - i] [ c - bounded + i]
81
+ == word. chars ( ) . nth ( i) . unwrap ( )
82
+ } ) {
83
+ second_diagonal = true ;
84
+ }
85
+ // Check backward diagonal /
86
+ if ( 0 ..word_len) . all ( |i| {
87
+ self . grid [ r + bounded - i] [ c - bounded + i]
88
+ == reverse. chars ( ) . nth ( i) . unwrap ( )
89
+ } ) {
90
+ second_diagonal = true ;
91
+ }
92
+
93
+ if second_diagonal {
94
+ count += 1 ;
95
+ }
83
96
}
84
97
}
85
98
}
86
99
}
87
- }
88
100
89
- Ok ( count)
90
- }
101
+ Ok ( count)
102
+ }
91
103
92
- fn count_word ( grid : & [ Vec < char > ] , word : & str ) -> usize {
93
- let word_chars: Vec < char > = word. chars ( ) . collect ( ) ;
94
- let word_len = word_chars. len ( ) ;
95
- let rows = grid. len ( ) ;
96
- let cols = grid[ 0 ] . len ( ) ;
97
- let mut count = 0 ;
98
-
99
- let directions = vec ! [
100
- ( 0 , 1 ) , // Horizontal right
101
- ( 0 , -1 ) , // Horizontal left
102
- ( 1 , 0 ) , // Vertical down
103
- ( -1 , 0 ) , // Vertical up
104
- ( 1 , 1 ) , // Diagonal down-right
105
- ( 1 , -1 ) , // Diagonal down-left
106
- ( -1 , 1 ) , // Diagonal up-right
107
- ( -1 , -1 ) , // Diagonal up-left
108
- ] ;
109
-
110
- for row in 0 ..rows {
111
- for col in 0 ..cols {
112
- for ( dx, dy) in & directions {
113
- let mut found = true ;
114
-
115
- for ( i, _) in word_chars. iter ( ) . enumerate ( ) . take ( word_len) {
116
- let x = isize:: try_from ( row) . unwrap ( ) + isize:: try_from ( i) . unwrap ( ) * dx;
117
- let y = isize:: try_from ( col) . unwrap ( ) + isize:: try_from ( i) . unwrap ( ) * dy;
118
-
119
- if x < 0
120
- || y < 0
121
- || x >= rows. try_into ( ) . unwrap ( )
122
- || y >= cols. try_into ( ) . unwrap ( )
123
- {
124
- found = false ;
125
- break ;
104
+ fn count_word ( & self , word : & str ) -> usize {
105
+ let word_chars: Vec < char > = word. chars ( ) . collect ( ) ;
106
+ let word_len = word_chars. len ( ) ;
107
+ let rows = self . grid . len ( ) ;
108
+ let cols = self . grid [ 0 ] . len ( ) ;
109
+ let mut count = 0 ;
110
+
111
+ let directions = vec ! [
112
+ ( 0 , 1 ) , // Horizontal right
113
+ ( 0 , -1 ) , // Horizontal left
114
+ ( 1 , 0 ) , // Vertical down
115
+ ( -1 , 0 ) , // Vertical up
116
+ ( 1 , 1 ) , // Diagonal down-right
117
+ ( 1 , -1 ) , // Diagonal down-left
118
+ ( -1 , 1 ) , // Diagonal up-right
119
+ ( -1 , -1 ) , // Diagonal up-left
120
+ ] ;
121
+
122
+ for row in 0 ..rows {
123
+ for col in 0 ..cols {
124
+ for ( dx, dy) in & directions {
125
+ let mut found = true ;
126
+
127
+ for ( i, _) in word_chars. iter ( ) . enumerate ( ) . take ( word_len) {
128
+ let x = isize:: try_from ( row) . unwrap ( ) + isize:: try_from ( i) . unwrap ( ) * dx;
129
+ let y = isize:: try_from ( col) . unwrap ( ) + isize:: try_from ( i) . unwrap ( ) * dy;
130
+
131
+ if x < 0
132
+ || y < 0
133
+ || x >= rows. try_into ( ) . unwrap ( )
134
+ || y >= cols. try_into ( ) . unwrap ( )
135
+ {
136
+ found = false ;
137
+ break ;
138
+ }
139
+
140
+ let u_x: usize = usize:: try_from ( x) . unwrap ( ) ;
141
+ let u_y: usize = usize:: try_from ( y) . unwrap ( ) ;
142
+
143
+ if self . grid [ u_x] [ u_y] != word_chars[ i] {
144
+ found = false ;
145
+ break ;
146
+ }
126
147
}
127
148
128
- let u_x: usize = usize:: try_from ( x) . unwrap ( ) ;
129
- let u_y: usize = usize:: try_from ( y) . unwrap ( ) ;
130
-
131
- if grid[ u_x] [ u_y] != word_chars[ i] {
132
- found = false ;
133
- break ;
149
+ if found {
150
+ count += 1 ;
134
151
}
135
152
}
136
-
137
- if found {
138
- count += 1 ;
139
- }
140
153
}
141
154
}
142
- }
143
155
144
- count
156
+ count
157
+ }
145
158
}
0 commit comments