1 divert(-1)dnl -*- m4 -*-
2 # Usage: m4 [-Dstart=A,B | -Dfile=day21.input] day21.m4
4 include(`common.m4')ifelse(common(21), `ok', `',
5 `errprint(`Missing common initialization
8 define(`parse', `define(`start', `$4,$9')')
9 ifdef(`start', , `parse(shift(translit(include(defn(`file')), nl` ', `,,')))')
12 define(`max', `ifelse(lt64($1, $2), 1, $2, $1)')
13 define(`init', `define(`pos1', $1)define(`pos2', $2)')
14 define(`next', `eval(($1+($2)-1)%10+1)')
16 # each player advances by (3*(6*(turn-1)+(3*player-1))%10) per turn
17 # player 1 advances in sequence 6,4,2,0,8... same as 8*(turn+1)%10
18 # player 2 advances in sequence 5,3,1,9,7...
19 # after 10 turns, both players are back in starting position
20 define(`score1', 0)define(`score2', 0)define(`check')init(start)
21 define(`move', `_$0($1, score$1, next(pos$1, ((8*($2+1)+1-$1)%10)))')
22 define(`_move', `define(`score$1', eval($2+$3))define(`pos$1', $3)')
23 define(`round', `move(1, $1)check(1, 2, $1)move(2, $1)check(2, 1, $1)')
24 forloop_arg(1, 10, `round')
25 define(`skip', `_$0(eval(999/max(score1, score2)))')
26 define(`_skip', `define(`score1', eval(score1*$1))define(`score2',
27 eval(score2*$1))forloop_arg($1`'1, incr($1)0, `round')')
28 pushdef(`check', `ifelse(len(score$1), 4, `popdef(`check')define(`part1',
29 eval((6*($3-1)+3*$1)*score$2))')')skip()
31 # Cache by pos1,score1,pos2,score2=>win2,win1
32 define(`vadd', `add64($1,$3),add64($2,$4)')
33 define(`vmul', `mul64($1,$2),mul64($1,$3)')
34 define(`use', `_$0($2, next($1, $3))')
35 define(`_use', `$2, eval($1+$2)')
36 forloop(21, 30, `define(`v'', `)')
37 define(`count', `ifdef(`v$4', `0,1', `ifdef(`c$1_$2_$3_$4', `', `_$0($@,
38 move($@))')c$1_$2_$3_$4`'')')
39 define(`_count', `define(`c$1_$2_$3_$4', `$6,$5')')
40 define(`move', `vadd(vadd(count($3,$4, use($1,$2,3)), count($3,$4,
41 use($1,$2,9))), vadd(vmul(3, vadd(count($3,$4, use($1,$2,4)), count($3,$4,
42 use($1,$2,8)))), vadd(vmul(6, vadd(count($3,$4, use($1,$2,5)), count($3,$4,
43 use($1,$2,7)))), vmul(7, count($3,$4, use($1,$2,6))))))')
45 define(`part2', max(count(pos1, 0, pos2, 0)))
48 dnl golfed version of part 1, requires GNU m4, 195 bytes
49 define(D,defn(define))D(p,d($5,0,2,0,$10))D(n,E($3+3)s(E(($1+3*$3-1)%10+1)$2))p(translit(include(f),`
50 ' ,`,,')D(s,E($1+$2)$1)D(d,`ifelse(len($4),4,E(($3-2)*$2)`d($5,$4,n($@))')')D(E,`eval($@),'))