include("utils.jl") function interval(coords) coords[1]:coords[2] end function parse_input(filename) map(non_empty_lines(filename)) do line command, coords = split(line) coords = map(x->parse(Int, x.match), eachmatch(r"-?[0-9]+", coords)) coords = [interval(sort(coords[1:2])), interval(sort(coords[3:4])), interval(sort(coords[5:6]))] command, coords end end function ccontains(a, b) all(issubset.(a, b)) end function cempty(cube) reduce(min, length.(cube)) == 0 end function setdiffcubes(cube, subcube) above = [cube[1], cube[2], (subcube[3].stop+1):(cube[3].stop)] below = [cube[1], cube[2], (cube[3].start):(subcube[3].start-1)] far = [cube[1], (subcube[2].stop+1):(cube[2].stop), subcube[3]] near = [cube[1], (cube[2].start):(subcube[2].start-1), subcube[3]] right = [(subcube[1].stop+1):(cube[1].stop), subcube[2], subcube[3]] left = [(cube[1].start):(subcube[1].start-1), subcube[2], subcube[3]] filter(c->!cempty(c), [above, below, far, near, right, left]) end function add_cube(cubes, cube) if length(cubes) == 0 return [cube] end if any(map(c->ccontains(cube, c), cubes)) return cubes end cubes = filter(c->!ccontains(c, cube), cubes) result = [cube] for c in cubes inter = intersect.(c, cube) if cempty(inter) push!(result, c) else append!(result, setdiffcubes(c, inter)) end end result end function remove_cube(cubes, cube) if length(cubes) == 0 return [] end result = [] for c in cubes if ccontains(c, cube) continue end inter = intersect.(c, cube) if cempty(inter) push!(result, c) continue end append!(result, setdiffcubes(c, inter)) end result end function magnitude(cube) reduce(*, length.(cube)) end function run(filter=nothing) cubes = [] for (command, coords) in parse_input("22.data") if typeof(filter) == Int64 && reduce(max, map(x->reduce(max, abs.(x)), coords)) > filter continue end if command == "on" cubes = add_cube(cubes, coords) else cubes = remove_cube(cubes, coords) end end sum(map(magnitude, cubes)) end function solution22_1() run(50) end function solution22_2() run() end solution22_1(), solution22_2()