-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday09.rs
164 lines (136 loc) · 4.78 KB
/
day09.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
use crate::util::file::read;
fn process_file(filename: &str) -> Vec<u32> {
return read(filename)
.unwrap()
.flatten()
.next()
.unwrap()
.chars()
.map(|number| number.to_digit(10).unwrap())
.collect();
}
fn build_memory(disk_map: Vec<u32>) -> Vec<Option<usize>> {
let mut file_id = 0;
let mut memory: Vec<Option<usize>> = vec![];
disk_map
.iter()
.enumerate()
.for_each(|(index, &block_size)| {
let is_file = index % 2 == 0;
for _i in 0..block_size {
if is_file {
memory.push(Some(file_id));
} else {
memory.push(None);
}
}
// Increment the current file id.
if is_file {
file_id += 1;
}
});
return memory;
}
fn calculate_checksum(memory: &Vec<Option<usize>>) -> usize {
return memory
.iter()
.enumerate()
.filter_map(|(pos, id)| {
if id.is_some() {
return Some(pos * (id.unwrap()));
} else {
None
}
})
.sum();
}
fn part1(mut memory: Vec<Option<usize>>) -> usize {
let mut free_memory_index = 0;
let mut file_block_index = memory.len() - 1;
loop {
// Iterate until a free memory index is found.
while memory[free_memory_index].is_some() {
free_memory_index += 1;
}
// Iterate until a file block index is found.
while memory[file_block_index].is_none() {
file_block_index -= 1;
}
if file_block_index <= free_memory_index {
break;
}
memory.swap(free_memory_index, file_block_index);
}
return calculate_checksum(&memory);
}
fn part2(mut memory: Vec<Option<usize>>) -> usize {
let mut file_block_index = memory.len() - 1;
// Each interation of the loop should attempt to move a file block to a
// free memory space.
loop {
// Iterate until a file block index is found.
while memory[file_block_index].is_none() {
file_block_index -= 1;
}
let mut file_block_first_index = file_block_index;
// Get the first index of the file block
while memory[file_block_first_index] == memory[file_block_index] {
if file_block_first_index == 0 {
break;
}
file_block_first_index -= 1;
}
if file_block_first_index == 0 {
break;
}
let block_size = file_block_index - file_block_first_index;
let mut free_memory_index = 0;
let mut free_memory_last_index = free_memory_index;
// Try to find available free memory space
loop {
// Skip memory that has values to try and find available empty memory.
while memory[free_memory_index].is_some() {
free_memory_index += 1;
free_memory_last_index = free_memory_index;
}
// If we start looking at free memory after the current file blocks index,
// we know there isn't an availble spot and can return early.
if free_memory_last_index - 1 > file_block_first_index {
free_memory_index = 0;
free_memory_last_index = 0;
break;
}
// Determine the size of the empty memory.
if memory[free_memory_last_index].is_none() {
free_memory_last_index += 1;
continue;
}
// If the file fits into the free memory, stop looping.
if free_memory_last_index - free_memory_index >= block_size {
break;
}
// If we get here, the current empty memory won't fit the file, so we jump to
// the end to try and find the next available memory index.
free_memory_index = free_memory_last_index;
}
let free_memory_block_size = free_memory_last_index - free_memory_index;
// Swap if the block sizes are equal
if file_block_index > free_memory_index && free_memory_block_size >= block_size {
for i in 0..block_size {
memory.swap(free_memory_index + i, file_block_index - i);
}
}
// Update the file block index references.
file_block_index = file_block_first_index;
}
return calculate_checksum(&memory);
}
pub fn run() -> (usize, usize) {
let disk_map = process_file("input/year2024/day09.txt");
let memory = build_memory(disk_map);
let checksum1 = part1(memory.clone());
let checksum2 = part2(memory);
println!("Part1: {:?}", checksum1);
println!("Part2: {:?}", checksum2);
return (checksum1, checksum2);
}