Commit 097b4dee authored by Peter Fidelman's avatar Peter Fidelman
Browse files

Day 8

parent e7a60632
......@@ -78,4 +78,62 @@ new[8] = old[0]
buffer "new" now describes fishes in step 1
```
The same code solved Part A and B of this problem, because my word size is 64 bits and that was enough to track the number of lanternfish after 256 days. For my puzzle input the answer took about 41 bits. Good thing too, because I really didn't want to implement an arbitrary-precision math library.
\ No newline at end of file
The same code solved Part A and B of this problem, because my word size is 64 bits and that was enough to track the number of lanternfish after 256 days. For my puzzle input the answer took about 41 bits. Good thing too, because I really didn't want to implement an arbitrary-precision math library.
# Day 7
# Day 8
## Part A
First throw away everything before the pipe character (`|`, ascii 124), then iterate through the remaining words and count how many of them have length 2, 3, 4 or 7. If a pipe character is not found in the line, this must be the end of the input so we end the program.
## Part B
Each digit has seven segments a through g. I'll pack these into the low
seven bits of a byte, where 1 means the segment is used and 0 means it is not.
```
gfedcba
00000000
```
Some digits can be recognized immediately from how many segments they use.
```
segments value
(2) ------> #1
(3) ------> #7
(4) ------> #4
(7) ------> #8
```
The remaining six digits will be ambiguous for now. I will throw them into a pool, then define a "find" operation that searches the pool and removes/returns the digit matching a given bitmask. To come up with these search terms, I will use binary combinations of the digits already known. As digits are found, they are removed from the pool of ambiguous digits so subsequent searches get easier.
Here is my algorithm:
```
#7 #4 or -----> find --> #9
#8 #1 xor ----> find --> #6
#8 #4 #1 xor -> find --> #0
#9 #6 and ----> find --> #5
#8 #4 xor ----> find --> #2
and the last digit is #3
```
Here is a diagram showing why it works:
![Some scribbles](advent-2021-08b.png)
Finally, the data structures I am using are extremely simple:
```
gfedcba ambiguous-digits pool
00000000
00000000
... (6 bytes total)
gfedcba known-digits
00000000 -- binary representation of digit #0
00000000 -- binary representation of digit #1
...
00000000 -- binary representation of digit #9
... (10 bytes total)
```
\ No newline at end of file
variable #easy 0 #easy !
: =? ( n -- ) >r swap r> = or ;
: is-easy ( n -- 0|1 ) dup 2dup 2 = 3 =? 4 =? 7 =? 1 and ;
: skip-to-pipe ( -- ?pipe-found ) 124 word count nip ;
: count-easy-words ( -- )
0 begin bl word count nip dup while is-easy + repeat drop ;
: line-counter ( -- ) skip-to-pipe dup if count-easy-words #easy +! then 0= ;
: >pad ( a n -- a ) tuck pad swap cmove pad + ;
: >>pad ( a -- a n ) dup -1 1 >> accept + pad - pad swap ;
: count-line ( -- ) s" line-counter " >pad >>pad evaluate ;
: go ( -- ) begin count-line until ." Answer:" #easy @ . ;
create ambiguous-digits 6 allot ambiguous-digits 6 0 fill
variable (acursor) 0 (acursor) !
: ambiguous-digit-cursor ( -- a )
(acursor) @ dup 5 = if 0 else dup 1+ then (acursor) ! ambiguous-digits + ;
: find-match ( c -- b ) 127 and
begin dup ambiguous-digit-cursor dup >r ( c c a ) c@ over and = ( c f )
if drop r> dup c@ swap 0 swap c! exit else rdrop then again ;
: last-match ( -- b )
begin ambiguous-digit-cursor c@ dup if exit else drop then again ;
create known-digits 10 allot known-digits 10 0 fill
: th-digit ( n -- b ) known-digits + c@ ;
: >th-digit ( b n -- ) known-digits + c! ;
: lookup-digit ( b -- n )
>r known-digits
begin dup c@ r@ = 0= while 1+ repeat rdrop known-digits - ;
: str>bin ( a n -- b )
0 -rot over + swap do 1 i c@ 32 invert and 65 - << or loop ;
: handle-known-digit ( b n )
dup 2 = if drop 1 >th-digit rdrop else
dup 3 = if drop 7 >th-digit rdrop else
dup 4 = if drop 4 >th-digit rdrop else
dup 7 = if drop 8 >th-digit rdrop else
then then then then ;
: handle-ambiguous-digit ( b n ) drop ambiguous-digit-cursor c! ;
: handle-digit ( a n -- )
dup >r str>bin r> ( b n )
handle-known-digit handle-ambiguous-digit ;
: infer-digits ( -- )
7 th-digit 4 th-digit or find-match 9 >th-digit
8 th-digit 1 th-digit xor find-match 6 >th-digit
8 th-digit 4 th-digit 1 th-digit xor xor
find-match 0 >th-digit
9 th-digit 6 th-digit and find-match 5 >th-digit
8 th-digit 4 th-digit xor find-match 2 >th-digit
last-match 3 >th-digit ;
: left-half ( -- ) 10 0 do bl word count handle-digit loop infer-digits ;
: eat-delimiter ( -- ) bl word drop ;
: right-half ( -- n )
0 4 0 do bl word count str>bin lookup-digit swap 10 * + loop ;
variable total-value
: process-line ( -- )
left-half eat-delimiter right-half total-value +! ;
: eval-or-done ( a n -- f )
tuck pad swap cmove pad + ( a' )
dup -1 1 >> accept ( a' n' )
dup if + pad - pad swap evaluate 0 else 2drop -1 then ;
: go ( -- )
0 total-value !
begin s" process-line " eval-or-done until ." Answer:" total-value @ . ;
\ No newline at end of file
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