So I have decided to follow Advent-of-Code live this year [I am 10 days behind so it’s hardly live, but I should catch up soon :) ]
Advent of Code is a programming themed fun-little-event that takes place every year on http://adventofcode.com
You can find my solutions (in (Dyalog-)APL) below.
Day 1
q1 ←{ +/ (1↓⍵) > (¯1↓⍵) }
q1pt1 ←{
q1 ⍎⍤1⊢↑ ⊃⎕NGET './q1.txt'1
}
q1pt2 ← {
x ← ⍎⍤1⊢↑ ⊃⎕NGET './q1.txt'1
q1 (2↓x) + (1↓¯1↓x) + (¯2↓x)
}
q1pt1_v2 ←{
+/2</ ⍎⍤1⊢↑ ⊃⎕NGET './q1.txt'1
}
q1pt2_v2 ← {
x ← ⍎⍤1⊢↑ ⊃⎕NGET './q1.txt'1
+/2</3+/x
}
I learned about N op /
a while after solving this for the 1st time.
It sure makes it simpler
Day 2
C ← 'forward' 'down' 'up'
M ← (1 0) (0 1) (0 ¯1)
d ← ⊃⎕NGET './q2.txt'1
q2←{
×/↑↑+/{M[C⍳⍵[1]]×(⍎⍤1⊢↑⍵[2])}¨' '(≠⊆⊢)¨d
}
q2pt2←{
f←{
h ← ⍵[1]
a ← ⍵[2]
d ← ⍵[3]
⍵ + ((⍺[1]) (⍺[2]) (a×⍺[1]))
}
⍝ appending (0 0 0) as the initial value of my accumulator for my reduce
x ← ⊖(↓↓0 0 0), {M[C⍳⍵[1]]×(⍎⍤1⊢↑⍵[2])}¨ ' '(≠⊆⊢)¨d_
×/ (1 0 1)/ ↑f/ ↑¨x
}
The reduce (/
) works right to left so I had to ⊖ it then swap ⍵ and ⍺
Day 3
C ← 'forward' 'down' 'up'
M ← (1 0) (0 1) (0 ¯1)
d ← ⊃⎕NGET './q2.txt'1
q2←{
×/↑↑+/{M[C⍳⍵[1]]×(⍎⍤1⊢↑⍵[2])}¨' '(≠⊆⊢)¨d
}
q2pt2←{
f←{
h ← ⍵[1]
a ← ⍵[2]
d ← ⍵[3]
⍵ + ((⍺[1]) (⍺[2]) (a×⍺[1]))
}
x ← ⊖(↓↓0 0 0), {M[C⍳⍵[1]]×(⍎⍤1⊢↑⍵[2])}¨ ' '(≠⊆⊢)¨d_
×/ (1 0 1)/ ↑{}/ ↑¨x
}
Day 4
n ←{ ⍎⍤1⊢↑⍵ }
nonempty ←{ ↑,/0≠⍴¨⍵ }
playcards ←{ n↑↑(nonempty⊆⊢)' '∘(≠⊆⊢)¨1↓⍵ }
d ← ⊃⎕nget'q4.txt'1
P ← n','(≠⊆⊢)⊃d ⍝ Pouch
C ← playcards d ⍝ Cards
WT ← {⍵⍳1}¨ ↓⍉↑ ↑∨/¨{∨/5∊¨⍵}¨¨{(+/[1]⍵) (+/[2]⍵)}¨∨\C∘=¨P ⍝ Winning Turns
score ←{ P(⊢⌷⊣)WT(⊢⌷⊣)⍵ × +/ (↑,/,/⍵⌷C) ~ (1+⍵⌷WT)↑P }
q4pt1 ← score WT⍳⌊/WT
q4pt2 ← score WT⍳⌈/WT
I liked how neat ∨\C∘=¨P
was to generate states of each bingo card across multiple turns. I am curious to see how I can use \
in other problems.
I got a better grasp of tacit programming this time around. I am not sure if Y(⊢⌷⊣)X
is the best way to do Y[X]
but at least I am able to create functions like it .
I do a lot of ↑
and ↓
, which also requires me to ¨
. I should figure out how to better handle boxes of values.
Day 5
valid_pt1 ← {(∆x ∆y)←|-/¨⍵ ⋄ (∆x=0)∨(∆y=0)}
valid_pt2 ← {(∆x ∆y)←|-/¨⍵ ⋄ (∆x=∆y)∨(∆x=0)∨(∆y=0)}
applyvent ← {{(⍵⌷M)+←1}¨⍵} ⍝ impure function. modifies M
range ← {d←⍵-⍺ ⋄ s←d÷|d ⋄ ⍺+s×⍳+1+|d} ⍝ 5 range 3 gives 5 4 3
d ← ⊃⎕nget'q5.txt'1
V ← {n¨','∘(≠⊆⊢)¨(1 0 1)/' '(≠⊆⊢)⍵}¨d
D ← 1+⌈/∊V
M ← D D⍴0 ⋄ valid ← valid_pt1 ⋄ applyvent¨0⌷{↑(↑,.(⊂,))/↑range/¨⍵}¨(↑valid¨⊆⊢){↓⍉↑⍵}¨V
q5pt1 ← +/∊M≥2
M ← D D⍴0 ⋄ valid ← valid_pt2 ⋄ applyvent¨0⌷{↑(↑,.(⊂,))/↑range/¨⍵}¨(↑valid¨⊆⊢){↓⍉↑⍵}¨V
q5pt2 ← +/∊M≥2
It was fun to solve this problem as I iterated over the map-view. I enjoy this style of interactive programming, doing as I’m seeing. It helps get rid of some hesitancy to approach even a seemingly difficult problem.
I ended relying on a mutable table to solve this and I wonder how I could have done it purely.
Day 6
f ← {s←⍵⋄((1↓s),0)+s[0]×(0 0 0 0 0 0 1 0 1)}
genS ← {x←⍵ ⋄ {+/x=⍵}¨⍳8+1}
d ← ⊃⎕nget'q6.txt'1
N ← n','(≠⊆⊢)d
q6pt1 ← 20⍕ +/↑(⊢f)/(⍳80),↓genS N
q6pt2 ← 20⍕ +/↑(⊢f)/(⍳256),↓genS N
Thinking of this problem as arrays of values helped me coming up with a solution.
The first solution I came up relied on keeping a record of each fish (as an integer) and resulted in memory overflow for part-2.
Day 7
d ← ⊃⎕nget'q7.txt'1
N ← n','(≠⊆⊢)⊃d
K ← 1+⌈/∊N
q7pt1 ← ⌊/+/ |(⍉↑K⍴¨N)-(0⌷¨⍳K(≢N))
g ← {0.5×⍵×⍵+1}
q7pt2 ← ⌊/+/g|(⍉↑K⍴¨N)-(0⌷¨⍳K(≢N))
Another problem that was represented by a table rather neatly. If I write about APL this could be the problem I solve.
Day 8
A ← 'abcdefg'
MK ← {(∊∘⍵)¨A}
MK_v2 ← A∊
Mb ← ↑MK ¨ ('abcfeg' 'cf' 'acdeg' 'acdfg' 'bcdf' 'abdfg' 'abdefg' 'acf' 'abcdefg' 'abcdfg')
l ← {{((~'|'∊⊢)¨⍵)⊆⍵}' '∘(≠⊆⊢)⍵}
loner ← {x←⍵ ⋄ {⍵/x}1={+/x=⍵}¨x}
len ← {∊(⍺=≢¨⍵)⊆⍵} ⍝ selects items with given length
decode ←{
b←⍺∊⍵
1(⊢⍳⊣)b∘(⊢≡⊣)¨↓Mb
}
solve ← {
x←⍵
S_1←2 len x
S_4←4 len x
S_7←3 len x
S_8←7 len x
S_a←S_7~S_1
S_g←⊃1 len{⍵~S_a,S_4}¨x
S_e←⊃∊{⍵~S_g,S_a,S_4}¨x
S_b←loner 1 len{⍵~S_7,S_e,S_g}¨x
S_d←S_8~S_7,S_b,S_e,S_g
S_c←loner 1 len{⍵~S_a,S_g,S_e,S_b,S_d}¨x
S_f←⊃∊{⍵~S_a,S_c,S_g,S_e,S_b,S_d}¨x
∊(S_a S_b S_c S_d S_e S_f S_g)
}
d ← ⊃⎕nget'q8.txt'1
q8pt2 ← +/{R←solve↑0⌷l ⍵ ⋄ ⊖{⍺+10×⍵}/⊖R∘decode¨↑1⌷l ⍵}¨d
OK, this one actually took me a while. Once I was able to decode S_g
the rest came smoothly.
I want to be able to come up with tacit versions of len
and loner
, but not yet :)
Day 9
x←↑n¨¨⊃⎕NGET'q9.txt' 1
d←⍴x
q9_pt1 ← +/{o←4⌷⍵ ⋄ (o+1)×0=+/o>(0 1 0 1 0 1 0 1 0)/⍵}¨∊¨sx
connlabel←{{{⍵[1;0]=0:0 ⋄ ⌊/0~⍨,⍵}¨(⊂⊢)⌺3 1⊢{⍵[0;1]=0:0 ⋄ ⌊/0~⍨,⍵}¨(⊂⊢)⌺1 3⊢⍵}(⍣≡)1+∘⍸@⊢⍵}
m2←connlabel x<9
pt2←×/3↑(⊂∘⍒⌷⊢){+/∊m2=⍵}¨0~⍨∪∊m2
I insisted on coming up with an array-based solution to connected-component labeling. It took me a while but I discovered ⍣≡
in the process. I used to write recursive functions that I ran repeatedly until the system stabilized. Well, this does it all by itself.
Also ⌺
would have been very handy in all the 2d filters I have been doing over matrixes.
Day 10
B ← '>' '}' ']' ')' ' ' '(' '[' '{' '<'
Cost_b_1 ← 25137 1197 57 3 0 1 2 3 4
Cost_b_2 ← 25137 1197 57 3 0 0 0 0 0
Cost_b ← Cost_b_1
c←{Cost_b[B⍳⍵] }
cost←{
x ← c⊃(⍵∊'>}])')/⍵
x>0:0
{⍺+⍵×5}/⊖0,⊖c¨⍵
}
f_i←{{(⍵,0)∨(0,⍵)}2=(1↓⍺[1]=⍵)+(¯1↓⍺[0]=⍵)}
f_rm←{∊(⊢⊆∘⍵)↑~∨/(⊢f_i∘⍵)¨'()' '{}' '[]' '<>'}
f_rms←{
w_←f_rm ⍵
(⍴w_)=(⍴⍵):w_
f_rms w_
}
q10← {{⍵[0.5×(⍴⍵)-1]}{(⊂⍋⍵)⌷⍵}∊0(≠⊆⊢)cost¨f_rms¨d}
⍝ pt1
Cost_b ← Cost_b_1
q10 0
⍝ pt2
Cost_b ← Cost_b_2
q10 0
Day 11
step←{
x0←↑⍵[1]
d←⍴x0
flash←{
⍝⎕←DISPLAY ⍺ ⍵
x←⍵
F←⍺
F_new←F-⍨x>9
0=+/∊F_new:F x
0=+/{(⍵⌷x)+←1}¨N_diag¨(,F_new)/(,⍳d):F x
(F∨F_new)∇(x)
}
l r←↑¨(d⍴0)flash 1+x0
(+/⍵[0],∊l)({9<⍵:0 ⋄ ⍵}¨r)
}
x←↑n¨¨⊃⎕NGET'q11.txt'1
pt1←0⌷⊃step/⊖(⊂0 x),⍳100
pt2←1+{⍵⍳1}99<|2-/⊃¨{⊃step/⊖(⊂0 x),⍳⍵}¨⍳1000
The scan operator goes through the same elements every time, without using the accumulated data. There should be a more performant version of it that doesn’t have O(N!) complexity.
Day 12
A_lower←819⌶⎕A
d←⊃⎕NGET'q12.txt' 1
L←'-'∘(≠⊆⊢)¨d
C←∪↑,/L
C_once←{⍵/C}{⍵∊A_lower}¨⊃¨C
D←⊃↑⍴C
M←D D⍴0⍴D*2
{(⍵⌷M)←1}¨{⍵⍳1}¨¨{(,⍵)∘≡¨C}¨¨,¨¨L ⍝ marks M with 1s
iCity←{1(⊢⍳⊣)(,⍵)∘≡¨C}
f←{
c←⍺
Open←⍵
next←Open∩{⍵/C}(iCity↑c)⌷(M∨⍉M)
c≡'end':1
0=(⍴next):0
Open_←Open~C_once∩(↓,c)
∊{⍵ f Open_}¨next
}
pt1←+/ 'start'f(C~↓,'start')
f2←{
fin←{⍵}
c←↑⍺[0]
path←⍺[1]
Closed←⍵
C_open←{⍵~↓'start'}{⍵/C}(Closed<(2-+/Closed>1))
next←C_open ∩ {⍵/C}(iCity↑c)⌷(M∨⍉M)
c≡'end':(fin 1)
0=(⍴next):0
+/∊{n←↓,⍵ ⋄ (⍵(∊path,'-',⍵)) f2 (Closed+(C∊n)×n∊C_once)}¨next
}
pt2←('start' 'start') f2 ((⍴C)⍴0)
the old travelling salesman problem with additional constraints.
Day 13
p←{'.#'[⍵]}¨ ⍝ plot for binary matrix
{a←⍺[0] ⋄ b←⍺[1]>⍳a⌷⍴⍵ ⋄ (b⌿[a]⍵)((0,¯1↓~b)⌿[a]⍵)} ⍝ cuts ⍵ at ⍺ to 2
⍝ where ⍺[0] is axis
⍝ where ⍺[1] is position at axis
f←{
pt1 pt2←⍺ cut ⍵
pt2_←⍺{⍺[0]=0:⊖⍵ ⋄ ⌽⍵}pt2 ⍝ flip horizontally or vertically
sBigger←∊⌈/⍴¨pt1 pt2_
⊃∨/{⊖⌽sBigger↑⌽⊖⍵}¨⊢pt1 pt2_ ⍝ pad (in top and left) to match the bigger of the two
}
dat←⊃⎕NGET'proj/apl/q13.txt'1
P←⊖¨n¨,','(≠⊆⊢)¨↑','∘((∊¨)⊆⊢)dat ⍝ points as (i j) tuples
d←∊1+⌈/P ⍝ dimensions
F←(('yx'∘⍳∊)@0)¨(n@1)¨'='(≠⊆⊢)¨↑2∘⌷¨' '(≠⊆⊢)¨1↓,↑','∘((~∊¨)⊆⊢)dat ⍝ folds (as t
M←(1@P)d⍴0 ⍝ the initial matrix
pt1←q13pt1←+/∊(⊃F) f M
pt2←p↑f/⌽(⊂M),F
I added documentation the APL way, as a second column. Looks neat doesn’t it :)
Day 14
fn←{
turns←⍵
dat←⊃⎕NGET'proj/apl/q14.txt' 1
p0←2,/⊃dat ⍝ initial pairs
Ma←{a b c←⍵ ⋄ (a b)(a c)(c b)}¨(∊(1 0 1)∘/)¨' '(≠⊆⊢)¨2↓dat ⍝ all movez
Mk←⊃¨Ma ⍝ keys of moves
Punq←∪↑,/Ma,⊂p0 ⍝ all pairs, uniq
M←↑(+/(¯1 1 1)∘×)¨(Punq∊⊂)¨¨Ma ⍝ ∆state of moves
Ps←{↑(Mk∊⊂⍵)/M}¨Punq ⍝ ∆state of pairs
s0←⊃+/(Punq∊⊂)¨p0 ⍝ initial state
sf←↑{⍵+∊+/Ps×⍵}/⌽(⊂s0),⍳turns ⍝ final state
⎕←⊢A←∪∊Punq ⍝ all letters available
⎕←⊢scr←⌈2÷⍨(+/sf∘×)¨(+/¨Punq∘=)¨A ⍝ scores
(⌈/-⌊/)scr
}
pt1←fn 10
pt2←fn 40
I had to optimize the solution for pt2 again, keeping counts instead of data. The solution didn’t work at first, though. I thought there could be an error due to the ⌈
operation, and manually subtracted 1 from the result.
Day 15
solv←{
M←⍵
d←⍴M
O←(1@(⊂0 0))d⍴0
V←d⍴0
C←d⍴0
g←⊂d-1
H←+/¨|g-⍳d
f←{
⍝ V visited
⍝ O open/available
⍝ H heuristics (cost to 'g'oal)
⍝ C costs (cost to start)
o←⍸(O∧0=V)
0=≢o:1 ⍝ no more open slots. finish
x←o⌷⍨{⍵⍳⌊/⍵}C[o]+H[o] ⍝ take the least cost pos
x≡g:1
V[x]←1
n←{(~0∘∊¨⍵≥0)/⍵}{(~0∘∊¨⍵<⊂d)/⍵}(0 ¯1)(¯1 0)(0 1)(1 0)+x ⍝ neighbours
c←C[x]
C[n]←{⍵⌷O:(⍵⌷C)⌊c+⍵⌷M ⋄ c+⍵⌷M}¨n ⍝ update costs to neighbours
O[n]←1 ⍝ make available
0
}
{f 0:C[g] ⋄ ∇ 0} 0
}
pt1←{
M←↑n¨¨⊃⎕NGET'tmp.txt' 1
solv M
}
pt2←{
M←↑n¨¨⊃⎕NGET'tmp.txt' 1
S←⊖⌽10 9↑⌽⊖↑{⍵⌽1+⍳9}¨∪,+/¨⍳5 5
solv⍪/(⊃,/)¨↓{S∘(⌷⍨)¨⍵∘(,⍨)¨M}¨+/¨⍳5 5
}
Day 16, 17
I didn’t do as good a bookkeeping for questions beyond this point. The interface I am using (Ride) was crashing at an increased frequency, perhaps due to the amount of data. I actually gave up on solving some of the questions after a few of those crashes.
Day 18
mag←{
⍝⎕←↑⍵
x←⍵
n d←x
2>≢n:⊃n
i j←0 2+(⊢⍳⌈/)d
l←1⌷⍴↑x
a←↑i↑¨x
c←↑j↓¨x
m←+/3 2×⌷∘n¨(i(i+1))
n←1-⍨i⌷d
∇↓(a,(2 1⍴m n),c)
}
itr←{
s x←(9 4)<⌈/¨⍵
x:∇ xpl ⍵
s:∇ spl ⍵
⍝⎕←↑⍵
⍵
}
add←{0 1+↓⊃,/↑¨⍺ ⍵}
par←{
x←⍵
b←↑x∘=¨'[],'
n←⍎¨(~∨⌿b)⊆x
d←⊃¨(~∨⌿b)⊆(-⌿+\2↑b)
n d
}
mag⊃⊢y←(itr add⍨)/⌽par¨⊃⎕NGET'proj/apl/q18.txt' 1
Day 19
'pmat' 'det'⎕CY'dfns'
RA←{⍵/⍨1=det¨⍵},(↓pmat 3)∘.{⍵@(⍺,¨⍳3)⊢3 3⍴0},1-2×⍳2 2 2
dat←getdata ⍬
D←≢dat
snsA←(∘.⊣)⍨dat
⍝ find matching sensors
matches←(∘.{cmn←⊃∩/∊¨⍺ ⍵ ⋄ 12=+⌿⍺∊cmn})⍨{(∘.far)⍨↓⍵}¨dat
snsM←↑¨(⍴snsA)⍴↑(,matches),.{⊂⍺/↓⍵}(,snsA)
fnd←(,⍨⍴dat)⍴⊃(,snsM),.(⊂relpos)(,⍉snsM)
⍝ found matches. fnd[i;j] ≡ r x y z,
⍝ `r` is ∆rot of "j" wrt "i"
⍝ `x y z` is ∆pos of "j" wrt "i"
fndr←⊃¨fnd ⍝ found rotations
fndp←(1∘↓)¨fnd ⍝ found positions
I←⍸25>fndr ⍝ indexes of matches in "fnd"
⍝{(⍵⌷xp)←⊂0 0 0 ⋄ (⍵⌷xr)←0}¨{(=/¨⍵)/⍵},⍳D D
open←(≢∪∊I)⍴0
imap←(⊃¨I){⊂(1∘⌷¨⍵)}⌸I
myi←(≢imap)⍴10+≢imap
0{myi[⍺]<⍵:⍵ ⋄ myi[⍺]←⍵ ⋄ ⍵>30:⍵ ⋄ ∇/(⊃imap[⍺]),⍵+1}0
Icand←⊃,/(((⊃¨I){⊂⍵}⌸I)@myi)27⍴9999
Idup←{i j←⍵ ⋄ open[i]←1 ⋄ open[j]}¨Icand
I_←(~Idup)/Icand
0≡≢∊~/∊¨I I_ ⍝ ensure nothing missing
P R←fill I_ ⍝ absolute positions and rotations
part1←≢∪⊃⍪/{↑(⊃P[⍵])∘+¨R[⍵]∘roti¨↓⊃dat[⍵]}¨⍳D
part2←{⌈/∊P(∘.{+/⍺-⍵})P}
Day 20
m x0←readdata ⍬
pad←{k←⍺ ⋄ r c←(2 0)+⍴⍵ ⋄ (r⍴k){⍺,⍵,⍺}(c⍴k){⍺⍪⍵⍪⍺}⍵}
⊢part1←+/∊({s←⊃⍵ ⋄ a←⊃1⌷⍵ ⋄ (m⌷⍨2⊥9⍴s),⊂({m⌷⍨2⊥∊{(s 0 1)[⍵]}¨⍵}⌺3 3)1+s pad a}⍣2)(0,(⊂x0))
⊢part2←+/∊({s←⊃⍵ ⋄ a←⊃1⌷⍵ ⋄ (m⌷⍨2⊥9⍴s),⊂({m⌷⍨2⊥∊{(s 0 1)[⍵]}¨⍵}⌺3 3)1+s pad a}⍣50)(0,(⊂x0))
Day 21
part1←{
⍝ both 'pad' and '⌺' uses 0 as fill-character
⍝ so I used 1 2 in place of 0 1 in the img matrix
n←0
scr←0 0
pos←1-⍨4 1
{i nr←⍵ ⋄ ⌈/scr≥1000:⍵ ⋄ nr_ ∆x←r nr ⋄ pos[i]←10|∆x+i⌷pos ⋄ scr[i]+←1+pos[i] ⋄ ∇(2|i+1)nr_}(0 0)
(⌊/scr)×n×3
}
part2←{
initpos←4 8
N←21+10+1
I←⍳N N
IW←⍸¨⊂[1 2]21<(0 1)∘.⌷I ⍝ win indexes
p←↓(initpos-1)(∘.=)⍳10 ⋄ s←(1@(⊂0 0))N N⍴0 ⋄ wins←0 0 ⋄ f 0
(⊂p)(⊂s)
}
Day 22
todo
Day 23
todo
Day 24
K←⎕.v>
s0←'w0' 'x0' 'y0' 'z0'
doop←{ ⍝ do op at left to state at right
k←⊃⍺
v←1↓⍺
k=INP:v inp ⍵
k=ADD:v add ⍵
k=MUL:v mul ⍵
k=DIV:v div ⍵
k=EQL:v eql ⍵
k=MOD:v mod ⍵
⎕←'unknown op: ',k
⍵ ⍝noop
}
pt1←{doop/(⌽⊃,/8↑digiops),⊂s0}
pt2←{inpi←0 ⋄ ↑{⊃doop/(⌽⊃,/⍵⌷digiops),⊂'w0' 'x0' 'y0' 'z0'}¨⍳14}
⍝ the above didn't actually help solve the problem, but they explained the state of it.
P←(12 1 1) (13 1 9) (12 1 11) (¯13 26 6) (11 1 6) (15 1 13) (¯14 26 13) (12 1 5) (¯8 26 7) (14 1 2) (¯9 26 10) (¯11 26 14) (¯6 26 7) (¯5 26 1)
itr←{
i z←⍵
a b c←i⊃P
d←i⊃⍺
k←d≠a+26|z
0≠b∧k:1
k=0:(i+1)z÷b
(i+1)c+d+26×z÷b
}
soln←{{0=⊃(⊖⍵)(itr⍣14)0 0:⍵ ⋄ ∇ dc ⍵}14⍴9}
neither did this solve the problem, but it became more eligible that we are manipulating a number as if it’s a stack of integers that are <26.
I ended up solving it afterwards with pen and paper.
Day 25
K←⎕.v>
plt←{K∘(⌷⍨)¨⍵}
upd←{(mvS FF)(mvE FF)⍵}
mvS←{
n _ s _ c←⍵[I]
(c s)≡S O:O
(n c)≡S O:S
c
}
mvE←{
_ e _ w c←⍵[I]
(c e)≡E O:O
(w c)≡E O:E
c
}
pt1←{
K←'⋄.v>'
F O S E←⍳4
I←(0 1)(1 2)(2 1)(1 0)(1 1) ⍝ neighbour indexes
plt←{K∘(⌷⍨)¨⍵}
X←dat←↑K∘⍳¨⊃⎕NGET'tmp.txt' 1
⍝⎕←plt¨{(upd⍣⍵)X}¨⍳⍵
1↓({x n←⍵ ⋄ x_←(upd⊃⍵) ⋄ x_(n+1)}⍣{(⊃⍺)≡(⊃⍵)})(X 0)
}