61 lines
1.4 KiB
Julia
61 lines
1.4 KiB
Julia
|
|
const ID = Union{Int,Nothing}
|
|
function getDisk()
|
|
local blocks::Vector{Int8} = [ x - Int('0') for x in collect(read("input/9")) ][1:end-1]
|
|
local disk::Vector{ID} = Vector()
|
|
for b in 1:length(blocks)
|
|
local id = (b - 1) ÷ 2
|
|
local size = blocks[b]
|
|
local isFile = b & 1 == 1
|
|
for i in 1:size
|
|
push!(disk, isFile ? id : nothing)
|
|
end
|
|
end
|
|
return disk
|
|
end
|
|
|
|
const disk = getDisk()
|
|
|
|
function compress!(arr::AbstractVector, selectRange = (arr, i) -> i:i)
|
|
for i in reverse(1:length(arr))
|
|
if !isnothing(arr[i])
|
|
local fillerRange = selectRange(arr, i)
|
|
local head = 1
|
|
while head < i
|
|
if isnothing(arr[head])
|
|
local emptyRange = selectRange(arr, head)
|
|
local l = length(fillerRange)
|
|
if length(emptyRange) >= l
|
|
local s = emptyRange[1]
|
|
arr[s:s+l-1] = arr[fillerRange]
|
|
arr[fillerRange] .= nothing
|
|
break
|
|
else
|
|
head += l
|
|
continue
|
|
end
|
|
else
|
|
head += 1
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return arr
|
|
end
|
|
|
|
function selectRangeChunk(arr, i)
|
|
local c, lower, upper = arr[i], i, i
|
|
while lower > 1 && arr[lower-1] == c
|
|
lower -= 1
|
|
end
|
|
while upper < length(arr) && arr[upper+1] == c
|
|
upper += 1
|
|
end
|
|
return lower:upper
|
|
end
|
|
|
|
checksum(arr) = mapreduce(x -> isnothing(x[2]) ? 0 : (x[1]-1) * x[2], +, enumerate(arr))
|
|
|
|
println("Part one ", checksum(compress!(copy(disk))))
|
|
println("Part two ", checksum(compress!(copy(disk), selectRangeChunk)))
|
|
|