Mercurial > lbo > hg > aoc22
view 07/07.jl @ 9:a7b3529283e9
day 07, parsing of part 1
author | Lewin Bormann <lbo@spheniscida.de> |
---|---|
date | Fri, 09 Dec 2022 23:09:01 +0100 |
parents | |
children | d110dc63f18e |
line wrap: on
line source
const input::String = "07/input.txt" import Base: push! using ParserCombinator abstract type Entry end struct File <: Entry name::String size::Int end struct Dir <: Entry name::String children::Vector{Entry} end function filename(f::File)::String f.name end function filesize(f::File)::Int f.size end function filename(f::Dir)::String f.name end function filesize(d::Dir)::Int sum(filesize(f) for f in d.children) end function push!(d::Dir, e::Entry) # Avoid duplication of entries if !isnothing(findnext((==)(e), d.children, 1)) return; end push!(d.children, e::Entry); end function cd(d::Dir, s::String)::Entry d.children[findnext(e -> filename(e) == s, d.children, 1)] end abstract type TerminalLine end struct Cd <: TerminalLine dir::String end struct Ls <: TerminalLine contents::Vector{Entry} end # Parsers ParseFilename() = p"[a-z/\.]+" |> (x -> string(x[1])) ParseCd() = (E"cd " + ParseFilename()) |> (x -> Cd(x[1])) ParseLs() = (E"ls" + Eos()) |> (_ -> Ls([])) ParseCommandLine() = E"$ " + (ParseCd() | ParseLs()) + Eos() ParseLsEntry() = ((E"dir " + ParseFilename()) |> (d -> Dir(d[1], []))) | ((PInt() + E" " + ParseFilename()) |> (f -> File(f[2], f[1]))) + Eos() function build_filesystem(io::IO)::Entry root = Dir("/", []) current = root path = [] pcl = ParseCommandLine() ple = ParseLsEntry() state = "shell"; for line in eachline(io) parsed = false; while !parsed if state == "shell" cmd = parse_one(line, pcl)[1] parsed = true; if isa(cmd, Cd) if (cmd::Cd).dir == "/" current = root; path = []; elseif (cmd::Cd).dir == ".." current = pop!(path); else push!(path, current); oc = current; current = cd(current, (cmd::Cd).dir); end elseif isa(cmd, Ls) state = "ls"; else error("unknown type: ", line); end elseif state == "ls" try e = parse_one(line, ple)[1]::Entry; println(e, " -> ", current); push!(current, e); parsed = true; catch exc state = "shell"; end else error("unknown state ", state); end end end root end open("07/small.txt"; read=true) do fh println(build_filesystem(fh)) end