Reputation: 1663
Say I have a list of 3 symbols :
l:`s1`s2`s3
What is the q-way to generate the following list of n*(n+1)/2 permutations?
(`s1;`s1),(`s1;`s2),(`s1;`s3),(`s2;`s2),(`s2;`s3),(`s3;`s3)
This can be seen as in the context of correlation matrix, where I want all the upper triangular part of the correlation matrix, including the diagonal.
Of course the size of my initial list will exceed 3, so I would like a generic function to perform this operation.
I know how to generate the diagonal elements:
q) {(x,y)}'[l;l]
(`s1`s1;`s2`s2;`s3`s3)
But I don't know how to generate the non-diagonal elements.
Upvotes: 3
Views: 419
Reputation: 666
Another solution you might find useful:
q)l
`s1`s2`s3
q){raze x,/:'-1_{1_x}\[x]}l
s1 s1
s1 s2
s1 s3
s2 s2
s2 s3
s3 s3
This uses the scan accumulator to create a list of lists of symbols, with each dropping the first element:
q)-1_{1_x}\[l]
`s1`s2`s3
`s2`s3
,`s3
The extra -1_
is needed since the scan will also return an empty list at the end. Then join each element of the list onto this result using an each-right and an each:
{x,/:'-1_{1_x}\[x]}l
(`s1`s1;`s1`s2;`s1`s3)
(`s2`s2;`s2`s3)
,`s3`s3
Finally use a raze to get the distinct permutations.
EDIT: could also use
q){raze x,/:'til[count x]_\:x}l
s1 s1
s1 s2
s1 s3
s2 s2
s2 s3
s3 s3
which doesnt need the scan at all and is very similar to the scan solution performance-wise!
Upvotes: 2
Reputation: 2569
I would try below code
{distinct asc each x cross x}`s1`s2`s3
It
cross
generates all (s_i, s_j) pairsasc each
sorts every pair by index, so `s3`s1
becomes `s1`s3
distinct
removes duplicatesNot the most efficient way by very short one.
Upvotes: 1
Reputation: 170
If I am understanding the question (apologies if I have missed something). Below should give you what you are looking for
q)test:`s1`s2`s3`s4`s5
q)(til cnt) _' raze (-1+cnt:count test)cut test,'/:test
(`s1`s1;`s2`s1;`s3`s1;`s4`s1;`s5`s1)
(`s2`s2;`s3`s2;`s4`s2;`s5`s2)
(`s3`s3;`s4`s3;`s5`s3)
(`s4`s4;`s5`s4)
,`s5`s5
Upvotes: 0