3

I'm trying to do leet puzzle https://leetcode.com/problems/max-area-of-island/, requiring labelling connected (by sides, not corners) components.

How can I transform something like

0 0 1 0 0
0 0 0 0 0
0 1 1 0 1
0 1 0 0 1
0 1 0 0 1

into

0 0 1 0 0
0 0 0 0 0
0 2 2 0 3
0 2 0 0 3
0 2 0 0 3

I've played with the stencil operator and also tried using scan operators but still not quite there. Can somebody help?

Adám
  • 6,573
  • 20
  • 37
mazin
  • 395
  • 2
  • 7
  • 1
    Hi, I did something similar for advent of code https://github.com/rak1507/Advent-Of-Code-APL/blob/main/2021/Day09.dyalog, maybe that can help? {(×⍵)×⍵⌈⊃⌈/0 shifts ⍵}⍣≡{(1+⍳+/,⍵)@⊢⍵} – rak1507 Dec 14 '21 at 12:39

1 Answers1

4

We can start off by enumerating the ones. We do the by applying the function (where, but since all are 1s, it is equivalent to 1,2,3,…) @ at the subset masked by the bits themselves, i.e. ⍸@⊢:

      ⍸@⊢m
0 0 1 0 0
0 0 0 0 0
0 2 3 0 4
0 5 0 0 6
0 7 0 0 8

Now we need to flood-fill the lowest number in each component. We do this with repeated application until the fix-point ⍣≡ of processing Moore neighbourhoods ⌺3 3. To get the von Neumann neighbours, we reshape the 9 elements in the Moore neighbourhood into a 4-row 2-column matrix with 4 2⍴ and use ⊢/ to select the right column. We remove any 0s with 0~⍨ them prepend , the original value ⍵[2;2] (even if 0) and have ⌊/ select the smallest value:

        {⌊/⍵[2;2],0~⍨⊢/4 2⍴⍵}⌺3 3⍣≡⍸@⊢m
0 0 1 0 0
0 0 0 0 0
0 2 2 0 4
0 2 0 0 4
0 2 0 0 4

We map the values to indices by finding their indices ⍳⍨ in the unique elements of ∘∪ 0 followed by , the ravelled matrix ,:

        (⊢⍳⍨∘∪0,,){⌊/⍵[2;2],0~⍨⊢/4 2⍴⍵}⌺3 3⍣≡⍸@⊢m
1 1 2 1 1
1 1 1 1 1
1 3 3 1 4
1 3 1 1 4
1 3 1 1 4

And decrement which adjusts back to begin with zero:

        ¯1+(⊢⍳⍨∘∪0,,){⌊/⍵[2;2],0~⍨⊢/4 2⍴⍵}⌺3 3⍣≡⍸@⊢m
0 0 1 0 0
0 0 0 0 0
0 2 2 0 3
0 2 0 0 3
0 2 0 0 3
Adám
  • 6,573
  • 20
  • 37
  • Nice. I've not seen `(⍳+/)@⊢m` before. It would be nice if you could briefly annotate also, what does `4 2⍴` do here, it looks like a clever trick, but it's not clear what – mazin Dec 14 '21 at 16:10
  • @AdamNathan I've inserted some explanations, although `(⍳+/)` was very silly of me on an all-one vector, so I've simplified that. – Adám Dec 16 '21 at 12:29
  • Thanks. Wouldn't it be simpler to use the max instead of filtering 0? – mazin Dec 16 '21 at 12:45
  • 1
    @AdamNathan You could use max instead of min, but you still have to prevent 0s from getting non-0 neighbours' values, so you'd have to multiply by the sign of the current value or something like that: `¯1+(∪⍤,⍳⊢){⍵[2;2](×⍤⊣×⌈/⍤,)⊢/4 2⍴⍵}⌺3 3⍣≡⍸@⊢m` – Adám Dec 16 '21 at 13:04
  • Reviewing this again, I noticed that it's a problem when the top left corner is *not* the background. How would you resolve this? Sorting `(∪⍤,⍳⊢)` seems a bit ugly. – mazin Jul 31 '22 at 07:30
  • 1
    Nicely spotted. Fixed. – Adám Jul 31 '22 at 07:38