! Copyright (C) 2022 Your name. ! See http://factorcode.org/license.txt for BSD license. USING: accessors arrays assocs combinators io.encodings.utf8 io.files kernel math math.parser prettyprint regexp sequences sequences.deep sorting splitting ; IN: dec-7 TUPLE: directory up name subdirectories files ; SYMBOL: root : ( name subdirectories files -- directory ) [ f ] 3dip clone directory boa ; : empty-directory ( name -- directory ) f swap { } H{ } clone directory boa ; : >up-directory ( key directory -- directory ) [ swap '[ name>> _ = ] reject ] change-subdirectories ; : add-subdirectory ( subdirectory directory -- directory ) swap '[ _ 1array append ] change-subdirectories ; : add-file ( size name directory -- directory ) [ [ pick set-at ] 2curry ] dip swap change-files ; : down-directory ( key directory -- directory ) subdirectories>> swap '[ name>> _ = ] find nip ; : cd-down ( key directory -- directory ) [ >up-directory ] [ dupd down-directory dup [ nip ] [ drop empty-directory ] if ] 2bi swap >>up ; : cd-up ( directory -- directory ) dup up>> [ f >>up ] dip add-subdirectory ; : root? ( directory -- bool ) up>> f = ; : cd-root ( directory -- directory ) [ dup root? not ] [ cd-up ] while ; : input ( -- array ) "/Users/zip/desktop/aoc2022/dec-7/input.txt" utf8 file-lines ; : handle-command ( string directory -- directory ) swap { { [ dup "$ cd /" = ] [ drop cd-root ] } { [ dup "$ cd .." = ] [ drop cd-up ] } { [ dup R/ ^\$ cd .*$/ matches? ] [ " " split last swap cd-down ] } { [ dup R/ ^\d+ .*$/ matches? ] [ " " split swap [ first2 [ string>number ] dip ] dip add-file ] } { [ ] [ ] } } cond ; : derive-tree ( string -- directory ) root empty-directory swap [ swap handle-command ] each cd-root ; : directory-size ( directory -- number ) [ subdirectories>> [ directory-size ] map-sum ] [ files>> values sum ] bi + ; : walk-tree ( directory quot: ( a -- a ) -- seq ) [ call ] [ [ subdirectories>> ] dip [ walk-tree ] curry map ] 2bi [ 1array ] dip append ; inline recursive : part1 ( -- number ) input derive-tree [ directory-size ] walk-tree flatten [ 100000 <= ] filter sum ; : total-free ( -- number ) 30000000 ; : total-space ( -- number ) 70000000 ; : needed-space ( number -- number ) total-free total-space - + ; : part2 ( -- number ) input derive-tree [ directory-size ] walk-tree unclip needed-space [ flatten natural-sort ] dip [ >= ] curry find nip ; MAIN: [ part1 . part2 . ]