!!! this is REALLY TERRIBLE code... I was too tired to refactor after solving USING: arrays combinators grouping io.encodings.utf8 io.files kernel math math.parser math.unicode sequences splitting strings ; IN: aoc.7 : I ( -- input-file ) "~/factor/aoc/7/7.in" utf8 file-lines ; : get-dir ( dir cmd -- dir ) { { [ dup 4 head "cd ." = ] [ drop but-last ] } { [ dup 2 head "cd" = ] [ split-words second suffix ] } [ drop ] } cond ; ! dirs are in the form { { dir contents } } : add-dirs ( {commands} -- dirs ) [ V{ } [ get-dir ] accumulate* ] keep [ 2array ] 2map ; : remove-commands ( dirs -- dirs ) [ last 2 head "cd" ≠ ] filter ; : group-output ( ls-and-output -- grouped ) split-words rest 2 group ; : get-importants ( {dir,name}|{size,name}s -- infos ) [ first2 over "dir" = [ nip ] [ drop dec> ] if ] map ; : remove-file-names ( dirs -- dirs ) [ first2 group-output get-importants 2array ] map ; :: absolute-path ( path contents -- contents' ) contents [ dup string? [ path swap suffix ] [ ] if ] map ; ! 2 tail to remove leading `$ cd /`, then rest to remove space from after prompt : input ( -- input ) I " " join "$" split 2 tail [ [ 32 = ] trim ] map add-dirs remove-commands remove-file-names [ first2 dupd absolute-path 2array ] map ; : dir-name ( dir -- str ) first "/" join ; : get-size-by-name ( dirs name -- dirs size ) dupd [ swap dir-name = ] curry find nip last [ dup number? [ ] [ "/" join get-size-by-name ] if ] map sum ; : sizes ( -- sizes ) input dup [ dir-name get-size-by-name ] map nip ; : part1 ( -- n ) sizes [ 100000 <= ] filter sum ; : part2 ( -- n ) sizes unclip [ max ] reduce 40000000 - [ >= ] curry sizes swap filter unclip [ min ] reduce ; : solve ( -- ) part1 . part2 . ;