It's been a while since my first message last October. I was going to probably be writing more as I planned to do Advent of Code 2020 in Pure but decided to use C to destress with some nostalgia programming instead, and that's been great.
A conversation with coworkers, however, on how they solved Day 18 made me realize it would be neat to try and use Pure for a second time (the problem involves changing the precedence of arithmetic among + and * -- my colleague used JavaScript's .replace method of string objects).
Here's my Pure solution to the problem. Part one is to just have + and * have equal precedence but with left associativity. Part two is to have + bind tighter than *. If you have a few moments, could you please tell me how this could be better in a Pure idiomatic / style sense. Thanks!
using system, regex ;
leftFirst = reduce with a + b * c = (a + b) * c end ;
addFirst = reduce with
a * b + c = prod(a, b + c) ;
a + b * c = dorp(a + b, c) ;
prod(a, b) + c = prod(a, b + c) ;
a + dorp(b, c) = dorp(a + b, c) ;
dorp(a, b) = prod(a, b) ;
'prod(a, b) = prod(a, b) ;
prod(prod(a, b), c) = prod(a * b, c) ;
prod(a, prod(b, c)) = prod(a, b * c) ;
prod(a, b) = a * b ;
end ;
fixed f a = loop a (f a) with
loop b bb = b if same b bb ;
= loop bb (f bb) otherwise ;
end ;
quoted s = regsub (cst "'(") "(" 0 s 0 ; // can these two be done more idiomatically?
toLong s = regsub (\s -> s!1 + "L") "[[:digit:]][[:digit:]]*" 0 s 0 ;
let input = map val . filter ("" ~=) . split "\n" . toLong . quoted . fget $ fopen "input.raw" "r" ;
run r = init . str . foldl (+) 0L . map (fixed eval . r) $ input ;
printf "Part 1: %s\nPart 2: %s\n" (run leftFirst, run addFirst) ;