adventofcode2022/day23/sol.ivy

108 lines
2.3 KiB
XML

)get "input.ivy"
sample = 7 7 rho '....#..' '..###.#' '#...#.#' '.#...##' '#.###..' '##.#.##' '.#..#..'
#board = sample == '#'
board = input == '#'
#board
op show a = (text ".#23456789"[1+a]),"\n-"
op lift a = (1,rho a) rho a
op n moveNSWE a = (lift n flip a[1]), (lift (-n) flip a[2]), (lift n rot a[3]), (lift (-n) rot a[4])
op any a = or/,a
op maybePad1 a =
c1 = any a[1]
c2 = any a[(rho a)[1]]
c1 and c2: 0,a,0
c1: 0,a
c2: a,0
a
op maybePad a =
a = maybePad1 a
(any a[;1]) or (any a[;(rho a)[2]]): transp maybePad1 transp a
a
op smearWE a = a or (1 rot a) or (-1 rot a)
op smearNS a = a or (1 flip a) or (-1 flip a)
op look a =
ns = lift smearNS a
we = lift smearWE a
-1 moveNSWE (we, we, ns, ns)
op axis1 a = 3 1 2 transp a
op dup4 a = (4,rho a) rho a
# look in each direction
# an elf can move in a direction if there is no elf in said direction and there is an elf somewhere nearby
# returns a 4x(rho a) matrix
op canMove a =
C = look a
(not C) and dup4 (a and or/axis1 C)
# prepare moves
# assign each move a priority and take the max
# remove lower priority moves
op p prepare choices =
best = max/ p * axis1 choices # select best direction
p o.== best # decompose into 4x?x? matrix
# count how many elves want to move to each square
# filter out moves which conflict
op unblocked moves =
open = 1 == +/axis1 1 moveNSWE moves
moves and -1 moveNSWE dup4 open
priority = 4 3 2 1
M = 0
changed = 0
op M round a =
a = maybePad a
moves = unblocked (M flip priority) prepare canMove a
moved = or/axis1 moves
changed; changed = +/, moved
b = (a and not moved) + +/axis1 1 moveNSWE moves
b
op round a = M round a
# this is implemented using globals
# to store the board instead of recursion
# in order to avoid keeping a bunch of large
# intermediate values alive on the stack
B = 0
op i loop n =
i > n: i
changed; changed = 0
B = M round B
M = M - 1
changed == 0: i
(i+1) loop n
op n rounds a =
B; B = a
M; M = 0
1 loop n
B
op n numrounds a =
B; B = a
M; M = 0
1 loop n
op score a =
a = maybePad a
n = */ (rho a) - 2
n - +/, a
show board
#show round board
show 10 rounds board
score 10 rounds board
1000 numrounds board