1 divert(-1)dnl -*- m4 -*-
2 # Usage: m4 [-Dfile=day04.input] day04.m4
4 include(`common.m4')ifelse(common(04), `ok', `',
5 `errprint(`Missing common initialization
8 # First line is list, all remaining lines are 76 byte boards
9 define(`input', translit((include(defn(`file'))), `,()', ` '))
10 define(`offset', index(defn(`input'), nl))
11 define(`list', quote(translit(substr(defn(`input'), 0, offset), ` ', `,')))
12 define(`boards', translit(substr(defn(`input'), incr(offset)), nl, ` '))
13 define(`best', offset)define(`worst', `-1')
14 define(`setup', `_$0($*)')define(`_setup', `define(`m$2', `$1')')
15 define(`bingo', `eval(`($1 & ($1>>1) & ($1>>2) & ($1>>3) & ($1>>4) & 0x108421)
16 || ($1 & ($1>>5) & ($1>>10) & ($1>>15) & ($1>>20) & 0x1f)')')
17 define(`daub', `ifdef(`cur', `ifdef(`m$1', `+$1popdef(`m$1')')', `ifdef(`m$1',
18 `define(`set', eval(set | (1<<m$1)))popdef(`m$1')ifelse(bingo(set), 1,
19 `define(`cur', $1)')')define(`round', incr(round))')')
20 define(`score', `ifelse(eval($2 < best), 1, `define(`best', $2)define(`part1',
21 $1)')ifelse(eval($2 > worst), 1, `define(`worst', $2)define(`part2', $1)')')
23 forloop_var(`i', 0, 24, `setup(i, substr(`$1', eval(i*3), 3))')
24 define(`set', 0)define(`round', 0)popdef(`cur')
25 score(eval((foreach(`daub', list))*cur), round)
28 dnl shame that GNU m4 regex lacks .{76}
29 patsubst(defn(`boards'), translit(format(`%076d', 0), 0, .), `board(`\&')')
31 define(`half', `eval($1/76/2*76)')
32 define(`chew', `ifelse($1, 76, `board(`$2')', `$0(half($1),
33 substr(`$2', 0, half($1)))$0(eval($1-half($1)), substr(`$2', half($1)))')')
34 chew(len(defn(`boards')), defn(`boards'))