day 24 optimize
[aoc_eblake.git] / 2018 / day15.m4
blob0d7a5c003b88aa9868936e85d427fad2e4e650c6
1 divert(-1)dnl -*- m4 -*-
2 # Usage: m4 [-Dhashsize=H] [-Dfile=day15.input] day15.m4
4 include(`common.m4')ifelse(common(15, 65537), `ok', `',
5 `errprint(`Missing common initialization
6 ')m4exit(1)')
8 define(`D', defn(`define'))define(`I', defn(`ifelse'))define(`F', defn(`ifdef'))
9 define(`P', defn(`popdef'))define(`H', defn(`pushdef'))define(`E', defn(`eval'))
10 define(`input', translit(include(defn(`file')), nl`#.', `_01'))
11 define(`x', 0)
12 define(`cnt', 1)define(`p0', `3')
13 define(`v_', `ifdef(`y', `', `define(`y', `$1')')')
14 define(`v0', `D(`x', incr(`$1'))')
15 define(`v1', `D(`g$1', 0)v0(`$1')')
16 define(`unit', `D(`U$1', ``$1',`$2',`$3'')D(`T$1', `$3')D(
17   `cnt', incr(`$1'))v1(`$2')')
18 define(`vE', `unit(cnt, `$1', 1)')
19 define(`vG', `unit(cnt, `$1', 0)')
20 ifdef(`__gnu__', `
21   patsubst(defn(`input'), `.', `v\&(x)')
22 ', `
23   define(`chew', `ifelse(`$1', `1', `v$2(x)', `$0(eval(`$1/2'), substr(
24     `$2', 0, eval(`$1/2')))$0(eval(`$1-$1/2'), substr(`$2', eval(`$1/2')))')')
25   chew(len(defn(`input')), defn(`input'))
27 define(`reset', `D(`c0',0)D(`c1',0)D(`l')forloop_arg(1,'dnl
28 `cnt-1,`_$0')P(`done')D(`stable',`-1')D(`p1',`$1')output(1,`...$1')')
29 define(`_reset', `$0_(U$1)')
30 define(`_reset_', `P(`d$1')H(`g$2',`$1')H(`t$2',$3)D(`u$1',`$1,$2,$3')D(`h$1',
31   `200')D(`c$3',incr(c$3))D(`l',defn(`l')`,$1')')
32 define(`lt', `E(`$2<$5')')
33 define(`sort', `I(`$2',,`,`$1'',`I(lt(u$1,u$2),1,`,$@',`,`$2'$0(`$1',
34   shift(shift($@)))')')')
35 define(`act', `I(`$2',,,done,,,`F(`d$2',,`I(defn(`c'E(1-T$2)),0,`D(`done')',
36   `move(u$2)attack(u$2)')')$0(shift($@))')')
37 define(`min', `I(E(`$1<$2'),1,`$1',`$2')')
38 define(`max', `I(E(`$1>$2'),1,`$1',`$2')')
39 define(`e0', 1)define(`e1', 0)
40 define(`by', `b$2(`$1',`$3',`$4')')
41 define(`prep', `ifdef(`g$1', `define(`b$1', `$'2)_$0($1, eval($1-''y``))_$0($1,
42   decr($1))_$0($1, incr($1))_$0($1, eval($1+''y``))')')
43 define(`_prep', `ifdef(`g$2', `define(`b$1', `$'1`($2,'defn(`b$1')`,$'3`)')')')
44 forloop_arg(y, x-y, `prep')
46 define(`near', `by(`_$0',$1,0,e$2)')
47 define(`_near', `I($2,1,1,t$1,$3,1,0)')
48 define(`queue', `by(`_$0',$1,,`$2,$3,$4')')
49 define(`_queue', `I(g$1,0,`F(`f$1',`I(f$1,`$3',`D(`s$1',min($4,s$1))')',`H(`f',
50   `$1')D(`f$1',`$3')D(`s$1',I(`$4',,`E($1-$5)',`$4'))H(`q$3',`$1')')')')
51 define(`move', `I(stable,1,`output(2, `stable, leaving unit $1 alone')',
52   near(`$2',`$3'),0,`queue($2,1,,`$2')_$0(`$1',`$2',fill(1,2,`$3'),`$3')',
53   `output(2, `unit $1 stays put')')')
54 define(`_move', `I(`$3',0,`output(2, `no move possible for unit $1')',
55   `$0_(`$1',`$2',E($2+$3),`$4')')')
56 define(`_move_', `P(`g$2')H(`g$3',`$1')D(`t$3',$4)P(`t$2')D(`u$1',`$1,$3,$4')D(
57   `stable',`-1')output(2, `move unit $1 from $2 to $3')')
58 define(`fill', `F(`q$1',`_$0(q$1,`$2',defn(`s'q$1),`$3')P(`q$1')$0($@)',`F(
59   `best',`defn(`s'best)clean(`$2')',`F(`q$2',`$0(`$2',incr(`$2'),`$3')',
60   `0clean(`$2')')')')')
61 define(`_fill', `I(near(`$1',`$4'),0,`queue($1,$2,$3)',`I(F(`best',
62   `E($1<best)',1),1,`D(`best',`$1')')')')
63 define(`clean', `F(`q$1',`P(`q$1')$0(`$1')',`F(`f',`P(`f'f)P(`s'f)P(`f')$0(
64   `$1')',`P(`best')')')')
66 define(`attack', `_$0(by(`pick',`$2',`0,201',$3),$3)D(`l',defn(`l')`,$1')')
67 define(`_attack', `I(`$1',`0',,E(`$2>'p$3),1,`D(`h$1',E(`$2-'p$3))output(2,
68   `attack 'defn(`u$1') to h$1)', `drop(u$1)')')
69 define(`pick', `F(`t$1',`_$0(g$1,`$2',`$3',`$4')',`$2,$3')')
70 define(`_pick', `I(E(h$1`<$3&&$4!='T$1),1,`$1,h$1',`$2,$3')')
71 define(`drop', `D(`d$1')P(`g$2')P(`t$2')D(`c$3',decr(c$3))output(2,
72   `kill unit 'defn(`u$1'))D(`stable',`-1')I($3,1,`F(`part1',`D(`done')')')')
74 define(`_round', `I(`$2',,`D(`l')',`sort($2$0(shift($@)))')')
75 define(`round', `output(2, `...$3:$1 'c1 c0)D(`stable', `$2')act(_$0(
76   l))I(done, `', `E($1*(0forloop_arg(1, decr(cnt), `gather')))',
77   `$0(incr(`$1'), min(incr(stable), 1), `$3')')')
78 define(`gather', `ifdef(`d$1', `', `_$0(u$1)')')
79 define(`_gather', `popdef(`g$2')popdef(`t$2')+h$1')
80 reset(3)
81 define(`start', max(4, eval(3*c0/c1)))define(`C1', c1)
82 define(`part1', round(0, -1, 3))
83 define(`Round', `reset(`$1')define(`part2', round(0, -1, `$1'))ifelse(c1, C1,
84   `', `$0(incr(`$1'))')')
85 Round(start)
87 divert`'part1
88 part2