1
+ use std:: cmp:: Ordering ;
2
+
1
3
use util:: input_lines;
2
4
3
- #[ derive( Debug ) ]
5
+ #[ derive( Debug , Clone ) ]
4
6
struct Map {
5
7
dest : u64 ,
6
8
src : u64 ,
@@ -21,8 +23,22 @@ impl Map {
21
23
len : iter. next ( ) . unwrap ( ) . parse ( ) . unwrap ( ) ,
22
24
} )
23
25
}
26
+ v. sort_by ( |a, b| a. src . cmp ( & b. src ) ) ;
24
27
v
25
28
}
29
+ fn get_dest ( & self , src : u64 ) -> u64 {
30
+ assert ! ( self . contains( src) ) ;
31
+ self . dest + src - self . src
32
+ }
33
+ fn contains ( & self , src : u64 ) -> bool {
34
+ src >= self . src && src < self . src + self . len
35
+ }
36
+ fn src_upper_limit ( & self ) -> u64 {
37
+ let max = self . src + self . len - 1 ;
38
+ assert ! ( self . contains( max) ) ;
39
+ assert ! ( !self . contains( max + 1 ) ) ;
40
+ max
41
+ }
26
42
}
27
43
28
44
#[ derive( Debug , Default ) ]
@@ -39,19 +55,57 @@ struct Input {
39
55
40
56
trait GetDest {
41
57
fn get_dest ( & self , src : u64 ) -> u64 ;
58
+ fn get_first_src_range ( & self , src : u64 , max : u64 ) -> ( u64 , u64 ) ;
59
+ fn get_src_ranges ( & self , min : u64 , max : u64 ) -> Vec < ( u64 , u64 ) > {
60
+ let mut v = Vec :: new ( ) ;
61
+ let mut x = min;
62
+ while x < max {
63
+ v. push ( self . get_first_src_range ( x, max) ) ;
64
+ x = v. last ( ) . unwrap ( ) . 1 + 1 ;
65
+ }
66
+ v
67
+ }
68
+ fn get_dest_ranges ( & self , src_min : u64 , src_max : u64 ) -> Vec < ( u64 , u64 ) > ;
69
+ fn get_many_dest_ranges ( & self , ranges : & [ ( u64 , u64 ) ] ) -> Vec < ( u64 , u64 ) > {
70
+ let mut v = Vec :: new ( ) ;
71
+ for ( min, max) in ranges {
72
+ v. extend ( self . get_dest_ranges ( * min, * max) ) ;
73
+ }
74
+ v
75
+ }
42
76
}
43
77
44
78
impl GetDest for Vec < Map > {
45
79
fn get_dest ( & self , src : u64 ) -> u64 {
46
80
for m in self {
47
- if src >= m . src && src < m . src + m . len {
48
- println ! ( "{} --> {}" , src, m. dest + src - m. src) ;
49
- return m. dest + src - m . src ;
81
+ if m . contains ( src) {
82
+ // println!("{} --> {}", src, m.dest + src - m.src);
83
+ return m. get_dest ( src) ;
50
84
}
51
85
}
52
- println ! ( "{} --> {}" , src, src) ;
86
+ // println!("{} --> {}", src, src);
53
87
src
54
88
}
89
+
90
+ fn get_first_src_range ( & self , src : u64 , max : u64 ) -> ( u64 , u64 ) {
91
+ for m in self {
92
+ if m. contains ( src) {
93
+ return ( src, std:: cmp:: min ( max, m. src_upper_limit ( ) ) ) ;
94
+ }
95
+ if m. src > src {
96
+ return ( src, std:: cmp:: min ( max, m. src - 1 ) ) ;
97
+ }
98
+ }
99
+ ( src, max)
100
+ }
101
+
102
+ fn get_dest_ranges ( & self , src_min : u64 , src_max : u64 ) -> Vec < ( u64 , u64 ) > {
103
+ let mut v = Vec :: new ( ) ;
104
+ for ( min, max) in self . get_src_ranges ( src_min, src_max) {
105
+ v. push ( ( self . get_dest ( min) , self . get_dest ( max) ) ) ;
106
+ }
107
+ v
108
+ }
55
109
}
56
110
57
111
impl Input {
@@ -100,6 +154,26 @@ impl Input {
100
154
) ,
101
155
)
102
156
}
157
+ fn get_best ( & self , min : u64 , max : u64 ) -> u64 {
158
+ let locs = self . humidity_to_location . get_many_dest_ranges (
159
+ & self . temp_to_humidity . get_many_dest_ranges (
160
+ & self . light_to_temp . get_many_dest_ranges (
161
+ & self . water_to_light . get_many_dest_ranges (
162
+ & self . fertilizer_to_water . get_many_dest_ranges (
163
+ & self
164
+ . soil_to_fertilizer
165
+ . get_many_dest_ranges ( & self . seed_to_soil . get_dest_ranges ( min, max) ) ,
166
+ ) ,
167
+ ) ,
168
+ ) ,
169
+ ) ,
170
+ ) ;
171
+ let mut min = locs[ 0 ] . 0 ;
172
+ for loc in locs {
173
+ min = std:: cmp:: min ( min, loc. 0 ) ;
174
+ }
175
+ min
176
+ }
103
177
}
104
178
105
179
fn main ( ) {
@@ -109,4 +183,68 @@ fn main() {
109
183
min_loc = std:: cmp:: min ( min_loc, i. get_loc ( * seed) ) ;
110
184
}
111
185
println ! ( "Part 1: {}" , min_loc) ;
186
+ let mut min_loc = i. get_loc ( i. seeds [ 0 ] ) ;
187
+ let mut iter = i. seeds . iter ( ) ;
188
+ while let Some ( start) = iter. next ( ) {
189
+ min_loc = std:: cmp:: min ( min_loc, i. get_best ( * start, * start + * iter. next ( ) . unwrap ( ) ) ) ;
190
+ }
191
+ println ! ( "Part 2: {}" , min_loc) ;
192
+ }
193
+
194
+ #[ cfg( test) ]
195
+ mod tests {
196
+ use super :: * ;
197
+
198
+ #[ test]
199
+ fn test_map ( ) {
200
+ let map = Map {
201
+ dest : 10 ,
202
+ src : 100 ,
203
+ len : 10 ,
204
+ } ;
205
+ assert ! ( !map. contains( 99 ) ) ;
206
+ assert ! ( map. contains( 100 ) ) ;
207
+ assert ! ( map. contains( 109 ) ) ;
208
+ assert ! ( !map. contains( 110 ) ) ;
209
+ assert_eq ! ( map. src_upper_limit( ) , 109 ) ;
210
+ assert_eq ! ( map. get_dest( 100 ) , 10 ) ;
211
+ assert_eq ! ( map. get_dest( 109 ) , 19 ) ;
212
+ }
213
+
214
+ #[ test]
215
+ fn test_get_dest ( ) {
216
+ let v = vec ! [ Map {
217
+ dest: 10 ,
218
+ src: 100 ,
219
+ len: 10 ,
220
+ } ] ;
221
+ assert_eq ! ( v. get_dest( 99 ) , 99 ) ;
222
+ assert_eq ! ( v. get_dest( 100 ) , 10 ) ;
223
+ assert_eq ! ( v. get_dest( 109 ) , 19 ) ;
224
+ assert_eq ! ( v. get_dest( 110 ) , 110 ) ;
225
+
226
+ assert_eq ! ( v. get_first_src_range( 10 , 1000 ) , ( 10 , 99 ) ) ;
227
+ assert_eq ! ( v. get_first_src_range( 103 , 1000 ) , ( 103 , 109 ) ) ;
228
+ assert_eq ! ( v. get_first_src_range( 120 , 1000 ) , ( 120 , 1000 ) ) ;
229
+
230
+ assert_eq ! ( v. get_src_ranges( 10 , 20 ) , [ ( 10 , 20 ) ] ) ;
231
+ assert_eq ! ( v. get_src_ranges( 101 , 103 ) , [ ( 101 , 103 ) ] ) ;
232
+ assert_eq ! ( v. get_src_ranges( 110 , 120 ) , [ ( 110 , 120 ) ] ) ;
233
+ assert_eq ! ( v. get_src_ranges( 10 , 105 ) , [ ( 10 , 99 ) , ( 100 , 105 ) ] ) ;
234
+ assert_eq ! ( v. get_src_ranges( 105 , 1000 ) , [ ( 105 , 109 ) , ( 110 , 1000 ) ] ) ;
235
+ assert_eq ! (
236
+ v. get_src_ranges( 10 , 1000 ) ,
237
+ [ ( 10 , 99 ) , ( 100 , 109 ) , ( 110 , 1000 ) ]
238
+ ) ;
239
+
240
+ assert_eq ! ( v. get_dest_ranges( 10 , 20 ) , [ ( 10 , 20 ) ] ) ;
241
+ assert_eq ! ( v. get_dest_ranges( 101 , 103 ) , [ ( 11 , 13 ) ] ) ;
242
+ assert_eq ! ( v. get_dest_ranges( 110 , 120 ) , [ ( 110 , 120 ) ] ) ;
243
+ assert_eq ! ( v. get_dest_ranges( 10 , 105 ) , [ ( 10 , 99 ) , ( 10 , 15 ) ] ) ;
244
+ assert_eq ! ( v. get_dest_ranges( 105 , 1000 ) , [ ( 15 , 19 ) , ( 110 , 1000 ) ] ) ;
245
+ assert_eq ! (
246
+ v. get_dest_ranges( 10 , 1000 ) ,
247
+ [ ( 10 , 99 ) , ( 10 , 19 ) , ( 110 , 1000 ) ]
248
+ ) ;
249
+ }
112
250
}
0 commit comments