2024/9/odin: solve part 1

This commit is contained in:
2025-08-13 20:56:58 +02:00
parent 4b102c7104
commit 7db243be05
4 changed files with 176 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
input.txt
input

1
2024/9/odin/example.txt Normal file
View File

@@ -0,0 +1 @@
2333133121414131402

BIN
2024/9/odin/main Executable file

Binary file not shown.

173
2024/9/odin/main.odin Normal file
View File

@@ -0,0 +1,173 @@
package aoc2024day9
import "core:container/queue"
import "core:fmt"
import "core:os"
import "core:slice"
import "core:strconv"
import "core:unicode"
PUZZLE_INPUT_PATH :: "input.txt"
EXAMPLE_INPUT_PATH :: "example.txt"
main :: proc() {
path := len(os.args) == 2 ? os.args[1] : PUZZLE_INPUT_PATH
input := string(os.read_entire_file_from_filename(path) or_else panic("damn"))
fmt.println("part 1:", part1(input))
fmt.println("part 2:", part2(input))
}
part2 :: proc(input: string) -> int {
mem: [dynamic]int
defer delete(mem)
free: map[int]int // start_index -> free_space_interval_delta
defer delete(free)
filesizes: map[int]int // fileid -> block_count
defer delete(filesizes)
next_fileid := 0
memptr := 0
for r, i in input {
if !unicode.is_digit(r) {continue}
d := strconv._digit_value(r)
if i % 2 == 0 { // files
for j := 0; j < d; j += 1 {
append(&mem, next_fileid)
memptr += 1
filesizes[next_fileid] = j + 1
}
next_fileid += 1
} else { // free
for j := 0; j < d; j += 1 {
append(&mem, -1)
free[memptr - j] = j + 1
memptr += 1
}
}
}
// fmt.println(free)
// fmt.println(filesizes)
used: [dynamic]int
defer delete(used)
#reverse for fid, i in mem {
if fid < 0 || slice.contains(used[:], fid) {continue}
append(&used, fid)
move := false
size := filesizes[fid]
for f, j in mem {
if f >= 0 || !(j in free) {continue} // TODO: scary slow
t := free[j]
if t >= size {
move = true
for k in 0 ..< size {
mem[j + k] = fid
}
free[j + size] = t - size
break
}
}
if move {
for k in 0 ..< size {
mem[i - k] = -2
}
}
for m in mem {
if m < 0 {
fmt.print("x")
} else {
fmt.print(m)
}
}
fmt.println()
}
// for fid := next_fileid - 1; fid > 0; fid -= 1 {
// size := filesizes[fid]
// memptr -= size
// }
// keys := slice.map_keys(free) or_else panic("damn2")
// slice.sort(keys)
// ptr := 0
// #reverse for fileid, i in mem {
// if fileid < 0 {continue}
// cur := mem[memptr - 1]
// target := filesizes[cur]
// for start, j in keys[ptr:] {
// delta := free[start]
// if delta < target {continue}
// end := delta + start
// }
// }
// #reverse for fileid, i in mem {
// f := queue.peek_front(&free)^
// if queue.len(free) <= 0 || f >= len(mem) {break}
// if fileid >= 0 {
// mem[f] = fileid
// queue.pop_front(&free)
// }
// pop(&mem)
// }
sum := 0
for fileid, i in mem {
if fileid < 0 {continue}
sum += fileid * i
}
return sum
}
part1 :: proc(input: string) -> int {
mem: [dynamic]int
defer delete(mem)
free: queue.Queue(int)
queue.init(&free)
defer queue.destroy(&free)
next_fileid := 0
memptr := 0
for r, i in input {
if !unicode.is_digit(r) {continue}
d := strconv._digit_value(r)
if i % 2 == 0 { // files
for j := 0; j < d; j += 1 {
append(&mem, next_fileid)
memptr += 1
}
next_fileid += 1
} else { // free
for j := 0; j < d; j += 1 {
append(&mem, -1)
queue.push_back(&free, memptr)
memptr += 1
}
}
}
#reverse for fileid, i in mem {
f := queue.peek_front(&free)^
if queue.len(free) <= 0 || f >= len(mem) {break}
if fileid >= 0 {
mem[f] = fileid
queue.pop_front(&free)
}
pop(&mem)
}
sum := 0
for fileid, i in mem {
if fileid < 0 {continue}
sum += fileid * i
// fmt.println(fileid, i)
}
return sum
}