day 14 finish
[aoc_eblake.git] / 2021 / day22.m4
blobc6624806e58f1abe36bf9f21afe5245d36cd78bf
1 divert(-1)dnl -*- m4 -*-
2 # Usage: m4 [-Dfile=day22.input] day22.m4
3 # Optionally use -Dverbose=1 to see some progress
5 include(`common.m4')ifelse(common(22), `ok', `',
6 `errprint(`Missing common initialization
7 ')m4exit(1)')
9 include(`math64.m4')
11 define(`count', 0)
12 define(`bump', `define(`ia$1', $2)define(`ix$1', `$3,$4')define(`iy$1',
13   `$5,$6')define(`iz$1', `$7,$8')define(`count', incr($1))')
14 define(`inst', `ifelse(eval(len($2$3$4$5$6$7) <= 18), 1, `define(`mark',
15   count)')bump(count, $@)')
16 define(`Off', `inst(0, $1, incr($3), $4, incr($6), $7, incr($9))')
17 define(`On', `inst(1, $1, incr($3), $4, incr($6), $7, incr($9))')
18 translit((include(defn(`file'))), `o .'nl`xyz=', `O(,)')
20 define(`progress', 0)
21 define(`push', `ifelse(eval(progress % 1000), 0, `output(1,
22   `...'progress)')define(`progress', incr(progress))ifelse(`$1', `t',
23   `_$0(defn(`listt'),', `pushdef(')`list$1', `$2,$3,$4,$5,$6,$7,$8')')
24 define(`_push', `ifelse(`$1', `-$3', `popdef(`$2')', `-$1', `$3',
25   `popdef(`$2')', `pushdef(`$2', `$3')')')
26 define(`min', `ifelse(eval($1 < $2), 1, $1, $2)')
27 define(`max', `ifelse(eval($1 > $2), 1, $1, $2)')
28 define(`range', `max($1, $3), min($2, $4)')
29 define(`intersect', `_$0($1, $3, range(ix$2, $4, $5), range(iy$2, $6, $7),
30   range(iz$2, $8, $9))')
31 define(`_intersect', `ifelse(eval($4>$3 && $6>$5 && $8>$7), 1,
32   `push(`t', eval(-1*$2), $3, $4, $5, $6, $7, $8, $1)')')
33 define(`touch', `eval(_$0(ix$1, ix$2) && _$0(iy$1, iy$2) && _$0(iz$1, iz$2))')
34 define(`_touch', `($4>=$1 && $3<=$2)')
35 define(`visit', `ifelse($1, 0, `', `forloop(0, decr($1), `_$0(',
36   `, $1)')')ifelse(ia$1, 1, `push($1, 1, ix$1, iy$1, iz$1)')')
37 define(`_visit', `ifelse(touch($1, $2), 1, `_stack_foreach(`list$1',
38   `intersect($1, $2, first(', `))', `t')stack_reverse(`listt', `list$1')')')
39 define(`tally', `ifdef(`list$2', `$0(add64($1, _$0(list$2()popdef(
40   `list$2'), $2)), $2, $3)', `ifelse($2, $3, `$1', `$0($1, incr($2), $3)')')')
41 define(`_tally', `mul64(eval($1 *($3 - $2)), mul64(eval($5 - $4),
42   eval($7 - $6)))')
44 # Assume all part1 values come first in the input file, up to the marked line
45 forloop_arg(0, mark, `visit')
46 define(`part1', tally(0, 0, mark))
47 output(1, `...part 1 done')
48 ifelse(mark, count, `', `forloop_arg(incr(mark), decr(count), `visit')')
49 output(1, `...tallying part 2')
50 define(`part2', tally(part1, mark, count))
52 divert`'part1
53 part2