Commit 07e68e19 authored by Peter Fidelman's avatar Peter Fidelman
Browse files

Day 9

parent 097b4dee
......@@ -136,4 +136,21 @@ Finally, the data structures I am using are extremely simple:
...
00000000 -- binary representation of digit #9
... (10 bytes total)
```
\ No newline at end of file
```
# Day 9
## Part A
The trick here is the boundary behavior -- trying to read off the edge of the board should be treated exactly the same as reading a '9'.
2-D indexing is a huge pain in Forth, so I wanted a simpler way to track the board edges. Here's what I sound up doing.
- **For the left and right edges** - When reading input, pad each line with a leading '9'. The empty line at the end of input also counts as a "line" so the effect of this logic is to '9'-delimit the input lines and the first and last character of the board will both wind up as '9's too.
- **For the top and bottom edges** - Clamp out-of-range addresses to first or last character of board, which are now guaranteed to be 9's.
The result: x,y coordinates are now largely irrelevant and we can just traverse every square without worrying about boundary conditions.
The check of each square against its neighbors is very simple and there is probably a more elegant way of writing it, especially in Part B where significant code duplication creeps in.
## Part B
Same as above, but when I find a low point I kick off a recursive flood-fill there and track how many squares I filled (see `basinsize`). Once the basin size is known, I store it in the minimum index of a 3-long ascended-sorted array, and re-sort that array to ensure the least of these top-3 values winds up in the minimum index again ripe for replacement. At the end of traversal I multiply together the top three values to get the answer.
\ No newline at end of file
variable (padend) : padend ( a ) (padend) @ ;
variable stride
: 9! ( a -- a+1 ) 57 over c! 1+ ;
: line>> ( a -- a n ) 9! dup -1 1 >> accept ;
: stride! ( n -- n ) dup 1+ stride ! ;
: get-lines ( -- )
pad begin line>> dup if stride! + 0 else drop -1 then until (padend) ! ;
: clamp@ ( a -- c ) pad max padend min c@ ;
: <left ( a -- f a ) dup c@ over 1- clamp@ < swap ;
: <right ( a -- f a ) dup c@ over 1+ clamp@ < swap ;
: <above ( a -- f a ) dup c@ over stride @ - clamp@ < swap ;
: <below ( a -- f a ) dup c@ over stride @ + clamp@ < swap ;
: go ( -- ) get-lines
0 padend pad do i <left <right <above <below >r and and and
if r> c@ 47 - + else rdrop then
loop ." Answer:" . ;
variable (padend) : padend ( a ) (padend) @ ;
variable stride
: 9! ( a -- a+1 ) 57 over c! 1+ ;
: line>> ( a -- a n ) 9! dup -1 1 >> accept ;
: stride! ( n -- n ) dup 1+ stride ! ;
: get-lines ( -- )
pad begin line>> dup if stride! + 0 else drop -1 then until (padend) ! ;
: clamp ( a -- c ) pad max padend 1- min ;
: left ( a -- a' ) 1- clamp ;
: right ( a -- a' ) 1+ clamp ;
: above ( a -- a' ) stride @ - clamp ;
: below ( a -- a' ) stride @ + clamp ;
: <left ( a -- f a ) dup c@ over left c@ < swap ;
: <right ( a -- f a ) dup c@ over right c@ < swap ;
: <above ( a -- f a ) dup c@ over above c@ < swap ;
: <below ( a -- f a ) dup c@ over below c@ < swap ;
create top-sizes here 3 cells dup allot 0 fill
: pivot ( a -- ) >r r@ 2@ 2dup < if swap then r> 2! ;
: sort ( a -- ) dup cell+ pivot dup pivot cell+ pivot ;
variable basinsize
: basin ( a -- ) dup c@ 57 = if drop else
1 basinsize +!
dup 48 swap c! ( so we don't ascend two paths to the same place )
<left swap if dup left recurse then
<right swap if dup right recurse then
<above swap if dup above recurse then
<below swap if dup below recurse then
drop then ;
: do-basin ( a -- )
0 basinsize ! basin basinsize @ top-sizes @ >
if basinsize @ top-sizes ! top-sizes sort then ;
: go ( -- ) get-lines
padend pad do i <left <right <above <below >r and and and
if r> do-basin else rdrop then
loop top-sizes 2 cells + @ top-sizes 2@ * * ." Answer:" . ;
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment