2

Is there a simple idiom in (Dyalog) APL to surround a numeric array with zeros?

Currently for a numerical array NA of rank 1, or a vector I use

0,⍨0, NA

and for an array of rank 2 I use

0,[1]⍨0,[1]0,⍨0, NA

For higher ranks I could just repeat the pattern, but I'm sure there has to be a better way to do this (and with one definition for all ranks), but I just can't come up with one that doesn't seem overly complicated.

Probie
  • 1,371
  • 7
  • 15
  • is `NA` numeric? – ngn Jun 06 '18 at 00:57
  • It was for the use case I had in mind, but something which is more generic is probably more useful – Probie Jun 06 '18 at 01:07
  • if you don't state that explicitly in the question, I'll have to delete my answer - it's under fire for not supporting the general case – ngn Jun 06 '18 at 01:16
  • thanks­­­­­­­­­­­­­­­­­­­­­­ – ngn Jun 06 '18 at 01:57
  • Is `NA` simple? (If the first element is nested, @ngn's answer is won't work.) – Adám Jun 06 '18 at 05:43
  • In the case I had at the time it was simple, but an idiom that works on things that may not be simple is potentially of more use to me (and probably others) in the long run – Probie Jun 07 '18 at 17:14

5 Answers5

2

(¯2-⍴)↑(1+⍴)↑⊢­­­­­­­­­­­­­­­

ngn
  • 7,763
  • 6
  • 26
  • 35
  • It may well be that OP uses `0` as an example padding. Furthermore, OP does not specify what `NA` contains. Your solution only works on numeric arrays where the first element is a simple scalar number. It fails, e.g. [on character arrays](https://tio.run/##SyzI0U2pTMzJT///P@1R2wSNQ@uNdB/1btF81DZRw1AbynrUtQgorWCkYKxgAhR61DfVEQA "APL (Dyalog Unicode) – Try It Online") and [nested arrays](https://tio.run/##SyzI0U2pTMzJT///P@1R2wSNQ@uNdB/1btF81DZRw1AbynrUtQgorfCod7ORgrGCCQA "APL (Dyalog Unicode) – Try It Online"). And it cannot be customised to surround with anything but the prototypical element. – Adám Jun 05 '18 at 18:52
  • @Adám Surely 0 means 0 :) "NA" is suggestive of "numeric array". Yes, it's possible, though not very likely, that Probie meant something else. – ngn Jun 05 '18 at 19:37
  • 1
    **N**-dimensional **A**rray ;-) – Adám Jun 05 '18 at 19:48
  • 1
    As Adám has said, there's no need to make such assumptions. ;-) Also, while Probie most probably knows APL well enough, you may want to add an explanation of the code in case an APL beginner happens to read it (and to avoid automatic VLQ flags). – EKons Jun 05 '18 at 21:02
  • @ΈρικΚωνσταντόπουλος The OP has amended the question. I'd prefer to keep my answer concise, but feel free to edit your own explanation in if you think that helps, or flag it as VLQ you really consider my answer "very low quality" – ngn Jun 06 '18 at 01:56
1

This Dyalog APL version 16.0 solution (from here) handles any number of dimensions:

{⍵@(1+⍳⍴⍵)⊢0⍴⍨2+⍴⍵}

the array

@( placed at

1+ one plus

all the indices of

⍴⍵ the shape of the array

)⊢ in the array consisting of

0⍴⍨ zero reshaped to the shape

2+ two added to

⍴⍵ the shape of the array

In other words, we create an array entirely of 0s, which in every dimension is two elements larger than the array, then we place the array into that array (thus replacing the 0s in those positions) at an offset of one from the edges, i.e. in the center.

Try it online!

Alternative version that defines an at operator and can therefore be used pre-16.0.

Adám
  • 6,573
  • 20
  • 37
1
{r←≢⍴⍵ ⋄ i←1⌽⍳r ⋄ {0⍪0⍪⍨i⍉⍵}⍣r⊢⍵}

⍴⍵ the shape of the array
 the number of elements of that (i.e. array's rank)
r← store that as r (for rank)

⍳r the ɩndices of the rank
1⌽ rotate them one step
i← store in i (for indices)

⊢⍵ on the array
{}⍣r apply the following function r times (i.e. once per dimension):
i⍉⍵ reorder the axes of the argument according to i (i.e. put the next dimension in front)
0⍪⍨ append with 0s along the first axis
0⍪ prepend with 0s along the first axis

In other words, each axis gets its turn at being in front, where we prepend and append 0s.

Try it online!

Adám
  • 6,573
  • 20
  • 37
1

In response to your own answer; you can reduce instead of recursing:

{⊃{0,[⍺]⍵,[⍺]0}/(⍳≢⍴⍵),⊂⍵}

⊂⍵ enclose the array
(), prepend the following:
⍴⍵ the shape of the array
 the number of elements of that (i.e. array's rank)
⍳r the ɩndices of the rank
{}/ reduce (insert between the elements) using the following function:
⍵,[⍺]0 append 0s along the axis indicated by the left argument
0,[⍺]⍵ prepend 0s along the axis indicated by the left argument
 disclose (because the reduction reduces the rank from 1 to 0, so it has to enclose the result)

In other words, we prepend and append 0s along all each axis in turn.

Try it online!

Adám
  • 6,573
  • 20
  • 37
  • That's pretty cool, and was probably the answer I was looking for (although I'll probably accept either your `@` solution or ngn's use of the fill behaviour of `↑` since if someone searches for this question it seems like those are better solutions). I'm pretty new to APL, Are there any good exercises for thinking more like an APL programmer? My statically typed background means I'd never have thought of using reduce over an array with the last element as a different type. – Probie Jun 05 '18 at 18:38
  • 1
    @Probie Just notice my comment to ngn's solution. Freeing ones mind of other programming languages' influence happens gradually as you use APL. You may be interested in [the APL chat room](https://chat.stackexchange.com/rooms/52405), and the [lessons there](https://chat.stackexchange.com/rooms/info/52405?tab=conversations), especially [Lesson 27](https://chat.stackexchange.com/rooms/52405/conversation/lesson-27-lookup-without-replacement). – Adám Jun 05 '18 at 19:21
0

So, I've generalised my method to a recursive dfn which meets my "works for arbitrary rank" requirement, but I'm not happy with it because I still think there's a better way to do it that I'm just missing. I've put it as an answer, since it technically answers my question, but I'm still looking for better solutions.

{(⍴⍴⍵){⍺=0:⍵ ⋄ (⍺-1)∇0,[⍺]⍨0,[⍺]⍵}⍵}
Probie
  • 1,371
  • 7
  • 15