@@ -91,55 +91,40 @@ fn parse_blocks(input: &str) -> Vec<Block> {
9191}
9292
9393pub fn part_one ( input : & str ) -> Option < u64 > {
94- let mut blocks = parse_blocks ( input) ;
95-
96- // have 2 pointers, one at the start of the disk, one at the end
97- // move the pointer at the end to the leftmost free space block
98- // move the pointer at the start to the rightmost file block
99- // if the pointers meet, we're done
100- // if we have a free space block, we want to grab some of the file blocks to put in place of it
101-
102- let mut left_block_idx = 0 ;
103- let mut right_block_idx = blocks. len ( ) - 1 ;
104- while left_block_idx < right_block_idx {
105- let left_block = & blocks[ left_block_idx] ;
106- let right_block = & blocks[ right_block_idx] ;
107-
108- if !left_block. is_free ( ) {
109- left_block_idx += 1 ;
94+ const EMPTY : usize = usize:: MAX ;
95+ let nums: Vec < usize > = input
96+ . chars ( )
97+ . map ( |c| c. to_digit ( 10 ) )
98+ . filter ( |r| r. is_some ( ) )
99+ . map ( |r| r. unwrap ( ) )
100+ . enumerate ( )
101+ // create the full disk with all the file ids
102+ . flat_map ( |( i, num) | ( 0 ..num) . map ( move |_| if i % 2 == 0 { i / 2 } else { EMPTY } ) )
103+ . collect ( ) ;
104+
105+ let mut left = 0 ;
106+ let mut right = nums. len ( ) - 1 ;
107+ let mut checksum = 0 ;
108+ while left <= right {
109+ let left_num = nums[ left] ;
110+ if left_num != EMPTY {
111+ checksum += ( left * left_num) as u64 ;
112+ left += 1 ;
110113 continue ;
111114 }
112115
113- if !right_block. is_file ( ) {
114- right_block_idx -= 1 ;
116+ let right_num = nums[ right] ;
117+ if right_num != EMPTY {
118+ checksum += ( left * right_num) as u64 ;
119+ right -= 1 ;
120+ left += 1 ;
115121 continue ;
116122 }
117123
118- // now we have a free space block and a file block
119- // we want to grab some of the file blocks to put in place of the free space block
120-
121- let left_size = left_block. length ;
122- let ( right_movable, maybe_right_unmovable) = right_block. split ( left_size) ;
123- let ( _, maybe_left_additional_space) = left_block. split ( right_movable. length ) ;
124-
125- // move the movable part
126- if let Some ( left_additional_space) = maybe_left_additional_space {
127- blocks. insert ( left_block_idx, right_movable) ;
128- blocks[ left_block_idx + 1 ] = left_additional_space;
129- right_block_idx += 1 ;
130- } else {
131- blocks[ left_block_idx] = right_movable;
132- }
133-
134- if let Some ( right_unmovable) = maybe_right_unmovable {
135- blocks[ right_block_idx] = right_unmovable;
136- } else {
137- blocks. remove ( right_block_idx) ;
138- right_block_idx -= 1 ;
139- }
124+ right -= 1 ;
140125 }
141126
142- Some ( checksum ( & blocks ) )
127+ Some ( checksum)
143128}
144129
145130pub fn part_two ( input : & str ) -> Option < u64 > {
0 commit comments