view 05/05.jl @ 6:dea8d8f60e25

Finish day 05 part 01
author Lewin Bormann <lbo@spheniscida.de>
date Wed, 07 Dec 2022 22:14:02 +0100
parents dc901991442c
children 6344dda06b86
line wrap: on
line source

const input = "05/input.txt";

mutable struct Crates
    stacks::Vector{Vector{Char}}
end

using ParserCombinator

crate = (
    (
        (E"[" + p"[A-Z]" + E"]") |> s -> s[1][1])
    | (E"   " |> _ -> nothing)) + (E" " | Eos())
crate_row = Repeat(crate) + Eos()

crate_base = Repeat(P"\s*"+ p"\d" + P"\s*", 1, 100) + Eos()

function parse_stacks(lines::Vector{String})::Crates
    stacks = nothing
    # start is the line on which instructions start.
    start = 3
    for l in lines
        try
            cs = parse_one(chomp(l), crate_row);
            if isnothing(stacks)
                stacks = Crates([Vector{Char}() for i in 1:length(cs)])
            end
            for (i, e) in enumerate(cs)
                # inefficient but saves reversing
                if !isnothing(e)
                    pushfirst!(stacks.stacks[i], e);
                end
            end
            start += 1
        catch e
            @assert typeof(e) == ParserException
            break
        end
    end
    println(stacks)
    stacks
end

struct Instr
    n::Int
    from::Int
    to::Int
end

instruction = E"move " + PInt() + E" from " + PInt() + E" to " + PInt() + Eos()

function parse_instructions(lines::Vector{String})::Vector{Instr}
    v = Vector{Instr}();
    for l in lines
        try
            i = parse_one(chomp(l), instruction);
            push!(v, Instr(i[1], i[2], i[3]));
        catch e
            @assert typeof(e) == ParserException
        end
    end
    @show v
    v
end

function act(init::Crates, instr::Vector{Instr})::Crates
    for i in instr
        @assert length(init.stacks[i.from]) >= i.n
        for j in 1:i.n
            push!(init.stacks[i.to], pop!(init.stacks[i.from]));
        end
    end
    init
end

function endresult1(c::Crates)::String
    String([s[end] for s in c.stacks])
end

function run_05(f::String)
    open(f; read=true) do fh
        ls = collect(eachline(fh));
        crates = parse_stacks(ls);
        instrs = parse_instructions(ls);
        crates2 = act(crates, instrs);
        println(endresult1(crates2));
    end
end

run_05(input);