day 16 optimize
[aoc_eblake.git] / 2018 / day12.m4
blobeee9d1c6589ec0c99eabf7067ee9e2d483341f03
1 divert(-1)dnl -*- m4 -*-
2 # Usage: m4 [-Dfile=day12.input] day12.m4
4 include(`common.m4')ifelse(common(12), `ok', `',
5 `errprint(`Missing common initialization
6 ')m4exit(1)')
8 include(`math64.m4')
9 define(`input', translit(include(defn(`file')), nl`.# =>', `;01'))
10 define(`init', substr(defn(`input'), incr(index(defn(`input'), `:')),
11   eval(index(defn(`input'), `;;') - index(defn(`input'), `:') - 1)))
12 define(`list', substr(defn(`input'), incr(incr(index(defn(`input'), `;;')))))
13 define(`visit', `translit(`define(`rABCDE', `F')define(`REDCBA', `F')',
14   `ABCDEF', `$1')')
15 ifdef(`__gnu__', `
16   patsubst(defn(`init'), `.', `pushdef(`st0', `\&')')
17   patsubst(defn(`list'), `\([^;]*\);', `visit(`\1')')
18 ', `
19   define(`chew', `ifelse(`$1', `1', `pushdef(`st0', `$2')', `$0(eval(`$1/2'),
20     substr(`$2', 0, eval(`$1/2')))$0(eval(`$1-$1/2'), substr(`$2',
21     eval(`$1/2')))')')
22   chew(len(defn(`init')), defn(`init'))
23   define(`half', `eval($1/6/2*6)')
24   define(`chew', `ifelse(`$1', `6', `visit(`$2')', `$0(half(`$1'), substr(
25     `$2', 0, half(`$1')))$0(eval($1-half(`$1')), substr(`$2', half(`$1')))')')
26   chew(eval(len(defn(`list'))/7*6), translit(defn(`list'), `;'))
28 define(`offset', 0)
29 define(`prune', `ifelse($1, 0, `popdef(`$1')$2$0($@)')')
30 define(`rev', `_$0(0, 0, 0, 0, st0`'popdef(`st0'))prune(`st1',
31   `define(`offset', incr(offset))')')
32 define(`_rev', `pushdef(`st1', R$1$2$3$4$5)ifdef(`st0', `$0($2, $3, $4, $5,
33   st0`'popdef(`st0'))', `$0_($2, $3, $4, $5, 0)')')
34 define(`_rev_', `pushdef(`st1', R$1$2$3$4$5)pushdef(`st1',
35   R$2$3$4$5$5)pushdef(`st1', R$3$4$5$5$5)pushdef(`st1', R$4$5$5$5$5)define(
36   `offset', decr(decr(offset)))')
37 define(`fwd', `define(`sum', _$0(define(`offset', decr(decr(offset)))offset,
38   0, 0, 0, 0, 0, st1`'popdef(`st1')))prune(`st0')')
39 define(`_fwd', `pushdef(`st0', r$3$4$5$6$7)ifdef(`st1', `$0(incr($1),
40   eval($2+st0*$1), $4, $5, $6, $7, st1`'popdef(`st1'))', `$0_(incr($1),
41   eval($2+st0*$1), $4, $5, $6, $7, 0)')')
42 define(`_fwd_', `eval($2 + pushdef(`st0', r$3$4$5$6$7)st0*$1 +
43   pushdef(`st0', r$4$5$6$7$7)st0*($1+1) +
44   pushdef(`st0', r$5$6$7$7$7)st0*($1+2) +
45   pushdef(`st0', r$6$7$7$7$7)st0*($1+3))')
46 forloop_arg(0, 9, `rev()fwd')
47 define(`part1', sum)
48 define(`diff', 0)
49 define(`do', `define(`prev', sum)rev()fwd()ifelse(eval(sum - prev), diff,
50   `define(`part2', add64(mul64(add64(`50000000000', `-$1'), eval(diff/2)),
51   sum))', `define(`diff', eval(sum - prev))$0(incr(incr(`$1')))')')
52 do(22)
54 divert`'part1
55 part2