advent/2024/03.fs

62 lines
2.4 KiB
Forth

create data 20000 allot \ create a 20K buffer
variable fileid \ create a variable `fileid`
s" data/03.txt" r/o open-file \ open data file
drop \ drop the top value from the stack, it's just a status code and we aren't going to bother handling errors
fileid ! \ save the file id to the variable
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 the first `u2` bytes off the beginning of the string at `addr u`
tuck \ duplicate `u2` and store it "under" the length of the string
- \ subtract `u2` from the length of the string
-rot \ stick the new string length underneath the start pointer
+ \ increment the start pointer by `u2`
swap \ put them back in the right order
;
require regexp.fs
: mul-instr ( addr u -- flag )
(( =" mul(" \( {++ \d ++} \) ` , \( {++ \d ++} \) ` ) )) ;
: get-product ( addr u -- u2 )
mul-instr \ match the string from `addr u` against the above regex
if \ if the regex matches, then:
\1 s>number drop \ convert the first capture from string to number, drop the status code (we already know it will succeed)
\2 s>number drop \ convert the second capture from string to number, drop the status code
* \ multiply, and leave the answer on the stack
else
0 \ otherwise, leave 0 on the stack
then
;
variable result
0 result !
: sum-mul-instrs ( addr u -- u2 )
begin \ start looping
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
2dup \ duplicate address and remaining length of string
get-product \ pass those to get-product above
result @ + \ load `result` and add to product
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 .
bye