-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path09p1.odin
79 lines (66 loc) · 1.57 KB
/
09p1.odin
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
package main
import "core:fmt"
import "core:slice"
import "core:strconv"
import "core:strings"
disk_block :: struct {
is_file: bool,
file_id: int,
}
D09P1 :: proc() {
input_string := #load("inputs/09.txt", string)
fs_checksum := get_filesystem_checksum(input_string)
fmt.printf("Filesystem checksum: %d\n", fs_checksum)
}
get_filesystem_checksum :: proc(input: string) -> (checksum: u64) {
fragmented := parse_disk_contents(input)
defer delete(fragmented)
defragment_disk(&fragmented)
for block, i in fragmented {
if block.is_file {
checksum += auto_cast (block.file_id * i)
}
}
return
}
parse_disk_contents :: proc(disk_map: string) -> (blocks: [dynamic]disk_block) {
disk_map_parts := strings.split(disk_map, "", context.temp_allocator)
file_id := 0
for char, i in disk_map_parts {
is_file := i % 2 == 0
size := strconv.atoi(char)
for _ in 0 ..< size {
if is_file {
append(&blocks, disk_block{is_file, file_id})
} else {
append(&blocks, disk_block{is_file, -1})
}
}
if is_file {
file_id += 1
}
}
return
}
defragment_disk :: proc(fragmented: ^[dynamic]disk_block) {
file_blocks: [dynamic]int
defer delete(file_blocks)
file_count := 0
for block in fragmented {
if block.is_file {
append(&file_blocks, block.file_id)
file_count += 1
}
}
slice.reverse(file_blocks[:])
next_file_idx := 0
i := 0
for i < len(fragmented) {
if !fragmented[i].is_file && next_file_idx < len(file_blocks) {
fragmented[i] = disk_block{true, file_blocks[next_file_idx]}
next_file_idx += 1
}
i += 1
}
resize(fragmented, file_count)
}