day 25 optimize and improve heuristics
[aoc_eblake.git] / 2018 / day24.m4
blob11efd300fa9a281cfecb9c98b17142ffc52a2428
1 divert(-1)dnl -*- m4 -*-
2 # Usage: m4 [-Dfile=day24.input] day24.m4
3 # Optionally use -Dverbose=1 to see some progress
4 # Optionally use -Dpriority=0|1|2|3|4|5 to choose priority queue algorithms
6 include(`common.m4')ifelse(common(24), `ok', `',
7 `errprint(`Missing common initialization
8 ')m4exit(1)')
10 define(`radiation', 1)define(`cold', 2)define(`fire', 4)
11 define(`bludgeoning', 8)define(`slashing', 16)
12 define(`ignore')define(`hit', `(')
13 define(`units', `ignore(')define(`with', `)')
14 define(`an', `ignore(')define(`does', `)')
15 define(`damage', `ignore(')define(`initiative', `)')
16 define(`input', translit((include(defn(`file'))), nl`( );,', `:<.>'))
17 define(`type', 1)define(`max', 0)
18 define(`bump', `ifelse(eval($1<$2), 1, `define(`$1', $2)')')
19 define(`map', `eval(0_$0$3)')
20 define(`_map', `ifelse(`$1', `', `', `ifelse(`$1', `weak', `define(`scale',
21   5)', `$1', `immune', `define(`scale', 0)', `$1', `to', `',
22   `|($1<<scale)')$0(shift($@))')')
23 define(`line', `ifelse(`$1', `Infection', `define(`type', 0)',
24   eval(len(`$1')>20), 1, `_$0(translit(`$1', `<.>', `(,)'))')')
25 define(`_line', `setup(type, $1, $3, map$4, $6, $7, $9)')
26 define(`setup', `bump(`max', $7)define(`type$7', $1)define(`def$7', 0)define(
27   `off$7', 0)define(`units$7', $2)define(`hp$7', $3)define(`mod$7',
28   $4)define(`atk$7', $5)define(`dam$7', $6)')
29 ifdef(`__gnu__', `
30   patsubst(defn(`input'), `\([^:]*\):', `line(`\1')')
31 ', `
32   define(`_chew', `line(substr(`$1', 0, index(`$1', `:')))define(`tail',
33     substr(`$1', incr(index(`$1', `:'))))ifelse(index(defn(`tail'), `:'), -1,
34     `', `$0(defn(`tail'))')')
35   define(`chew', `ifelse(eval(`$1 < 200'), 1, `_$0(`$2')', `$0(eval(`$1/2'),
36     substr(`$2', 0, eval(`$1/2')))$0(eval(len(defn(`tail'))` + $1 - $1/2'),
37     defn(`tail')substr(`$2', eval(`$1/2')))')')
38   chew(len(defn(`input')), defn(`input'))
41 include(`priority.m4')
43 define(`prep', `define(`Atk$2', eval(atk$2+$1*type$2))define(`eff$2',
44   eval(units$2*Atk$2))pushdef(`list'eval(1-type$2), $2)')
45 define(`reset', `undefine(`list0')undefine(`list1')forloop(1, 'max`,
46   `prep($1, ', `)')')
47 define(`push', `_$0($1, eff$1)')
48 define(`_push', `ifelse($2, 0, `',
49   `insert(eval(`100000000-$1-$2*'''max``), $1)')')
50 define(`damage', `_$0(eff$1, dam$1, mod$2)')
51 define(`_damage', `eval(`$1*!($2&$3)*(1+!!(($2<<5)&$3))')')
52 define(`try', `ifelse(eff$2, 0, `popdef(`list'type$1)', off$2, 0,
53   `_$0(damage($1, $2), bestd, $2, eff$2)')')
54 define(`_try', `ifelse(eval(`$1>$2||($1&&$1==$2&&$4>='beste`)'), 1,
55   `define(`bestd', $1)define(`bestu', $3)define(`beste', $4)')')
56 define(`select', `ifelse($1, `', `', `define(`bestu', 0)define(`bestd',
57   0)define(`beste', 0)_$0($2)$0(pop)')')
58 define(`_select', `_stack_foreach(`list'type$1, `try($1, ', `)', `t')pair($1,
59   bestu)')
60 define(`pair', `ifelse($2, 0, `', `define(`def$1', $2)define(`off$2', $1)')')
61 define(`attack', `forloop_rev('max`, 1, `_$0(', `)')')
62 define(`_attack', `kill($1, def$1)')
63 define(`kill', `ifelse($2, `0', `', `_$0($1, $2, eff$2, damage($1, $2),
64   hp$2, Atk$2)define(`def$1', 0)define(`off$2', 0)')')
65 define(`_kill', `ifelse(eval(`$4>=$5'), 1, `-define(`eff$2',
66   eval(`($3/$6>$4/$5)*($3/$6-$4/$5)*$6'))')')
67 define(`count', 0)
68 define(`round', `ifelse(forloop_arg(1, max, `push')select(pop)attack(), `', `',
69   `ifelse(eval(count%1000), 0, `output(1, `...boost $2, round $1')')define(
70   `count', incr(count))$0(incr($1), $2)')')
71 define(`tally', `+eff$1/Atk$1')
72 define(`battle', `reset($1)round(1, $1)ifelse(ifdef(`list1', $1, 0), 0,
73   `eval(forloop_arg(1, max, `tally'))', `$0(incr($1))')')
74 define(`part1', battle(0))
75 define(`part2', battle(1))
77 divert`'part1
78 part2