mirror of
https://github.com/fredrikr79/advent_of_code.git
synced 2026-01-19 23:38:21 +01:00
174 lines
3.3 KiB
Odin
174 lines
3.3 KiB
Odin
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
|
|
}
|