@@ -4,6 +4,7 @@ advent_of_code::solution!(9);
44
55#[ derive( Debug , Clone ) ]
66struct Block {
7+ start_idx : usize ,
78 length : u32 ,
89 file_id : Option < u32 > ,
910}
@@ -19,10 +20,12 @@ impl Block {
1920 } else {
2021 (
2122 Block {
22- length : length,
23+ start_idx : self . start_idx ,
24+ length,
2325 file_id : self . file_id ,
2426 } ,
2527 Some ( Block {
28+ start_idx : self . start_idx + length as usize ,
2629 length : self . length - length,
2730 file_id : self . file_id ,
2831 } ) ,
@@ -31,36 +34,6 @@ impl Block {
3134 }
3235}
3336
34- // struct BlocksFmt<'a>(&'a Vec<Block>);
35-
36- // impl Debug for BlocksFmt<'_> {
37- // fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38- // for block in self.0 {
39- // for _ in 0..block.length {
40- // match block.file_id {
41- // Some(id) => write!(f, "{}", id)?,
42- // None => write!(f, ".")?,
43- // }
44- // }
45- // }
46- // Ok(())
47- // }
48- // }
49-
50- fn checksum ( blocks : & Vec < Block > ) -> u64 {
51- let mut sum: u64 = 0 ;
52- let mut idx = 0 ;
53- for block in blocks {
54- for _ in 0 ..block. length {
55- if let Some ( file_id) = block. file_id {
56- sum += idx * ( file_id as u64 ) ;
57- }
58- idx += 1 ;
59- }
60- }
61- sum
62- }
63-
6437fn parse_blocks ( input : & str ) -> Vec < Block > {
6538 let nums = input
6639 . chars ( )
@@ -69,6 +42,7 @@ fn parse_blocks(input: &str) -> Vec<Block> {
6942 . map ( |r| r. unwrap ( ) ) ;
7043
7144 let mut blocks = Vec :: with_capacity ( 1000 ) ;
45+ let mut idx = 0 ;
7246 for ( i, num) in nums. enumerate ( ) {
7347 let file_id = if i % 2 == 0 {
7448 Some ( ( i / 2 ) as u32 )
@@ -81,11 +55,13 @@ fn parse_blocks(input: &str) -> Vec<Block> {
8155 }
8256
8357 let b = Block {
58+ start_idx : idx,
8459 file_id,
8560 length : num,
8661 } ;
8762
8863 blocks. push ( b) ;
64+ idx += num as usize ;
8965 }
9066
9167 blocks
@@ -149,11 +125,15 @@ pub fn part_two(input: &str) -> Option<u64> {
149125 spaces_block_indices_by_size[ b. length as usize ] . push ( i) ;
150126 } ) ;
151127
152- let mut right_block_idx = blocks. len ( ) - 1 ;
153- while right_block_idx > 0 {
128+ let mut checksum = 0 ;
129+
130+ for right_block_idx in ( 0 ..blocks. len ( ) ) . rev ( ) {
154131 let right_block = & blocks[ right_block_idx] . clone ( ) ;
155132 if right_block. is_free ( ) {
156- right_block_idx -= 1 ;
133+ continue ;
134+ }
135+
136+ if right_block. length == 0 {
157137 continue ;
158138 }
159139
@@ -167,50 +147,47 @@ pub fn part_two(input: &str) -> Option<u64> {
167147 }
168148 }
169149
150+ // can't move the file, so just add to the checksum
170151 if best_free_space_block_idx == usize:: MAX {
171- right_block_idx -= 1 ;
152+ checksum += ( 0 ..right_block. length as u64 )
153+ . map ( |i| ( right_block. start_idx as u64 + i) )
154+ . sum :: < u64 > ( )
155+ * right_block. file_id . unwrap ( ) as u64 ;
172156 continue ;
173157 }
174158
175159 let left_block_idx = best_free_space_block_idx;
176- let left_block = & blocks[ left_block_idx] ;
160+ let left_block = & blocks[ left_block_idx] . clone ( ) ;
177161 spaces_block_indices_by_size[ left_block. length as usize ] . pop ( ) ;
178162
179163 let ( _, maybe_left_additional_space) = left_block. split ( right_block. length ) ;
180164 if let Some ( left_additional_space) = maybe_left_additional_space {
181- let new_idx = left_block_idx + 1 ;
182- blocks. insert ( left_block_idx, right_block. clone ( ) ) ;
183-
184- // shift all the indices that are greater than the left block index
185- spaces_block_indices_by_size
186- . iter_mut ( )
187- . flat_map ( |space_list| space_list. iter_mut ( ) )
188- . filter ( |idx| * * idx > left_block_idx)
189- . for_each ( |idx| * idx += 1 ) ;
190-
191165 // add the new space to the list
192166 let space_list =
193167 & mut spaces_block_indices_by_size[ left_additional_space. length as usize ] ;
194168 let mut insert_idx = space_list. len ( ) ;
195169 for i in ( 0 ..space_list. len ( ) ) . rev ( ) {
196- if space_list[ i] > new_idx {
170+ if space_list[ i] > left_block_idx {
197171 break ;
198172 }
199173 insert_idx = i;
200174 }
201- space_list. insert ( insert_idx, new_idx ) ;
175+ space_list. insert ( insert_idx, left_block_idx ) ;
202176
203- blocks[ new_idx] = left_additional_space;
204- right_block_idx += 1 ;
177+ blocks[ left_block_idx] = left_additional_space;
205178 } else {
206- blocks[ left_block_idx] = right_block . clone ( ) ;
179+ blocks[ left_block_idx] . length = 0 ;
207180 }
208181
209- blocks[ right_block_idx] . file_id = None ;
210- right_block_idx -= 1 ;
182+ let checksum_contribution = ( 0 ..right_block. length as u64 )
183+ . map ( |i| ( left_block. start_idx as u64 + i) )
184+ . sum :: < u64 > ( )
185+ * right_block. file_id . unwrap ( ) as u64 ;
186+
187+ checksum += checksum_contribution
211188 }
212189
213- Some ( checksum ( & blocks ) )
190+ Some ( checksum)
214191}
215192
216193#[ cfg( test) ]
0 commit comments