! 2022 nomennescio USING: accessors combinators io.encodings.utf8 io.files kernel math math.parser prettyprint sequences splitting ; IN: aoc2022 TUPLE: file size name ; TUPLE: dir name parent entries ; UNION: entry file dir ; GENERIC: size ( entry -- size ) M: file size size>> ; M: dir size entries>> [ size ] map-sum ; GENERIC: sizes<=n ( n seq entry -- n seq' ) M: file sizes<=n drop ; M: dir sizes<=n [ entries>> [ sizes<=n ] each ] [ size ] bi dup reach <= [ suffix ] [ drop ] if ; GENERIC: sizes>=n ( n seq entry -- n seq' ) M: file sizes>=n drop ; M: dir sizes>=n [ entries>> [ sizes>=n ] each ] [ size ] bi dup reach >= [ suffix ] [ drop ] if ; : prefix? ( string prefix -- ? ) subseq-index 0 = ; : cd ( cwd dir -- cwd' ) swap entries>> [ name>> over = ] find 2nip ; : add-entry ( cwd entry -- cwd' ) over entries>> push ; : add-dir ( cwd name -- cwd' ) over V{ } clone dir boa add-entry ; : add-file ( cwd size name -- cwd' ) file boa add-entry ; : parse-line ( root cwd line -- root' cwd' ) { { [ dup "$ ls" = ] [ drop ] } { [ dup "$ cd /" = ] [ drop ] } { [ dup "$ cd .." = ] [ drop parent>> ] } { [ dup "$ cd " prefix? ] [ 5 tail cd ] } { [ dup "dir " prefix? ] [ 4 tail add-dir ] } [ " " split1 [ dec> ] dip add-file ] } cond ; : parse-file ( path encoding -- root ) file-lines [ "/" f V{ } clone dir boa dup ] dip [ parse-line ] each drop ; : part1 ( root -- size ) [ 100000 { } clone ] dip sizes<=n sum nip ; : part2 ( root -- size ) [ 30000000 70000000 ] dip [ size - - { } clone ] keep sizes>=n infimum nip ; : day7 ( -- ) "input-7.txt" utf8 parse-file [ part1 . ] [ part2 . ] bi ; MAIN: day7