Search code examples
j

How can I take the outer product of string vectors in J?


I'm trying to replicate the outer product notation in APL:

∘.,⍨ 'x1' 'y1' 'z1' 'x2' 'y2' 'z2' 'x3' 'y3' 'z3'

which yields

 x1x1 x1y1 x1z1 x1x2 x1y2 x1z2 x1x3 x1y3 x1z3 
 y1x1 y1y1 y1z1 y1x2 y1y2 y1z2 y1x3 y1y3 y1z3 
 z1x1 z1y1 z1z1 z1x2 z1y2 z1z2 z1x3 z1y3 z1z3 
 x2x1 x2y1 x2z1 x2x2 x2y2 x2z2 x2x3 x2y3 x2z3 
 y2x1 y2y1 y2z1 y2x2 y2y2 y2z2 y2x3 y2y3 y2z3 
 z2x1 z2y1 z2z1 z2x2 z2y2 z2z2 z2x3 z2y3 z2z3 
 x3x1 x3y1 x3z1 x3x2 x3y2 x3z2 x3x3 x3y3 x3z3 
 y3x1 y3y1 y3z1 y3x2 y3y2 y3z2 y3x3 y3y3 y3z3 
 z3x1 z3y1 z3z1 z3x2 z3y2 z3z2 z3x3 z3y3 z3z3 

But I can't figure out how to do something similar in J. I found this Cartesian product in J post that I thought would be similar enough, but I just can't seem to translate it to an array of strings from an array of numbers.

Adapting Dan Bron's answer therein and applying it to a simpler example

6 6 $ , > { 2 # < 'abc'

gives

aaabac
babbbc
cacbcc
aaabac
babbbc
cacbcc

which is almost what I want, but I don't know how to generalize it to use 2-letter (or more) strings instead of single ones in a similar fashion. I also don't know how to format those results with spaces between the pairs like the APL output, so it may not be the right path either.

Similarly, I tried adapting Michael Berry's answer from that thread to get

9 36 $ ,,"1/ ~ 9 2 $ 'x1y1z1x2y2z2x3y3z3'

which gives

x1x1x1y1x1z1x1x2x1y2x1z2x1x3x1y3x1z3
y1x1y1y1y1z1y1x2y1y2y1z2y1x3y1y3y1z3
z1x1z1y1z1z1z1x2z1y2z1z2z1x3z1y3z1z3
x2x1x2y1x2z1x2x2x2y2x2z2x2x3x2y3x2z3
y2x1y2y1y2z1y2x2y2y2y2z2y2x3y2y3y2z3
z2x1z2y1z2z1z2x2z2y2z2z2z2x3z2y3z2z3
x3x1x3y1x3z1x3x2x3y2x3z2x3x3x3y3x3z3
y3x1y3y1y3z1y3x2y3y2y3z2y3x3y3y3y3z3
z3x1z3y1z3z1z3x2z3y2z3z2z3x3z3y3z3z3

Again, this is almost what I want, and this one handled the multiple characters, but there are still no spaces between them and the command is getting farther from the simplicity of the APL version.

I can get the same results a bit more cleanly with ravel items

,. ,"1/ ~ 9 2 $ 'x1y1z1x2y2z2x3y3z3'

I've been going through the J primer and exploring parts that look relevant in the dictionary, but I'm still very new, so I apologize if this is a dumb question. I feel like the rank conjunction operator should be able to help me here, but I had a hard time following its explanation in the primer. I played with ": to try to format the strings to have trailing spaces, but I also couldn't figure that out. The fact that this was so easy in APL also makes me think I'm doing something very wrong in J to be having this much trouble.

After reading more of the primer I got something that looks like what I want with

,. 9 1 $ ' ' ,."2 ,"1/~ [ ;._2 'x1 y1 z1 x2 y2 z2 x3 y3 z3 '

but this is still way more complicated than the APL version, so I'm still hoping there is an actually elegant and concise way to do this.


Solution

  • I think that the only thing that I can add to the things that you have already pointed out is that to keep a string separate into components you would need to box.

       <@,"1/~ 9 2 $ 'x1y1z1x2y2z2x3y3z3'
    +----+----+----+----+----+----+----+----+----+
    |x1x1|x1y1|x1z1|x1x2|x1y2|x1z2|x1x3|x1y3|x1z3|
    +----+----+----+----+----+----+----+----+----+
    |y1x1|y1y1|y1z1|y1x2|y1y2|y1z2|y1x3|y1y3|y1z3|
    +----+----+----+----+----+----+----+----+----+
    |z1x1|z1y1|z1z1|z1x2|z1y2|z1z2|z1x3|z1y3|z1z3|
    +----+----+----+----+----+----+----+----+----+
    |x2x1|x2y1|x2z1|x2x2|x2y2|x2z2|x2x3|x2y3|x2z3|
    +----+----+----+----+----+----+----+----+----+
    |y2x1|y2y1|y2z1|y2x2|y2y2|y2z2|y2x3|y2y3|y2z3|
    +----+----+----+----+----+----+----+----+----+
    |z2x1|z2y1|z2z1|z2x2|z2y2|z2z2|z2x3|z2y3|z2z3|
    +----+----+----+----+----+----+----+----+----+
    |x3x1|x3y1|x3z1|x3x2|x3y2|x3z2|x3x3|x3y3|x3z3|
    +----+----+----+----+----+----+----+----+----+
    |y3x1|y3y1|y3z1|y3x2|y3y2|y3z2|y3x3|y3y3|y3z3|
    +----+----+----+----+----+----+----+----+----+
    |z3x1|z3y1|z3z1|z3x2|z3y2|z3z2|z3x3|z3y3|z3z3|
    +----+----+----+----+----+----+----+----+----+
    

    If you want to get rid of the boxes and instead insert spaces then you are not really going to have the character items separately, you will have long strings with the spaces as part of the result.

    And it is a very good question because it requires you to understand the fact that character strings in J are vectors. I suppose that technically what you are looking for is this which results in a 9 9 4 shape, but it won't look the way that you expect.

       ,"1/~ 9 2 $ 'x1y1z1x2y2z2x3y3z3'
    x1x1
    x1y1
    x1z1
    x1x2
    x1y2
    x1z2
    x1x3
    x1y3
    x1z3
    
    y1x1
    y1y1
    y1z1
    y1x2
    y1y2
    y1z2
    y1x3
    y1y3
    y1z3
    
    z1x1
    z1y1
    z1z1
    z1x2
    z1y2
    z1z2
    z1x3
    z1y3
    z1z3
    
    x2x1
    x2y1
    x2z1
    x2x2
    x2y2
    x2z2
    x2x3
    x2y3
    x2z3
    
    y2x1
    y2y1
    y2z1
    y2x2
    y2y2
    y2z2
    y2x3
    y2y3
    y2z3
    
    z2x1
    z2y1
    z2z1
    z2x2
    z2y2
    z2z2
    z2x3
    z2y3
    z2z3
    
    x3x1
    x3y1
    x3z1
    x3x2
    x3y2
    x3z2
    x3x3
    x3y3
    x3z3
    
    y3x1
    y3y1
    y3z1
    y3x2
    y3y2
    y3z2
    y3x3
    y3y3
    y3z3
    
    z3x1
    z3y1
    z3z1
    z3x2
    z3y2
    z3z2
    z3x3
    z3y3
    z3z3
       $ ,"1/~ 9 2 $ 'x1y1z1x2y2z2x3y3z3'
    9 9 4
    
    You could also take the boxes and convert them to symbols, which might be closer to what you want, although they do have the backtick indicator as part of their representation.
     s:@<@,"1/~ 9 2 $ 'x1y1z1x2y2z2x3y3z3'
    `x1x1 `x1y1 `x1z1 `x1x2 `x1y2 `x1z2 `x1x3 `x1y3 `x1z3
    `y1x1 `y1y1 `y1z1 `y1x2 `y1y2 `y1z2 `y1x3 `y1y3 `y1z3
    `z1x1 `z1y1 `z1z1 `z1x2 `z1y2 `z1z2 `z1x3 `z1y3 `z1z3
    `x2x1 `x2y1 `x2z1 `x2x2 `x2y2 `x2z2 `x2x3 `x2y3 `x2z3
    `y2x1 `y2y1 `y2z1 `y2x2 `y2y2 `y2z2 `y2x3 `y2y3 `y2z3
    `z2x1 `z2y1 `z2z1 `z2x2 `z2y2 `z2z2 `z2x3 `z2y3 `z2z3
    `x3x1 `x3y1 `x3z1 `x3x2 `x3y2 `x3z2 `x3x3 `x3y3 `x3z3
    `y3x1 `y3y1 `y3z1 `y3x2 `y3y2 `y3z2 `y3x3 `y3y3 `y3z3
    `z3x1 `z3y1 `z3z1 `z3x2 `z3y2 `z3z2 `z3x3 `z3y3 `z3z3