day 25 optimize and improve heuristics
[aoc_eblake.git] / 2019 / day10.m4
blob6d7fb35472f2f760ef1a9cc4699794777a8d3f7b
1 divert(-1)dnl -*- m4 -*-
2 # Usage: m4 [-Dfile=day10.input] day10.m4
3 # Optionally use -Dverbose=1 to see more details
5 include(`common.m4')ifelse(common(10), `ok', `',
6 `errprint(`Missing common initialization
7 ')m4exit(1)')
9 define(`input', include(defn(`file')))
10 define(`rowlen', index(input, `
11 '))
12 ifelse(eval((rowlen + 1) * rowlen), len(input), `',
13   `errprint(`input not square
14 ')m4exit(1)')
15 define(`input', translit(input, `.#
16 ', `01'))
18 define(`p', `defn(`p'eval($2 * rowlen + $1))')
19 define(`split', `eval($1 % rowlen),eval($1 / rowlen)')
20 define(`setup', `define(`p$1', substr(input, $1, 1))')
21 forloop_arg(0, rowlen * rowlen - 1, `setup')
23 define(`check', `define(`count', 0)_$0(split($1), $1)ifelse(
24   eval(count > part1), 1, `define(`part1', count)define(`best', $1)')')
25 define(`_check', `ifelse(p($1, $2), 1, `define(`x', $1)define(`y',
26   $2)define(`from', $3)forloop_rev($3 - 1, 0, `check_one(', `)')forloop_arg(
27   $3 + 1, rowlen * rowlen - 1, `check_one')')')
28 define(`check_one', `ifelse(defn(`v$1'), from, `', `define(`dx',
29   eval($1 % rowlen - x))define(`dy', eval($1 / rowlen - y))_$0(split($1),
30   $1)act()')')
31 define(`_check_one', `ifelse(eval($1 >= 0 && $1 < rowlen && $2 >= 0 &&
32   $2 < rowlen), 1, `ifelse(p$3.defn(`hit'), 1., `define(`hit',
33   $3)')define(`v$3', from)$0(eval($1 + dx), eval($2 + dy),
34   eval($3 + dx + dy * rowlen))')')
36 define(`part1', 0)
37 define(`act', `ifdef(`hit', `define(`count', incr(count))popdef(`hit')')')
38 forloop_arg(0, rowlen * rowlen - 1, `check')
39 define(`reset', `undefine(`v$1')')
40 forloop_arg(0, rowlen * rowlen - 1, `reset')
42 define(`list')
43 define(`quote', `ifelse($#, `0', `', ``$*'')')
44 define(`sign', `eval((($1) > 0) - (($1) < 0))')
45 define(`cross', `eval(($1) * ($4) - ($2) * ($3))')
46 define(`cmp', `_$0(split($1), split($2))')
47 define(`_cmp', `ifelse(eval(($1 < x) != ($3 < x)), 1, `sign($3 - $1)',
48   eval(($1 == x) && ($3 == x)), 1, `sign($2 - $4)',
49   `sign(cross($3 - x, $4 - y, $1 - x, $2 - y))')')
50 define(`insert', `define(`list', quote(_$0($1, list)))')
51 define(`_insert', `ifelse($#, 2, `$1,', `ifelse(cmp($1, $2), 1,
52   `$2,$0($1, shift(shift($@)))', `$*')')')
53 define(`act', `ifdef(`hit', `insert(hit)popdef(`hit')')')
54 check(best)
55 ifdef(`__gnu__', `define(`pick', `pushdef(`t', `popdef(`t')$'`200')t($@)')',
56   `define(`pick', `_$0(200, $@)')define(`_pick', `ifelse($1, 1, `$2',
57   `$0(decr($1), shift(shift($@)))')')')
58 define(`part2', pick(list))
59 define(`part2', eval((part2 % rowlen) * 100 + part2 / rowlen))
61 divert`'part1()output(1, `' (at split(best)))
62 part2