General position find function in q - matrix

I need something like Position function for Mathematica (http://reference.wolfram.com/mathematica/ref/Position.html) but in Q. My solution for rectangular matrix is following:
q) colrow:{sz:count x; $[(count first x) = 1; enlist y; (floor y % sz; y mod sz)]}
q) position:{flip colrow[x;(where raze x = y)]}
It works straightforward for rectangular matrices and lists:
q) t:(1 -1 1; / matrix test
-1 3 4;
1 -1 1);
q) pos1:position[t;-1] / try to find all positions of -1
q) pos1
0 1
1 0
2 1
q) t ./: pos1 / here get items
-1 -1 -1
q) l:1 0 3 0 2 3 4 1 0 / list test
q) pos2:position[l;0] / try to find all positions of 0
q) pos2
1
3
8
q) l ./: pos2 / get items
0 0 0
This works but it'd be good to have more general solution for arbitrary lists and not only rectangular matrices. For instance code above won't work correctly for arguments like:
position[(1 2 3; 1 2; 1 2 1 4); 1]
May be someone has generic solution for that ?

How's this look? I think it should work for all two-dimensional lists, ragged or rectangular, and also for vectors. (I haven't worked out a version for arbitrary dimensions yet.)
q)position:{{$[type x;enlist each where x;raze flip each flip(til count x;raze each .z.s each x)]}x=y}
q)t
1 -1 1
-1 3 4
1 -1 1
q)l
1 0 3 0 2 3 4 1 0
q)r
1 2 3
1 2
1 2 1 4
q)pos1:position[t;-1]
q)pos2:position[l;0]
q)pos3:position[r;1]
q)pos1
0 1
1 0
2 1
q)pos2
1
3
8
q)pos3
0 0
1 0
2 0
2 2
q)t ./:pos1
-1 -1 -1
q)l ./:pos2
0 0 0
q)r ./:pos3
1 1 1 1
q)
EDIT:
Here's a version that works for all dimensions except 1 (and 0 of course):
q)position2:{{$[type x;where x;raze each raze flip each flip(til count x;.z.s each x)]}x=y}
q)r2:(r;r)
q)0N!r2;
((1 2 3;1 2;1 2 1 4);(1 2 3;1 2;1 2 1 4))
q)pos4:position2[r2;1]
q)0N!pos4;
(0 0 0;0 1 0;0 2 0;0 2 2;1 0 0;1 1 0;1 2 0;1 2 2)
q)r2 ./:pos4
1 1 1 1 1 1 1 1
q)r ./:position2[r;1]
1 1 1 1
q)t ./:position2[t;-1]
-1 -1 -1
q)
On vectors, though, it returns an address vector, not an address matrix, so it has to be used with #, not .:
q)0N!position2[l;0];
1 3 8
q)l ./:position2[l;0]
'type
q)l position2[l;0]
0 0 0
q)
If you really need it to work the same way on vectors as on higher-dimensional structures, the simplest solution is probably just to special-case them directly:
q)position3:{$[type x;enlist each where#;{$[type x;where x;raze each raze flip each flip(til count x;.z.s each x)]}]x=y}
q)position3[l;0]
1
3
8
q)l ./:position3[l;0]
0 0 0
q)r2 ./:position3[r2;1]
1 1 1 1 1 1 1 1
q)r ./:position3[r;1]
1 1 1 1
q)t ./:position3[t;-1]
-1 -1 -1
q)

Below should also work.
Not the exact solution but workable.
pos:{$[type x;where x=y;where each x=y]}
val:{raze ($[0h=type x;x#';x#])pos[x;y]}
q)t:(1 -1 1;-1 3 4;1 -1 1)
q)pos[t;-1]
1
0
1
q)val[t;-1]
-1
-1
-1
q)l:1 0 3 0 2 3 4 1 0
q)pos[l;0]
1 3 8
q)val[l;0]
0 0 0
q)r:(1 2 3; 1 2; 1 2 1 4)
q)pos[r;1]
,0
,0
0 2
q)val[r;1]
1 1 1 1

Related

Minesweeper puzzle

I'm creating a minesweeper solver, but it's unable to solve this puzzle and nor can I figure out how to do it by hand.
Is this puzzle possible without guessing?
1 1 1 0
1 x 2 1
1 2 ? ?
0 1 ? ?
1 2 2 ?
x 2 ? ?
1 2 ? ?
There are 3 mines remaining.
Here are two possibilities I can up with:
1 1 1 0
1 x 2 1
1 2 x 1
0 1 1 1
1 2 2 2
x 2 x x
1 2 2 2
1 1 1 0
1 x 2 1
1 2 3 x
0 1 x 2
1 2 2 2
x 2 x 1
1 2 1 1
It is not possible without guessing. Here are two (of several) solved grids that match your example.
1 1 1 0
1 x 2 1
1 2 x 1
0 1 2 2
1 2 2 x
x 2 x 2
1 2 1 1
1 1 1 0
1 x 2 1
1 2 2 x
0 1 x 2
1 2 2 2
x 2 2 x
1 2 x 2

APL find frequency of elements in a matrix

I have this piece of code
((⍳3)∘.+(⍳2))
which generates the following matrix
2 3
3 4
4 5
I want to find the occurrence of each unique element in the result i.e occurrence of 2,3,4,5 in the result.
I tried using "∘.=" with the matrix itself and then reshaping such that elements of each sub matrix is transformed into a row
using
6 6⍴ ((⍳3)∘.+(⍳2))∘.=((⍳3)∘.+(⍳2))
which gives the following result
1 0 0 0 0 0 for 2
0 1 1 0 0 0 for 3
0 1 1 0 0 0 for 3
0 0 0 1 1 0 for 4
0 0 0 1 1 0 for 4
0 0 0 0 0 1 for 5
as you can see it still contains the sum for duplicate items, and I'm lost as of now.
Any help will be appreciated.
You should do ∘.= between the unique elements in the matrix and a flat vector of all elements, like:
m ← ((⍳3)∘.+(⍳2))
(∪,m) ∘.= ,m
1 0 0 0 0 0
0 1 1 0 0 0
0 0 0 1 1 0
0 0 0 0 0 1
Then just do +/ on it to get the frequencies of ∪,m
+/ (∪,m) ∘.= ,m
1 2 2 1
∪,m
2 3 4 5
(Tested on GNU APL.)
Dyalog APL version 14.0 has the ⌸ Key operator exactly for this, you just need to ravel your data:
{≢⍵}⌸ ,((⍳3)∘.+(⍳2))
1 2 2 1
Try it online!
You can even use the left argument of ⌸'s operand function to create a table:
{⍺,≢⍵}⌸ ,((⍳3)∘.+(⍳2))
2 1
3 2
4 2
5 1
Try it online!

How to create a symmetric matrix of 1's and 0's with constant row and column sum

I'm trying to find an elegant algorithm for creating an N x N matrix of 1's and 0's, under the restrictions:
each row and each column must sum to Q (to be picked freely)
the diagonal must be 0's
the matrix must be symmetrical.
It is not strictly necessary for the matrix to be random (both random and non-random solutions are interesting, however), so for Q even, simply making each row a circular shift of the vector
[0 1 1 0 ... 0 0 0 ... 0 1 1] (for Q=4)
is a valid solution.
However, how to do this for Q odd? Or how to do it for Q even, but in a random fashion?
For those curious, I'm trying to test some phenomena on abstract networks.
I apologize if this has already been answered before, but none of the questions I could find had the symmetric restriction, which seems to make it much more complicated. I don't have a proof that such a matrix always exists, but I do assume so.
The object that you're trying to construct is known more canonically as an undirected d-regular graph (where d = Q). By the handshaking theorem, N and Q cannot both be odd. If Q is even, then connect vertex v to v + k modulo N for k in {-Q/2, -Q/2 + 1, ..., -1, 1, ..., Q/2 - 1, Q/2}. If Q is odd, then N is even. Construct a (Q - 1)-regular graph as before and then add connections from v to v + N/2 modulo N.
If you want randomness, there's a Markov chain whose limiting distribution is uniform on d-regular graphs. You start with any d-regular graph. Repeatedly pick vertices v, w, x, y at random. Whenever the induced subgraph looks like
v----w
x----y ,
flip it to
v w
| |
x y .
You can perhaps always follow your circular shift algorithm, when possible.
The only condition you need to follow while using the circular shift algorithm is to maintain the symmetric nature in the first row.
i.e. keeping Q 1's in the first row so that Q[0,1] to Q[0,N-1] {Assuming 0 indexed rows and cols, Q[0,0] is 0.} is symmetric, a simple example being 110010011.
Hence, N = 10, Q = 5, you can get many possible arrangements such as:
0 1 0 0 1 1 1 0 0 1
1 0 1 0 0 1 1 1 0 0
0 1 0 1 0 0 1 1 1 0
0 0 1 0 1 0 0 1 1 1
1 0 0 1 0 1 0 0 1 1
1 1 0 0 1 0 1 0 0 1
1 1 1 0 0 1 0 1 0 0
0 1 1 1 0 0 1 0 1 0
0 0 1 1 1 0 0 1 0 1
1 0 0 1 1 1 0 0 1 0
or
0 1 1 0 0 1 0 0 1 1
1 0 1 1 0 0 1 0 0 1
1 1 0 1 1 0 0 1 0 0
0 1 1 0 1 1 0 0 1 0
0 0 1 1 0 1 1 0 0 1
1 0 0 1 1 0 1 1 0 0
0 1 0 0 1 1 0 1 1 0
0 0 1 0 0 1 1 0 1 1
1 0 0 1 0 0 1 1 0 1
1 1 0 0 1 0 0 1 1 0
But as you can see for odd N(that means even N-1) and odd Q there can't be any such symmetric distribution.. Hope it helped.

Finding all subsets of a multiset

Suppose I have a bag which contains 6 balls (3 white and 3 black). I want to find all possible subsets of a given length, disregarding the order. In the case above, there are only 4 combinations of 3 balls I can draw from the bag:
2 white and 1 black
2 black and 1 white
3 white
3 black
I already found a library in my language of choice that does exactly this, but I find it slow for greater numbers. For example, with a bag containing 15 white, 1 black, 1 blue, 1 red, 1 yellow and 1 green, there are only 32 combinations of 10 balls, but it takes 30 seconds to yield the result.
Is there an efficient algorithm which can find all those combinations that I could implement myself? Maybe this problem is not as trivial as I first thought...
Note: I'm not even sure of the right technic words to express this, so feel free to correct the title of my post.
You can do significantly better than a general choose algorithm. The key insight is to treat each color of balls at the same time, rather than each of those balls one by one.
I created an un-optimized implementation of this algorithm in python that correctly finds the 32 result of your test case in milliseconds:
def multiset_choose(items_multiset, choose_items):
if choose_items == 0:
return 1 # always one way to choose zero items
elif choose_items < 0:
return 0 # always no ways to choose less than zero items
elif not items_multiset:
return 0 # always no ways to choose some items from a set of no items
elif choose_items > sum(item[1] for item in items_multiset):
return 0 # always no ways to choose more items than are in the multiset
current_item_name, current_item_number = items_multiset[0]
max_current_items = min([choose_items, current_item_number])
return sum(
multiset_choose(items_multiset[1:], choose_items - c)
for c in range(0, max_current_items + 1)
)
And the tests:
print multiset_choose([("white", 3), ("black", 3)], 3)
# output: 4
print multiset_choose([("white", 15), ("black", 1), ("blue", 1), ("red", 1), ("yellow", 1), ("green", 1)], 10)
# output: 32
No, you don't need to search through all possible alternatives. A simple recursive algorithm (like the one given by #recursive) will give you the answer. If you are looking for a function that actually outputs all of the combinations, rather than just how many, here is a version written in R. I don't know what language you are working in, but it should be pretty straightforward to translate this into anything, although the code might be longer, since R is good at this kind of thing.
allCombos<-function(len, ## number of items to sample
x, ## array of quantities of balls, by color
names=1:length(x) ## names of the colors (defaults to "1","2",...)
){
if(length(x)==0)
return(c())
r<-c()
for(i in max(0,len-sum(x[-1])):min(x[1],len))
r<-rbind(r,cbind(i,allCombos(len-i,x[-1])))
colnames(r)<-names
r
}
Here's the output:
> allCombos(3,c(3,3),c("white","black"))
white black
[1,] 0 3
[2,] 1 2
[3,] 2 1
[4,] 3 0
> allCombos(10,c(15,1,1,1,1,1),c("white","black","blue","red","yellow","green"))
white black blue red yellow green
[1,] 5 1 1 1 1 1
[2,] 6 0 1 1 1 1
[3,] 6 1 0 1 1 1
[4,] 6 1 1 0 1 1
[5,] 6 1 1 1 0 1
[6,] 6 1 1 1 1 0
[7,] 7 0 0 1 1 1
[8,] 7 0 1 0 1 1
[9,] 7 0 1 1 0 1
[10,] 7 0 1 1 1 0
[11,] 7 1 0 0 1 1
[12,] 7 1 0 1 0 1
[13,] 7 1 0 1 1 0
[14,] 7 1 1 0 0 1
[15,] 7 1 1 0 1 0
[16,] 7 1 1 1 0 0
[17,] 8 0 0 0 1 1
[18,] 8 0 0 1 0 1
[19,] 8 0 0 1 1 0
[20,] 8 0 1 0 0 1
[21,] 8 0 1 0 1 0
[22,] 8 0 1 1 0 0
[23,] 8 1 0 0 0 1
[24,] 8 1 0 0 1 0
[25,] 8 1 0 1 0 0
[26,] 8 1 1 0 0 0
[27,] 9 0 0 0 0 1
[28,] 9 0 0 0 1 0
[29,] 9 0 0 1 0 0
[30,] 9 0 1 0 0 0
[31,] 9 1 0 0 0 0
[32,] 10 0 0 0 0 0
>

How can I find a solution of binary matrix equation AX = B?

Given an m*n binary matrix A, m*p binary matrix B, where n > m what is an efficient algorithm to compute X such that AX=B?
For example:
A =
1 1 0 0 1 1 0 1 0 0
1 1 0 0 1 0 1 0 0 1
0 1 1 0 1 0 1 0 1 0
1 1 1 1 1 0 0 1 1 0
0 1 1 0 1 0 1 1 1 0
B =
0 1 0 1 1 0 1 1 0 1 0 0 1 0
0 0 1 0 1 1 0 0 0 1 0 1 0 0
0 1 1 0 0 0 1 1 0 0 1 1 0 0
0 0 1 1 1 1 0 0 0 1 1 0 0 0
1 0 0 1 0 0 1 0 1 0 0 1 1 0
Note, when I say binary matrix I mean matrix defined over the field Z_2, that is, where all arithmetic is mod 2.
If it is of any interest, this is a problem I am facing in generating suitable matrices for a random error correction code.
You can do it with row reduction: Place B to the right of A, and then swap rows (in the whole thing) to get a 1 in row 0, col 0; then xor that row to any other row that has a '1' in column 0, so you have only a single 1 in column 0. Then move to the next column; if [1,1] is zero then swap row 1 with a later row that has a 1 there, then xor rows to make it the only 1 in the column. Assuming 'A' is a square matrix and a solution exists, then you eventually have converted A to unity, and B is replaced with the solution to Ax=B.
If n > m, you have a system with more unknowns than equations, so you can solve for some of the unknowns, and set the others to zero. During the row reduction, if there are no values in a column which have a '1' to use (below the rows already reduced) you can skip that column and make the corresponding unknown zero (you can do this at most n-m times).

Resources