day 25 optimize and improve heuristics
[aoc_eblake.git] / 2017 / day13.m4
blob1d0d40dd99f5ff5c8f8f817f069a55d4800fb6b4
1 divert(-1)dnl -*- m4 -*-
2 # Usage: m4 [-Dfile=day13.input] day13.m4
4 include(`common.m4')ifelse(common(13), `ok', `',
5 `errprint(`Missing common initialization
6 ')m4exit(1)')
8 define(`input', translit(include(defn(`file')), nl`:', `;'))
9 ifdef(`__gnu__', `
10   patsubst(defn(`input'), `\([^ ]*\) \([^ ]*\);', `pushdef(`list', `\1,\2')')
11 ',`
12   define(`setup', `pushdef(`list', `$1,$2')')
13   define(`chew', `setup(translit(substr(`$1', 0, index(`$1', `;')), ` ',
14     `,'))define(`tail', substr(`$1', incr(index(`$1', `;'))))ifelse(index(defn(
15     `tail'), `;'), -1, `', `$0(defn(`tail'))')')
16   define(`split', `ifelse(eval($1 < 12), 1, `chew(`$2')', `$0(eval($1/2),
17     substr(`$2', 0, eval($1/2)))$0(eval(len(defn(`tail')) + $1 - $1/2),
18     defn(`tail')substr(`$2', eval($1/2)))')')
19   split(len(defn(`input')), defn(`input'))
21 define(`part1', 0)
22 define(`visit', `_$0($1)')
23 define(`_visit', `ifelse(eval($1%(($2-1)*2)), 0, `define(`part1',
24   eval(part1 + $1*$2))')')
25 stack_foreach(`list', `visit')
27 define(`mods')
28 define(`sort', `ifelse($2, `', ``,$1'', `ifelse($1, $2, ``,'shift($@)',
29   eval(`$1 < $2'), 1, ``,$@'', ``,$2'$0(`$1', shift(shift($@)))')')')
30 define(`prep', `_$0($1, eval($2*2-2))')
31 define(`_prep', `define(`mods', quote(sort($2mods)))define(`neq$2',
32   defn(`neq$2')`,'eval((60*$2-$1)%$2))')
33 _stack_foreach(`list', `prep(first(', `))', `t')
34 define(`cmp', `eval((($1) > ($2)) - (($1) < ($2)))')
35 define(`gcd', `ifelse($2, 0, $1, `$0($2, eval(`$1 % $2'))')')
36 define(`lcm', `eval($1 / gcd($1, $2) * $2)')
37 define(`whiledef', `ifdef(`$1', `$2$1$3popdef(`$1')$0($@)')')
38 define(`l', 1)pushdef(`r1', 0)
39 define(`filter', `whiledef(`r'l, `_$0('l`, $1, ', `)'define(`l', lcm($1, l)))')
40 define(`_filter', `forloop(0, eval(l/$1-1), `try($2, eval($3+$1*', `))')')
41 define(`try', `ifelse(index(defn(`neq$1')`,', `,'eval(`$2%$1')`,'), -1,
42   `pushdef(`r'l, `$2')')')
43 foreach(`filter'mods)
44 define(`part2', defn(`r'l))
45 define(`min', `ifelse(eval(`$1 < 'part2), 1, `define(`part2', $1)')')
46 whiledef(`r'l, `min(', `)')
48 divert`'part1
49 part2