-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday09.odin
125 lines (108 loc) · 2.22 KB
/
day09.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
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
package day09
import "core:fmt"
import "core:os"
import "core:slice"
import "core:strconv"
import "core:strings"
main :: proc() {
content, ok := os.read_entire_file("input/day09.txt")
if !ok {
// could not read file
return
}
defer delete(content)
disk_map := slice.mapper(
strings.split(strings.split_lines(string(content))[0], ""),
proc(s: string) -> int {return strconv.atoi(s)},
)
space_sum := slice.reduce(disk_map, 0, proc(a, n: int) -> int {return a + n})
disk := make([]int, space_sum)
disk_idx := 0
file_id := 0
free_space := false
for i in disk_map {
for j in 0 ..< i {
if free_space {
disk[disk_idx + j] = -1
} else {
disk[disk_idx + j] = file_id
}
}
if !free_space {
file_id += 1
}
disk_idx += i
free_space = !free_space
}
// Part 1
fmt.println(checksum(rearrange_1(disk)))
// Part 2
fmt.println(checksum(rearrange_2(disk)))
}
rearrange_1 :: proc(_disk: []int) -> []int {
disk := make([]int, len(_disk))
copy_slice(disk[:], _disk[:])
end_idx := len(disk) - 1
for curr_idx in 0 ..< len(disk) {
for disk[end_idx] == -1 {
end_idx -= 1
}
if curr_idx >= end_idx {
break
}
if disk[curr_idx] == -1 {
disk[curr_idx] = disk[end_idx]
disk[end_idx] = -1
}
}
return disk
}
rearrange_2 :: proc(_disk: []int) -> []int {
disk := make([]int, len(_disk))
copy_slice(disk[:], _disk[:])
for i := len(disk) - 1; i > 0; i -= 1 {
fid := disk[i]
if fid == -1 {
continue
}
file_end := i
file_start := i
for file_start >= 0 && disk[file_start] == disk[file_end] {
file_start -= 1
}
file_start += 1
file_end += 1
file_size := file_end - file_start
for j := 0; j < i; j += 1 {
if disk[j] != -1 {
continue
}
free_start := j
free_end := j
for disk[free_start] == disk[free_end] {
free_end += 1
}
free_end -= 1
free_size := free_end - free_start + 1
if free_size >= file_size {
copy_slice(disk[free_start:free_end + 1], disk[file_start:file_end])
for k in file_start ..< file_end {
disk[k] = -1
}
break
}
}
i -= file_size - 1
}
return disk
}
checksum :: proc(disk: []int) -> int {
result := 0
for id, idx in disk {
if id == -1 {
continue
}
result += (idx * id)
}
return result
}