fn main [ const d2dx := [ 1, 0, -1, 0 ]; const d2dy := [ 0, 1, 0, -1 ]; var a := infinite(infinite(byte, 0)); var lines := list_break_to_lines(read_lazy(h[0])); var input := empty(tuple3(int, int, int)); for line in lines do [ var hex := line[list_search(line, '#') + 1 .. ]; var n := ston_base(hex[ .. 5], 16); var dx := d2dx[hex[5] - '0']; var dy := d2dy[hex[5] - '0']; input +<= mktuple3(dx, dy, n); ] var min_x, min_y := 0, 0; var max_x, max_y := 0, 0; var x_splits := treeset_init(int); var y_splits := treeset_init(int); var xp, yp := 0, 0; for t in input do [ xp += t.v1 * t.v3; yp += t.v2 * t.v3; min_x := min(min_x, xp); min_y := min(min_y, yp); max_x := max(max_x, xp); max_y := max(max_y, yp); x_splits := treeset_set(x_splits, xp); x_splits := treeset_set(x_splits, xp + 1); y_splits := treeset_set(y_splits, yp); y_splits := treeset_set(y_splits, yp + 1); ] fn x_to_idx(x : int) : int [ var a := treeset_prev(x_splits, x + 1); return a.j; ] fn x_next(x : int) : int [ x := x_to_idx(x); var a := treeset_next(x_splits, x); return a.j; ] fn y_to_idx(y : int) : int [ var a := treeset_prev(y_splits, y + 1); return a.j; ] fn y_next(y : int) : int [ var a := treeset_next(y_splits, y); return a.j; ] xp, yp := 0, 0; for t in input do [ var dx := t.v1; var dy := t.v2; var n := t.v3; var x_idx := x_to_idx(xp); var y_idx := y_to_idx(yp); again: a[y_idx - min_y][x_idx - min_x] := 1; if dx = 1 then [ var x_next := x_next(x_idx); if x_next < xp + dx * n then [ x_idx := x_next; goto again; ] ] else if dx = -1 then [ var x_next := x_to_idx(x_idx - 1); if x_next > xp + dx * n then [ x_idx := x_next; goto again; ] ] else if dy = 1 then [ var y_next := y_next(y_idx); if y_next < yp + dy * n then [ y_idx := y_next; goto again; ] ] else if dy = -1 then [ var y_next := y_to_idx(y_idx - 1); if y_next > yp + dy * n then [ y_idx := y_next; goto again; ] ] xp += dx * n; yp += dy * n; ] var pending := empty(tuple2(int, int)); for j in y_splits do [ if j > max_y then continue; pending +<= mktuple2(min_x, j); pending +<= mktuple2(max_x, j); ] for i in x_splits do [ if i > max_x then continue; pending +<= mktuple2(i, min_y); pending +<= mktuple2(i, max_y); ] while len_greater_than(pending, 0) do [ var p := pending[len(pending) - 1]; pending := pending[ .. len(pending) - 1]; if a[p.v2 - min_y][p.v1 - min_x] <> 0 then continue; a[p.v2 - min_y][p.v1 - min_x] := 2; for d := 0 to 4 do [ var cx, cy := p.v1, p.v2; var dx := d2dx[d]; var dy := d2dy[d]; if dx = 1 then [ if cx = max_x then continue; cx := x_next(cx); ] else if dx = -1 then [ if cx = min_x then continue; cx := x_to_idx(cx - 1); ] else if dy = 1 then [ if cy = max_y then continue; cy := y_next(cy); ] else if dy = -1 then [ if cy = min_y then continue; cy := y_to_idx(cy - 1); ] pending +<= mktuple2(cx, cy); ] ] var sum := 0; for i in x_splits do [ if i > max_x then continue; for j in y_splits do [ if j > max_y then continue; if a[j - min_y][i - min_x] <> 2 then [ var nx := x_next(i); var ny := y_next(j); sum += (nx - i) * (ny - j); ] ] ] write(h[1], ntos(sum) + nl); ]