2024 day 3 part 2

This commit is contained in:
Joseph Montanaro 2024-12-06 20:39:16 -05:00
parent e1496aa25a
commit ec3b438f40

View File

@ -1,16 +1,11 @@
create data 20000 allot \ create a 20K buffer : load-data ( addr1 u1 -- addr2 u2 )
variable fileid \ create a variable `fileid` 20000 allocate drop \ allocate a 20k buffer, drop the status code
s" data/03.txt" r/o open-file \ open data file dup 2swap \ duplicate the buffer addr and stick both copies under the addr/length of filename
drop \ drop the top value from the stack, it's just a status code and we aren't going to bother handling errors r/o open-file drop \ open file, drop the status code
fileid ! \ save the file id to the variable 20000 swap \ stick the number of bytes to be read in between the buffer addr and file id
read-file drop \ read the file, drop the status code
;
variable data-len
data 20000 fileid @ read-file
drop
data-len !
: data-str ( -- addr u )
data data-len @ ;
: chop-prefix ( addr u u2 -- addr2 u2 ) : chop-prefix ( addr u u2 -- addr2 u2 )
\ chop the first `u2` bytes off the beginning of the string at `addr u` \ chop the first `u2` bytes off the beginning of the string at `addr u`
@ -21,9 +16,11 @@ data-len !
swap \ put them back in the right order swap \ put them back in the right order
; ;
require regexp.fs require regexp.fs
: mul-instr ( addr u -- flag ) : mul-instr ( addr u -- flag )
\ match a string of the form `mul(x,y)` where x and y are integers and capture those integers
(( =" mul(" \( {++ \d ++} \) ` , \( {++ \d ++} \) ` ) )) ; (( =" mul(" \( {++ \d ++} \) ` , \( {++ \d ++} \) ` ) )) ;
@ -38,24 +35,53 @@ require regexp.fs
then then
; ;
variable result
variable result \ initialize `result` with 0
0 result ! 0 result !
: sum-mul-instrs ( addr u -- u2 ) variable enabled
begin \ start looping -1 enabled ! \ idiomatically -1 is "true" (really anything other than 0 is true)
s" mul(" search \ search for the string "mul("
if \ if successful, top 2 values on stack will be start address of "mul(" and remainder of original string : handle-mul ( addr u -- )
2dup \ duplicate address and remaining length of string
get-product \ pass those to get-product above get-product \ pass those to get-product above
result @ + \ load `result` and add to product result @ + \ load `result` and add to product
result ! \ store this new value back in `result` result ! \ store this new value back in `result`
4 chop-prefix \ bump the start of the string by 4 characters
else \ if not successful, we have finished scanning through the string
2drop \ dump the string address and length
result @ exit \ put the result on top of the stack and return to caller
then
again
; ;
data-str sum-mul-instrs . : sum-mul-instrs ( addr u -- u2 )
\ we want to loop from addr to (addr + u - 8), because 8 is the min length of a valid mul(x,y) instruction
\ we also want to have addr + u on the top of the stack when we enter the loop,
\ so that we can use that to compute the remaining length of the string from our current address
over + \ copy addr to top of stack and add to length
dup 8 - \ duplicate, then subtract 8 from the top value
rot \ move original addr to top of stack
( stack at this point: [ addr + u, addr + u - 8, addr ] )
( i.e. [ end-of-string, loop-limit, loop-start ] )
do \ start looping
I 4 s" do()" str= \ compare the length-4 substring starting at I to the string "do()"
if \ if valid do() instruction,
-1 enabled ! \ set enabled=true
then
I 7 s" don't()" str= \ compare length-7 substring to "don't()"
if \ if valid don't() instruction,
0 enabled ! \ set enabled=false
then
I 4 s" mul(" str= \ compare length-4 substring to "mul("
enabled @ and \ combine with current value of `enabled`
if \ if a candidate for `mul(x,y)` instruction, and enabled=true, then
dup I - \ subtract current string pointer from end-of-string pointer to get length of remaining string
I swap handle-mul \ put current pointer onto stack again, swap so stack is ( addr len), and handle
then
loop
drop \ get rid of end-of-string pointer
result @ \ return value of result
;
s" data/03.txt" load-data
sum-mul-instrs .
bye bye