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