1 divert(-1)dnl -*- m4 -*-
2 # Usage: m4 [-Dfile=day18.input] day18.m4
4 include(`common.m4')ifelse(common(18), `ok', `',
5 `errprint(`Missing common initialization
9 define(`input', translit(include(defn(`file')), nl`RDLUabcdef ()#',
15 # https://en.wikipedia.org/wiki/Shoelace_formula is close for twice area;
16 # but we are digging 1x1 squares, not points. There is length/2 additional
17 # area oustside each line, and 1/4*(convex-concave) at corners.
18 # Assume corner at 0,0 is convex; but int division truncates if it's concave.
19 define(`area1', 0) define(`perim1', 0)
20 define(`corner1', 1) define(`x1', 0)
21 define(`y1', 0)define(`o1', `0')
22 define(`y2', 0)define(`o2', `0')
23 define(`corner2', 1) define(`x2', 0)
24 define(`area2', 0) define(`perim2', 0)
25 define(`visit', `define(`area$1',
26 add64(area$1, sub64(mul64($2, $5),
27 mul64($3, $4))))define(`perim$1',
28 eval(perim$1+$6))define(`corner$1',
29 eval(defn(`o'o$1`$7')+ corner$1))define(`x$1',
30 $4)define(`y$1',$5) define(`o$1', `$7')')
31 define(`o01', 1) define(`o12', 1)
32 define(`o23', 1) define(`o30', 1)
33 define(`o03', -1)define(`o32', -1)
34 define(`o21', -1)define(`o10', -1)
35 define(`do0', `visit( $1, $2, $3, eval(`$2
36 + $4'), $3, $4, `0')')define(`do1',
37 `visit($1, $2, $3, $2, eval(`$3 + $4'),
38 $4, `1')')define( `do2', `visit($1,
39 $2, $3, eval(`$2 - $4'), $3, $4, `2')')
40 define(`do3', `visit($1, $2, $3, $2,
41 eval(`$3 - $4'), $4, `3')')define(`_do',
42 `do$1(1, x1, y1, $2)first(`do'eval(
43 `0x$3%4'))(2, x2, y2, eval(`0x$3/16'))')
44 define(`do', `_$0(translit(`$1', `.', `,'))')
47 patsubst(defn(`input'), `\([^;]*\);', `do(`\1')')
49 define(`_chew', `do(substr(`$1', 0, index(`$1', `;')))define(
50 `tail', substr(`$1', incr(index(`$1', `;'))))ifelse(index(defn(`tail'),
51 `;'), -1, `', `$0(defn(`tail'))')')
52 define(`chew', `ifelse(eval($1 < 30), 1, `_$0(`$2')', `$0(eval($1/2),
53 substr(`$2', 0, eval($1/2)))$0(eval(len(defn(`tail')) + $1 - $1/2),
54 defn(`tail')substr(`$2', eval($1/2)))')')
55 chew(len(defn(`input')), defn(`input'))
58 define(`_half', `substr(`$1', 0, decr(len(`$1')))')
59 define(`half', `_$0(mul64(`$1', 5))')
60 define(`part1', eval(translit(area1, `-')/2 + perim1/2 + corner1/4))
61 define(`part2', add64(half(translit(area2, `-')), eval(perim2/2 + corner2/4)))