2024 day 3 part 2
This commit is contained in:
parent
e1496aa25a
commit
ec3b438f40
82
2024/03.fs
82
2024/03.fs
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user