How to implement combinations of a list - kdb

All
I need to get the combinations and permutations of a list.
A function have been implemented for permutations.
perm:{[N;l]$[N=1;l;raze .z.s[N-1;l]{x,/:y except x}\:l]}
However, I have no idea about combinations, just like this:
l: 1 2 3
comb[2;l]
1 2
1 3
2 3
l: 1 2 3 4
comb[3;l]
1 2 3
1 2 4
1 3 4
2 3 4
Thanks!

From your solution, you can do:
q)comb:{[N;l]$[N=1;l;raze .z.s[N-1;l]{x,/:y where y>max x}\:l]}
q)comb[2;1 2 3]
1 2
1 3
2 3
Another approach using over:
q)perm:{{raze x{x,/:y except x}\:y}[;y]/[x-1;y]}
q)comb:{{raze x{x,/:y where y>max x}\:y}[;y]/[x-1;y]}

One option is to use your permutation function like this:
q) comb:{[N;l] distinct asc each perm[N;l] }
q)l: 1 2 3 4
q) comb[3;l]
output:
1 2 3
1 2 4
1 3 4
2 3 4
Note: This will change the order of elements because of asc. So if your list should have (1 3 2) in answer, it will give (1 2 3).
To maintain order, use any other function/logic in place of asc to filter duplicate elements in sets (ex: (1 2 3) and (1 3 2) are duplicates).

Related

Sum of each two elements using vector functions

How to get sum of eath two elements with the vector functions? I want the same result as:
{x+y}':[1 2 3 2 1]
Why this approach gives something different than first one?
sum':[1 2 3 2 1]
sum is not the same as {x+y}.
sum has rank 1 meaning it takes one input and sums the elements of that input.
It can sum an atom:
q)sum 1
1
a uniform list
q)sum 1 2
3
or a list of lists
q)sum(1 2;3 4)
4 6
{x+y} is rank 2 meaning it requires two inputs.
q){x+y}[1;2]
3
q){x+y}[1 2;3 4]
4 6
Giving it an atom, a single list, or a list of lists leads to projections
q){x+y}1
{x+y}[1]
q){x+y}1 2
{x+y}[1 2]
q){x+y}(1 2;3 4)
{x+y}[(1 2;3 4)]
Since each-prior (':) creates binary pairs from the input and attempts to apply a rank 2 function, it works as intended on your rank 2 function {x+y}.
But since sum is not rank 2 the each-prior doesn't generate pairs in the same way, it's equivalent to doing
q){x}':[1 2 3 2 1]
1 2 3 2 1
q){sum x}':[1 2 3 2 1]
1 2 3 2 1
You could force it to be rank 2:
q){sum(x;y)}':[1 2 3 2 1]
1 3 5 5 3
but this gives a different result since sum ignores nulls while + doesn't.
q)sum(0N;1)
1
q)0N+1
0N
Finally, an alternative way to achieve this using sum (and without using each-prior) is to shift the vector using prev and then sum
q){sum(prev x;x)}[1 2 3 2 1]
0N 3 5 5 3

(q/kdb+) Merge items in a list

I have a list of items and need to merge them into a single column
using the list
list:(1 2;3 4 5 7;0 1 3)
index value
0 1 2
1 3 4 5 7
2 0 1 3
my goal is
select from list2
value
1
2
3
4
5
7
0
1
3
'raze' function flattens out 1 level of the list.
q) raze (1 2;3 4 5 7;0 1 3)
q) 1 2 3 4 5 7 0 1 3
If you have list with multi level indexing then use 'over' adverb with raze:
q) (raze/)(1 2 3;(11 12;33 44);5 6)
To convert that to table column:
q) t:([]c:raze list)
ungroup would also work provided your table doesn't have multiple columns with different nesting (or strings)
q)ungroup ([]list)
list
----
1
2
3
4
5
7
0
1
3
If you just wanted your list to appear like that I would do the following.
1 cut raze list
I see that you have used a select statement, however if you want your column defined as this in your table do the following
a:raze list
tab:([] b:a)
Your output from this should look like this
q)tab
b
-
1
2
3
4
5
7
0
1
3
Overall, a more concise way to achieve what you want to do would be
select from ([]raze list)
To avoid any errors you should not call the column header 'value' as this is a protected keyword in kdb+ and when you try to reassign it as a column header kdb will through an assign error
`assign
Hope this helps

Nested loop and conditional statement (Matlab)

If you have a random matrix, for example a 5x5:
A(i,j) = (5 4 3 2 1
4 3 2 1 0
5 4 3 2 1
4 3 2 1 0
5 4 3 2 1)
And a second array:
B(1,j) = (4 5 6 7 8)
How can I then assign values of B to A if this only needs to be done when the value of B(1,j) is larger than any of the values from a certain colomn of A?
For example, B(1,1) = 4 and in the first colomn of A it is larger than A(1,1), A(3,1) and A(5,1), so these must be replaced by 4. In the second colomn, nothing needs to be replaced, etc.
Thanks already!
You can do this without any explicit looping using bsxfun:
A = [5 4 3 2 1
4 3 2 1 0
5 4 3 2 1
4 3 2 1 0
5 4 3 2 1];
B = [4 5 6 7 8];
A = bsxfun(#min,A,B);
Result:
A =
4 4 3 2 1
4 3 2 1 0
4 4 3 2 1
4 3 2 1 0
4 4 3 2 1
In later versions of MATLAB (2016b and later) you can even omit the bsxfun and get the same result.
A = min(A,B);
Matlab "find" may be of use to you.
https://www.mathworks.com/help/matlab/matlab_prog/find-array-elements-that-meet-a-condition.html
If you aren't concerned about speed or efficiency, you could also set up a two nested for loops with a condition (i.e. an if) statement comparing the values of A and B.
If you only interested in column wise comparison to B, you could use the increment of the outer loop in the inner loop.
for i,...
for j,...
if B(1,i) > A(j,i)
A(j,i)=B(i,j)

How to sum consecutive identical numbers in a list in kdb?

I have a list like this:
a:1 1 1 1 2 3 1 1 4 4 4 5 6 4
How can I sum all of the consecutive identical numbers in a, so that it will become:
a:4 2 3 2 12 5 6 4
There are many ways - one method:
q) a:1 1 1 1 2 3 1 1 4 4 4 5 6 4
q) sum each where[differ a] _ a
4 2 3 2 12 5 6 4
Another method to achieve this using prev & <>:
sum each cut[where a<>prev[a]; a]
4 2 3 2 12 5 6 4

find group of elements in matrix matlab

I have an array of elements E = [1 2 3 4 5 10] and matrix A of couples of elements
A=[ 1 2;
2 3;
3 1;
4 1;
4 3;
5 1]
You can read this matrix as
1 is similar (with a certain probability) to 2
2 is similar (with a certain probability) to 3
3 is similar (with a certain probability) to 1 etc...
I would like to know how many different groups of element are in the array E given the matrix A
In this case I have
1 group = 1 2 3
2 group = 1 3 4
3 group = 1 5
4 group = 10
so there are 4 different groups of elements in E
NOTE:
if 1 is similar to 2 (first row)
and if 5 is similar to 1 (sixth row)
5 is not similar to 2!!! (if it is not written anywhere)
so 1 2 5 don't belong to the same group
On the other hand
1 is similar to 2 (first row),
2 is similar to 3 (second row)
and 3 is similar to 1 (third row)
so 1 2 3 belong to the same group