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)))