day 24 optimize
[aoc_eblake.git] / 2023 / day16.m4
blobc1262f5f3310e85fdf1ae74f21f23b6919607c9f
1 divert(-1)dnl -*- m4 -*-
2 # Usage: m4 [-Dfile=day16.input] day16.m4
3 # Optionally use -Dverbose=1 to see some progress
5 include(`common.m4')ifelse(common(16), `ok', `',
6 `errprint(`Missing common initialization
7 ')m4exit(1)')
9 # Easier to map tiles to valid macro name components:
10 # \n./\|-
11 #  012345
13 define(`input', translit(include(defn(`file')), nl`./\|-', `012345'))
14 define(`x', 1)define(`y', 1)
15 define(`do', `ifelse(`$3', 0, `define(`maxx', $1)define(`x', 1)define(`y',
16   incr($2))', `define(`x', incr($1))define(`g$1_$2', $3)')')
18 ifdef(`__gnu__', `
19   patsubst(defn(`input'), `.', `do(x, y, \&)')
20 ',`
21   define(`chew', `ifelse($1, 1, `do(x, y, $2)', `$0(eval($1/2), substr(
22     `$2', 0, eval($1/2)))$0(eval($1-$1/2), substr(`$2', eval($1/2)))')')
23   chew(len(defn(`input')), defn(`input'))
26 define(`vr1', `visit(incr($1), $2, `r')')
27 define(`vu1', `visit($1, decr($2), `u')')
28 define(`vl1', `visit(decr($1), $2, `l')')
29 define(`vd1', `visit($1, incr($2), `d')')
31 define(`vr2', `visit($1, decr($2), `u')')
32 define(`vu2', `visit(incr($1), $2, `r')')
33 define(`vl2', `visit($1, incr($2), `d')')
34 define(`vd2', `visit(decr($1), $2, `l')')
36 define(`vr3', `visit($1, incr($2), `d')')
37 define(`vu3', `visit(decr($1), $2, `l')')
38 define(`vl3', `visit($1, decr($2), `u')')
39 define(`vd3', `visit(incr($1), $2, `r')')
41 define(`vr4', `ifelse(probe($1, $2), `', `visit($1, decr($2), `u')visit(
42   $1, incr($2), `d')')')
43 define(`vu4', `visit($1, decr($2), `u')')
44 define(`vl4', `ifelse(probe($1, $2), `', `visit($1, decr($2), `u')visit(
45   $1, incr($2), `d')')')
46 define(`vd4', `visit($1, incr($2), `d')')
48 define(`vr5', `visit(incr($1), $2, `r')')
49 define(`vu5', `ifelse(probe($1, $2), `', `visit(incr($1), $2, `r')visit(
50   decr($1), $2, `l')')')
51 define(`vl5', `visit(decr($1), $2, `l')')
52 define(`vd5', `ifelse(probe($1, $2), `', `visit(incr($1), $2, `r')visit(
53   decr($1), $2, `l')')')
55 forloop(1, decr(maxx), `define(`e'', ``_0_u')')
56 forloop(1, decr(y), `define(`e0_'', ``_l')')
57 forloop(1, decr(maxx), `define(`e'', ``_''y``_d')')
58 forloop(1, decr(y), `define(`e''maxx``_'', ``_r')')
60 define(`_visit', `ifdef(`e$1_$2', `', `.use(`$1_$2')')use(`$1_$2_$3')v$3$4($1,
61   $2)')
62 define(`visit', `ifdef(`e$1_$2_$3', `define(`s$1_$2')', `_$0($@, g$1_$2)')')
63 define(`track', `len(visit($@))clean()')
64 define(`startr', `decr($1),$2')
65 define(`startu', `$1,incr($2)')
66 define(`startl', `incr($1),$2')
67 define(`startd', `$1,decr($2)')
68 define(`_start', `ifdef(`s$1_$2', 0, `define(`hit', 0)eval(track($3, $4,
69   `$5') + core*hit)')')
70 define(`start', `_$0($0$3($1, $2), $@)')
72 # Any exit energized by a prior entrance cannot produce a higher
73 # score.  Additionally, I assume that part 1 visits more than half the
74 # grid, and the bulk of that visit occurs after the first splitter hit
75 # from the side.  Find the number of cells energized by that core, at
76 # which point, the rest of the problem (including part 1) consists of
77 # finding how many additional cells are energized on the way into the
78 # core, rather than having to trace the full path from each start.
80 define(`use', `define(`e$1')define(`c$1')')
81 define(`clean', `ifdef(`all', `popdef(defn(`all'))popdef(`all')$0()')')
82 pushdef(`_visit', `v$3$4($1, $2)')
83 define(`probe', `use(`$1_$2')popdef(`_visit')define(`$0')')
84 define(`core', incr(track(1, 1, `r')))
86 define(`use', `pushdef(`e$1')pushdef(`all', `e$1')')
87 define(`probe', `ifdef(`c$1_$2', `define(`hit', 1)-')')
88 define(`part1', start(1, 1, `r'))
90 define(`part2', part1)
91 define(`check', `ifelse(eval(part2 < $1), 1, `define(`part2', $1)')')
92 output(1, `d...')
93 forloop(1, decr(maxx), `check(start(', `, 1, `d'))')
94 output(1, `r...')
95 forloop(2, decr(y), `check(start(1, ', `, `r'))')
96 output(1, `u...')
97 forloop(1, decr(maxx), `check(start(', `, 'decr(y)`, `u'))')
98 output(1, `l...')
99 forloop(1, decr(y), `check(start('decr(maxx)`, ', `, `l'))')
101 divert`'part1
102 part2