my %dirs;
my @cwd;
grammar FileTree {
rule TOP { <command> || <dir-item> || <file-item> }
rule command { '$' [ 'ls' || <cd-command> ] }
rule cd-command { 'cd' <node-name> }
rule dir-item { 'dir' <node-name> }
rule file-item { <file-size> <node-name> }
token node-name { '/' || '..' || <[a..z] + [\.]>+ }
token file-size { \d+ }
}
class FTactions {
method cd-command($/) {
given $<node-name>.made {
when '/' { @cwd = '' }
when '..' { @cwd.pop }
default { @cwd.push($_) }
}
}
method file-item($/) {
for [\~] @cwd.map({ "$_/" }) -> \dir {
%dirs{dir} += $<file-size>.made;
}
}
method node-name($/) { make $/.Str }
method file-size($/) { make $/.Int }
}
FileTree.parse($_, :actions(FTactions)) for $*IN.lines;
put 'part 1: ', %dirs.values.grep(* ≤ 10_0000).sum;
put 'part 2: ', %dirs.values.sort.first(* ≥ %dirs</> - 4000_0000);