@@ -91,55 +91,40 @@ fn parse_blocks(input: &str) -> Vec<Block> {
91
91
}
92
92
93
93
pub 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 ;
110
113
continue ;
111
114
}
112
115
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 ;
115
121
continue ;
116
122
}
117
123
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 ;
140
125
}
141
126
142
- Some ( checksum ( & blocks ) )
127
+ Some ( checksum)
143
128
}
144
129
145
130
pub fn part_two ( input : & str ) -> Option < u64 > {
0 commit comments