#!/usr/bin/env julia using Test mutable struct Dir path :: String dnames :: Vector{String} fsize :: Int32 end function get_dir_map(infile) cwd = Vector{String}() path = "/" dirmap = Dict{String, Dir}() open(infile, "r") do io for line in eachline(io) parts = split(line) if parts[1] == "\$" if parts[2] == "cd" if parts[3] == "/" empty!(cwd) elseif parts[3] == ".." pop!(cwd) else push!(cwd, parts[3]) end path = "/" * join(cwd, '/') if ! haskey(dirmap, path) dirmap[path] = Dir(path, [], 0) end elseif parts[2] != "ls" println("Unknown command: ", line) end else parts = split(line, limit=2) if parts[1] == "dir" push!(dirmap[path].dnames, joinpath(path, parts[2])) else dirmap[path].fsize += parse(Int, parts[1]) end end end end for k in sort(collect(keys(dirmap)), by=p->length(p), rev=true) v = dirmap[k] for p in v.dnames dirmap[k].fsize += dirmap[p].fsize end end return dirmap end function small_dir_sum(infile) dirmap = get_dir_map(infile) small_sum = 0 for v in values(dirmap) if v.fsize <= 100000 small_sum += v.fsize end end return small_sum end function delete_candidate_size(infile) dirmap = get_dir_map(infile) total = 70000000 want = 30000000 used = dirmap["/"].fsize free = total - used need = want - free candidates = Vector{Int64}() # println("used ", used) # println("free ", free) # println("need ", need) for v in values(dirmap) if v.fsize >= need push!(candidates, v.fsize) end end return minimum(candidates) end function test() @testset "disk usage small dir sum" verbose=true begin @test small_dir_sum("example.txt") == 95437 @test small_dir_sum("input.txt") == 1306611 end @testset "disk usage delete candidate size" verbose=true begin @test delete_candidate_size("example.txt") == 24933642 @test delete_candidate_size("input.txt") == 13210366 end end function main() if size(ARGS, 1) == 0 test() else infile = ARGS[1] println("infile = ", infile) println("error priority sum: ", rucksack_errors(infile)) end end main()