do w/o a loop? (presumably an each question)
do w/o a loop? (presumably an each question)
stuck on this abstraction of a bigger problem:
a←4 2 ⍴⍳8
b←3 2⍴1 1 1 2 2 3
i want to generate a×[2]b[i;] where i loops thru the rows of b.
this works: ↑, ⍉(↓a)∘.×↓b
but i gotta believe there's a better way than using split and an outer product. i just haven't been able to figure it out. any help? thanks
a←4 2 ⍴⍳8
b←3 2⍴1 1 1 2 2 3
i want to generate a×[2]b[i;] where i loops thru the rows of b.
this works: ↑, ⍉(↓a)∘.×↓b
but i gotta believe there's a better way than using split and an outer product. i just haven't been able to figure it out. any help? thanks
Last edited by drothman on Thu Jun 18, 2020 1:07 pm, edited 1 time in total.
- StefanoLanzavecchia
- Posts: 113
- Joined: Fri Oct 03, 2008 9:37 am
Re: do w/o a loop? (presumably an each question)
Code: Select all
⎕IO←1
,[1 2]a×[2]⍤99 ¯1⊢b
I believe this does the same and unless there are major optimisations in the interpreter it's likely to have the same performance as your version if it's not slower.
As an aside, if ⎕IO needs to die, then the only possibility is to keep it at 1 unless people volunteer to rewrite and test a few millions of lines of code.
Re: do w/o a loop? (presumably an each question)
↑,b,.×⍉aBut ravel is redundant with a single axis as the axis spec combines a number of axes as one or adds new axes if fractional.
0 1
2 3
4 5
6 7
0 2
2 6
4 10
6 14
0 3
4 9
8 15
12 21
- StefanoLanzavecchia
- Posts: 113
- Joined: Fri Oct 03, 2008 9:37 am
Re: do w/o a loop? (presumably an each question)
thanks to each of you.
Stefano, would u mind walking me through your solution?
Phil, that's more inline with what i was going for.
again, thanks guys
Stefano, would u mind walking me through your solution?
Phil, that's more inline with what i was going for.
again, thanks guys
- StefanoLanzavecchia
- Posts: 113
- Joined: Fri Oct 03, 2008 9:37 am
Re: do w/o a loop? (presumably an each question)
The rank operator is a way to change the way functions (be they primitives or user defined) see their arguments. By specifying rank 99 (-1) you are telling the executor that the left argument should be passed in its entirety whereas the right argument should be passed line by line. So times with axis 2 (x[2]) sees the whole of "a" as its left argument and one line of "b" at a time as its right argument.
If you want, it's a "modern" (v14 onward for Dyalog APL, 30 years for Sharp APL) way to write (⊂a)×[2]¨↓b (which I assume is what you implied in your subject line with "each question"). The rank operator, though, does not nest its results, which get flattened much like a "mix" would do. So the only thing left to do at the end is to ravel together the first two dimensions of the rank 3 array.
Code: Select all
⍴a {⎕←'⍺'⍺'⍵'⍵⋄ ⍺×[2]⍵}⍤ 99 ¯1⊢b
⍺ 1 2 ⍵ 1 1
3 4
5 6
7 8
⍺ 1 2 ⍵ 1 2
3 4
5 6
7 8
⍺ 1 2 ⍵ 2 3
3 4
5 6
7 8
3 4 2
If you want, it's a "modern" (v14 onward for Dyalog APL, 30 years for Sharp APL) way to write (⊂a)×[2]¨↓b (which I assume is what you implied in your subject line with "each question"). The rank operator, though, does not nest its results, which get flattened much like a "mix" would do. So the only thing left to do at the end is to ravel together the first two dimensions of the rank 3 array.
Re: do w/o a loop? (presumably an each question)
thanks. got it. yes,
1. (⊂a)×[2]¨↓b was what i had in mind, but i kept trying to make (↓a)×[2]¨↓b because i'm an apl-1 guy at heart (and haven't coded much in the past few years which is the last time i worked thru some of the apl2 stuff).
2. "The same can be achieved using ⊢ e.g. f⍤1⊢Y because ⍤ binds tighter to its right operand than ⊢ does to its left argument, and ⊢ therefore resolves to Identity." Now noted.
3. "If an item k of B is zero or positive it selects k-cells of the corresponding argument. If it is negative, it selects (r+k)-cells where r is the rank of the corresponding argument. A value of ¯1 selects major cells. " Now noted
good stuff...thanks for the detail.
1. (⊂a)×[2]¨↓b was what i had in mind, but i kept trying to make (↓a)×[2]¨↓b because i'm an apl-1 guy at heart (and haven't coded much in the past few years which is the last time i worked thru some of the apl2 stuff).
2. "The same can be achieved using ⊢ e.g. f⍤1⊢Y because ⍤ binds tighter to its right operand than ⊢ does to its left argument, and ⊢ therefore resolves to Identity." Now noted.
3. "If an item k of B is zero or positive it selects k-cells of the corresponding argument. If it is negative, it selects (r+k)-cells where r is the rank of the corresponding argument. A value of ¯1 selects major cells. " Now noted
good stuff...thanks for the detail.
- Adam|Dyalog
- Posts: 143
- Joined: Thu Jun 25, 2015 1:13 pm
Re: do w/o a loop? (presumably an each question)
While you already have two working solutions, I'd like to make a slight modification to Stefano's code:
This one is ⎕IO-independent and avoids one usage of the bracket axis.
It is worth pointing out that, while elegant, Phil's code still uses nested arrays, and so suffers in speed. Let's scale things a bit:
,[⍳2]a×⍤1⍤99 ¯1⊢b
1 2
3 4
5 6
7 8
1 4
3 8
5 12
7 16
2 6
6 12
10 18
14 24
This one is ⎕IO-independent and avoids one usage of the bracket axis.
It is worth pointing out that, while elegant, Phil's code still uses nested arrays, and so suffers in speed. Let's scale things a bit:
:For f :In 1 3 10
a←(4 2×f)⍴⍳8×f
b←(3 2×f)⍴(/⍨∘⌽⍨⍳3×f)
'Factor:',f
cmpx '↑,⍉(↓a)∘.×↓b' '↑,b,.×⍉a' ',[1 2]a×[2]⍤99 ¯1⊢b' ',[⍳2]a×⍤1⍤99 ¯1⊢b'
:EndFor
Factor: 1
↑,⍉(↓a)∘.×↓b → 2.1E¯6 | 0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
↑,b,.×⍉a → 4.3E¯6 | +110% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
,[1 2]a×[2]⍤99 ¯1⊢b → 1.6E¯6 | -25% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
,[⍳2]a×⍤1⍤99 ¯1⊢b → 1.7E¯6 | -19% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
Factor: 3
↑,⍉(↓a)∘.×↓b → 1.3E¯5 | 0% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
↑,b,.×⍉a → 5.4E¯5 | +311% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
,[1 2]a×[2]⍤99 ¯1⊢b → 3.8E¯6 | -72% ⎕⎕⎕
,[⍳2]a×⍤1⍤99 ¯1⊢b → 4.1E¯6 | -69% ⎕⎕⎕
Factor: 10
↑,⍉(↓a)∘.×↓b → 1.7E¯4 | 0% ⎕⎕⎕
↑,b,.×⍉a → 2.4E¯3 | +1268% ⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕⎕
,[1 2]a×[2]⍤99 ¯1⊢b → 2.3E¯5 | -87%
,[⍳2]a×⍤1⍤99 ¯1⊢b → 2.4E¯5 | -87%
-
- Posts: 238
- Joined: Thu Jul 28, 2011 10:53 am
Re: do w/o a loop? (presumably an each question)
There is another equivalent expression:
This may not seem like an improvement, but had ⍪⌿ been defined differently in Dyalog APL the last expression can be
The ISO Standard for Extended APL ISO/IEC 13751:2001(E) §9.2.1 specifies two different and incompatible definitions for reduction (AKA insert):Enclose-Reduction-Style (what Dyalog APL and APL2 have) versus Insert-Reduction-Style (Iverson). With the latter, in f⌿⍵, the function operand f is inserted between the major cells of the argument ⍵, and makes for terser expressions in generating subgroups and permutations [Hui and Kromberg 2020, §3.2 and §11.3] as well as inner product reduction (in repeated squaring), etc.
The nested versus boxed array differences between APL2 and the Iverson APLs are well-publicized. IMO, Enclose-Reduction-Style versus Insert-Reduction-Style deserve at least as much attention.
,[⍳2]a×⍤1⍤99 ¯1⊢b
⊃ ⍪⌿ ⊂⍤¯1 ⊢a×⍤1⍤99 ¯1⊢b
This may not seem like an improvement, but had ⍪⌿ been defined differently in Dyalog APL the last expression can be
,[⍳2]a×⍤1⍤99 ¯1⊢b
⊃ ⍪⌿ ⊂⍤¯1 ⊢a×⍤1⍤99 ¯1⊢b
⍪⌿ a×⍤1⍤99 ¯1 ⊢b
The ISO Standard for Extended APL ISO/IEC 13751:2001(E) §9.2.1 specifies two different and incompatible definitions for reduction (AKA insert):Enclose-Reduction-Style (what Dyalog APL and APL2 have) versus Insert-Reduction-Style (Iverson). With the latter, in f⌿⍵, the function operand f is inserted between the major cells of the argument ⍵, and makes for terser expressions in generating subgroups and permutations [Hui and Kromberg 2020, §3.2 and §11.3] as well as inner product reduction (in repeated squaring), etc.
The nested versus boxed array differences between APL2 and the Iverson APLs are well-publicized. IMO, Enclose-Reduction-Style versus Insert-Reduction-Style deserve at least as much attention.
- Adam|Dyalog
- Posts: 143
- Joined: Thu Jun 25, 2015 1:13 pm
Re: do w/o a loop? (presumably an each question)
Even with Enclose-Reduction-Style reduction, if monadic ⍉ been defined as rotating the axes one step instead of reversing them, and we had the Under operator ⍢ then we could also have written:
⍪⍢⍉a×⍤1⍤99 ¯1⊢b