)get "input.ivy" sample = 7 7 rho '....#..' '..###.#' '#...#.#' '.#...##' '#.###..' '##.#.##' '.#..#..' #board = sample == '#' board = input == '#' #board op north a = 1 flip a op south a = -1 flip a op west a = 1 rot a op east a = -1 rot a #north 3 3 rho iota 9 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 a coalesce b = a: a b op any a = or/,a op pad a = 0,(transp (0,(transp a),0)),0 op needsPad a = (any 0 != a[1,(rho a)[1]]) or (any 0 != a[;(1,(rho a)[2])]) op maybePad a = needsPad a: pad a 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 (west a) or (east a) op smearNS a = a or (north a) or (south a) op show a = (text ".#23456789"[1+a]),"\n-" M = 0 op axis1 a = 3 1 2 transp a op look a = ns = lift smearNS a we = lift smearWE a -1 moveNSWE (we, we, ns, ns) 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 round board show 10 rounds board score 10 rounds board 1000 numrounds board #numrounds board