day 21 preliminary refactoring
[aoc_eblake.git] / 2023 / day18.m4
blob052bdeefed98bb0215ab1b7fc99b46cbda7201e3
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
6 ')m4exit(1)')
8 changecom
9 define(`input', translit(include(defn(`file')), nl`RDLUabcdef ()#',
10   `;0123ABCDEF.'))
11 changecom(`#', nl)
13 include(`math64.m4')
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', `.', `,'))')
46 ifdef(`__gnu__', `
47   patsubst(defn(`input'), `\([^;]*\);', `do(`\1')')
48 ', `
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)))
63 divert`'part1
64 part2