USING: arrays combinators continuations grouping hash-sets io.encodings.utf8 io.files kernel math math.parser math.vectors multiline namespaces peg.ebnf prettyprint ranges sequences sets ; IN: aoc.14 : input ( -- lines ) "~/factor/aoc/14/test.in" utf8 file-lines ; EBNF: parse [=[ num = [0-9]+ => [[ dec> ]] coord = num ","~ num cave = (coord " -> "*~)+ => [[ 2 clump ]] ]=] SYMBOL: floor : I ( -- hashset ) input [ parse ] map concat [ concat [ second ] map supremum 2 + floor namespaces:set ] keep [ first2 [ [a..b] ] 2map first2 cartesian-product concat ] map concat >hash-set ; DEFER: dfs : search-neighbours ( hashset coord -- hashset ) [ { [ { 0 1 } v+ ] [ { -1 1 } v+ ] [ { 1 1 } v+ ] } cleave 3array [ dfs ] each ] keep over adjoin ; SYMBOL: fn : dfs ( hashset coord -- hashset ) fn get call( -- ) 2dup [ swap in? ] [ nip second floor get = ] 2bi or [ drop ] [ search-neighbours ] if ; : (part) ( quot -- n ) fn namespaces:set I [ dup clone { 500 0 } dfs ] [ ] recover [ cardinality ] bi@ swap - ; : part1 ( -- n ) [ [ second floor get = [ throw ] when ] keep ] (part) ; : part2 ( -- n ) [ ] (part) ; : solve ( -- ) part1 . part2 . ;