USING: arrays hash-sets io.encodings.utf8 io.files kernel math math.order math.parser math.statistics math.vectors prettyprint sequences sets splitting ; IN: aoc.18 : input ( -- lines ) "~/factor/aoc/18/18.in" utf8 file-lines ; : I ( -- points ) input [ "," split [ dec> ] map ] map ; : neighbours ( point -- points ) { { 1 0 0 } { -1 0 0 } { 0 1 0 } { 0 -1 0 } { 0 0 1 } { 0 0 -1 } } [ v+ ] with map ; : count-sides ( points point -- n ) neighbours swap without length ; : air-tiles ( points -- n ) [ >hash-set ] keep [ count-sides ] with map-sum ; : part1 ( -- n ) I air-tiles ; DEFER: flood :: valid? ( points minmax point -- ? ) point [ minmax first2 between? ] all? not point points in? or ; : flood-neighbours ( points minmax point -- ) neighbours [ flood ] 2with each ; : add-point ( points minmax point -- ) nip swap adjoin ; : flood ( points minmax point -- ) 3dup valid? [ 3drop ] [ [ add-point ] 3keep flood-neighbours ] if ; : fill-outside ( seq -- seq ) [ >hash-set dup ] keep concat [ minmax 2array ] [ infimum dup dup 3array ] bi flood members ; : surface-area ( seq -- n ) concat range 1 + sq 6 * ; : part2 ( -- n ) I fill-outside [ air-tiles ] [ surface-area ] bi - part1 swap - ; : solve ( -- ) part1 . part2 . ;