You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
98 lines
2.2 KiB
98 lines
2.2 KiB
#!/usr/bin/env julia
|
|
|
|
using Test
|
|
|
|
function parse_stacks_line(line)
|
|
parts = Iterators.partition(line, 4)
|
|
return [s[2] for s in parts]
|
|
end
|
|
|
|
function read_stacks(io)
|
|
stacks = Vector{Vector{Char}}()
|
|
for line in eachline(io)
|
|
if isempty(line)
|
|
return stacks
|
|
end
|
|
if line[1:3] == " 1 "
|
|
continue
|
|
end
|
|
stacks_row = parse_stacks_line(line)
|
|
while length(stacks_row) > length(stacks)
|
|
push!(stacks, [])
|
|
end
|
|
for (i, c) in Iterators.enumerate(stacks_row)
|
|
if c == ' '
|
|
continue
|
|
end
|
|
pushfirst!(stacks[i], c)
|
|
end
|
|
end
|
|
return stacks
|
|
end
|
|
|
|
struct Move
|
|
count :: Int
|
|
from :: Int
|
|
to :: Int
|
|
end
|
|
|
|
function parse_move_line(line)
|
|
# move 1 from 2 to 1
|
|
parts = split(line)
|
|
return Move(parse(Int, parts[2]), parse(Int, parts[4]), parse(Int, parts[6]))
|
|
end
|
|
|
|
function read_apply_moves(stacks, io; rev::Bool = true)
|
|
for line in eachline(io)
|
|
move = parse_move_line(line)
|
|
if rev
|
|
for i in 1:move.count
|
|
push!(stacks[move.to], pop!(stacks[move.from]))
|
|
end
|
|
else
|
|
from_len = length(stacks[move.from])
|
|
from_range = UnitRange(from_len - move.count + 1, from_len)
|
|
append!(stacks[move.to], splice!(stacks[move.from], from_range))
|
|
end
|
|
end
|
|
return stacks
|
|
end
|
|
|
|
function operate_crane(infile; rev::Bool = true)
|
|
open(infile, "r") do io
|
|
stacks = read_stacks(io)
|
|
stacks2 = read_apply_moves(stacks, io, rev=rev)
|
|
return stacks2
|
|
end
|
|
end
|
|
|
|
function top_crates(stacks)
|
|
return join([last(s) for s in stacks])
|
|
end
|
|
|
|
function test()
|
|
@testset "elf crates 2000" verbose=true begin
|
|
@test top_crates(operate_crane("example.txt")) == "CMZ"
|
|
@test top_crates(operate_crane("input.txt")) == "QNHWJVJZW"
|
|
end
|
|
@testset "elf crates 2001" verbose=true begin
|
|
@test top_crates(operate_crane("example.txt", rev=false)) == "MCD"
|
|
@test top_crates(operate_crane("input.txt", rev=false)) == "BPCZJLFJW"
|
|
end
|
|
end
|
|
|
|
function main()
|
|
if size(ARGS, 1) == 0
|
|
test()
|
|
else
|
|
infile = ARGS[1]
|
|
println("infile = ", infile)
|
|
println("crates: ", read_stacks(infile))
|
|
stacks2 = operate_crane(infile)
|
|
println("after : ", stacks2)
|
|
println("top : ", top_crates(stacks2))
|
|
end
|
|
end
|
|
|
|
main()
|