Adding zeros between every 2 elements of a matrix in matlab/octave - matrix

I am interested in how can I add rows and columns of zeros in a matrix so that it looks like this:
1 0 2 0 3
1 2 3 0 0 0 0 0
2 3 4 => 2 0 3 0 4
5 4 3 0 0 0 0 0
5 0 4 0 3
Actually I am interested in how can I do this efficiently, because walking the matrix and adding zeros takes a lot of time if you work with a big matrix.
Update:
Thank you very much.
Now I'm trying to replace the zeroes with the sum of their neighbors:
1 0 2 0 3 1 3 2 5 3
1 2 3 0 0 0 0 0 3 8 5 12... and so on
2 3 4 => 2 0 3 0 4 =>
5 4 3 0 0 0 0 0
5 0 4 0 3
as you can see i'm considering all the 8 neighbors of an element, but again using for and walking the matrix slows me down quite a bit, is there a faster way ?

Let your little matrix be called m1. Then:
m2 = zeros(5)
m2(1:2:end,1:2:end) = m1(:,:)
Obviously this is hard-wired to your example, I'll leave it to you to generalise.

Here are two ways to do part 2 of the question. The first does the shifts explicitly, and the second uses conv2. The second way should be faster.
M=[1 2 3; 2 3 4 ; 5 4 3];
% this matrix (M expanded) has zeros inserted, but also an extra row and column of zeros
Mex = kron(M,[1 0 ; 0 0 ]);
% The sum matrix is built from shifts of the original matrix
Msum = Mex + circshift(Mex,[1 0]) + ...
circshift(Mex,[-1 0]) +...
circshift(Mex,[0 -1]) + ...
circshift(Mex,[0 1]) + ...
circshift(Mex,[1 1]) + ...
circshift(Mex,[-1 1]) + ...
circshift(Mex,[1 -1]) + ...
circshift(Mex,[-1 -1]);
% trim the extra line
Msum = Msum(1:end-1,1:end-1)
% another version, a bit more fancy:
MexTrimmed = Mex(1:end-1,1:end-1);
MsumV2 = conv2(MexTrimmed,ones(3),'same')
Output:
Msum =
1 3 2 5 3
3 8 5 12 7
2 5 3 7 4
7 14 7 14 7
5 9 4 7 3
MsumV2 =
1 3 2 5 3
3 8 5 12 7
2 5 3 7 4
7 14 7 14 7
5 9 4 7 3

Related

Maximum k such that A[0]<A[k], A[1]<A[k+1], ..., A[k-1]<A[2*k-1], after sorting each k-sized window

I need the efficient algorithm for this problem (time comlexity less than O(n^2)), please help me:
a[i..j] is called a[i..j] < b[i..j] if a[i]<b[i], a[i+1]<b[i+1], ..., a[j]<b[j] after sorting these 2 arrays.
Given array A[1..n], (n<= 10^5, a[i]<= 1000). Find the maximum of k that A[1..k] < A[k+1..2k]
For example, n=10: 2 2 1 4 3 2 5 4 2 3
the answer is 4
Easily to see that k <= n/2. So we can use brute-forces (k from n/2 to 1), but not binary search.
And I don't know what to do with a[i] <= 1000. Maybe using map???
Use a Fenwick tree with range updates. Each index in the tree represents the count of how many numbers in window A are smaller than it. For the windows to be valid, each element in B (the window on the right) must have a partner in A (the window on the left). When we shift a number x into A, we add 1 to the range, [x+1, 1000] in the tree. For the element shifted from B to A, add 1 in its tree index. For each new element in B, add -1 to its index in the tree. If an index drops below zero, the window is invalid.
For the example, we have:
2 2 1 4 3 2 5 4 2 3
2 2
|
Tree:
add 1 to [3, 1000]
add -1 to 2
idx 1 2 3 4 5
val 0 -1 1 1 1 (invalid)
2 2 1 4 3 2 5 4 2 3
2 2 1 4
|
Tree:
add 1 to [3, 1000]
add 1 to 2 (remove 2 from B)
add -1 to 1
add -1 to 4
idx 1 2 3 4 5
val -1 0 2 1 2 (invalid)
2 2 1 4 3 2 5 4 2 3
2 2 1 4 3 2
|
Tree:
add 1 to [2, 1000]
add 1 to 1 (remove 1 from B)
add -1 to 3
add -1 to 2
idx 1 2 3 4 5
val 0 0 2 2 3 (valid)
2 2 1 4 3 2 5 4 2 3
2 2 1 4 3 2 5 4
|
Tree:
add 1 to [5, 1000]
add 1 to 4 (remove 4 from B)
add -1 to 5
add -1 to 4
idx 1 2 3 4 5
val 0 0 2 2 3 (valid)
2 2 1 4 3 2 5 4 2 3
2 2 1 4 3 2 5 4 2 3
|
Tree:
add 1 to [4, 1000]
add 1 to 3 (remove 3 from B)
add -1 to 2
add -1 to 3
idx 1 2 3 4 5
val 0 -1 2 3 4 (invalid)

plotting multiple graphs and animation from a data file in gnuplot

Suppose I have the following sample data file.
0 1 2
0 3 4
0 1 9
0 9 2
0 19 0
0 6 1
0 11 0
1 3 2
1 3 4
1 1 6
1 9 2
1 15 0
1 6 6
1 11 1
2 3 2
2 4 4
2 1 6
2 9 6
2 15 0
2 6 6
2 11 1
first column gives value of time. Second gives values of x and 3rd column y. I wish to plot graphs of y as functions of x from this data file at different times,
i.e, for t=0, I shall plot using 2:3 with lines up to t=0 index. Then same thing I shall do for the variables at t=1.
At the end of the day, I want to get a gif, i.e, an animation of how the y vs x graph changes shape as time goes on. How can I do this in gnuplot?
What have you tried so far? (Check help ternary and help gif)
You need to filter your data with the ternary operator and then create the animation.
Code:
### plot filtered data and animate
reset session
$Data <<EOD
0 1 2
0 3 4
0 1 9
0 9 2
0 19 0
0 6 1
0 11 0
1 3 2
1 3 4
1 1 6
1 9 2
1 15 0
1 6 6
1 11 1
2 3 2
2 4 4
2 1 6
2 9 6
2 15 0
2 6
2 11 1
EOD
set terminal gif animate delay 50 optimize
set output "myAnimation.gif"
set xrange[0:20]
set yrange[0:10]
do for [i=0:2] {
plot $Data u 2:($1==i?$3:NaN) w lp pt 7 ti sprintf("Time: %g",i)
}
set output
### end of code
Result:
Addition:
The meaning of $1==i?$3:NaN in words:
If the value in the first column is equal to i then the result is the value in the third column else it will be NaN ("Not a Number").

How do I shorten execution time by replacing the while-loop?

I have written a small code in Octave and part of it is checking whether values in the first rows of two matrices are equal, and if so, adding the value of the second row of the second matrix to the value of the second row of the first matrix.
This is that part of the code that I have written, using a small set of data:
PositionLoadArray =
1 5 3 7 4 6 9 2 1 2
1 2 3 4 5 6 7 8 9 10
X =
0 1 2 3 4 5 6 7 8 9
0 0 0 0 0 0 0 0 0 0
x=1; #row number in matrix X
y=1; #row number in matrix PositionLoadArray
while y<=columns(PositionLoadArray)
if PositionLoadArray(1,y)==X(1,x)
X(2,x)=X(2,x)+PositionLoadArray(,y);
y=y+1;
x=1;
else
x=x+1;
endif
endwhile
This gives the result:
X =
0 1 2 3 4 5 6 7 8 9
0 10 18 3 5 2 6 4 0 7
The loop runs and works perfectly for small sets like the one above (i.e. where the total number of columns for X and PositionLoadArray (max. values of x and y, respectively) are small). But the loop takes hours to be executed with larger values.
How can I reduce the execution time and get the same result?
Try
X(2, X(1,:) == Y(1,:)) += Y(2, X(1,:) == Y(1,:))

Find row and column number of eight neighbors conditionally in Matlab

I have a 6 * 6 matrix
A=
3 8 8 8 8 8
4 6 1 0 7 -1
9 7 0 2 6 -1
7 0 0 5 4 4
4 -1 0 2 8 1
1 -1 0 8 3 9
I am interested in finding row and column number of neighbors starting from A(4,4)=5. But They will be linked to A(4,4) as neighbor only if A(4,4) has element 4 on right, 6 on left, 2 on top, 8 on bottom 1 on top left diagonally, 3 on top right diagonally, 7 on bottom left diagonally and 9 on bottom right diagonally. TO be more clear A(4,4) will have neighbors if the neighbors are surrounding A(4,4) as follows:
1 2 3;
6 5 4;
7 8 9;
And this will continue as each neighbor is found.
Also 0 and -1 will be ignored. In the end I want to have these cells' row and column number as shown in figure below. Is there any way to visualize this network as well. This is sample only. I really have a huge matrix.
A = [3 8 8 8 8 8;
4 6 1 0 7 -1;
9 7 0 2 6 -1;
7 0 0 5 4 4;
4 -1 0 2 8 1;
1 -1 0 8 3 9];
test = [1 2 3;
6 5 4;
7 8 9];
%//Pad A with zeros on each side so that comparing with test never overruns the boundries
%//BTW if you have the image processing toolbox you can use the padarray() function to handle this
P = zeros(size(A) + 2);
P(2:end-1, 2:end-1) = A;
current = zeros(size(A) + 2);
past = zeros(size(A) + 2);
%//Initial state (starting point)
current(5,5) = 1; %//This is A(4,4) but shifted up 1 because of the padding
condition = 1;
while sum(condition(:)) > 0;
%//get the coordinates of any new values added to current
[x, y] = find(current - past);
%//update past to last iterations current
past = current;
%//loop through all the coordinates returned by find above
for ii=1:size(x);
%//Make coord vectors that represent the current coordinate plus it 8 immediate neighbours.
%//Note that this is why we padded the side in the beginning, so if we hit a coordinate on an edge, we can still get 8 neighbours for it!
xcoords = x(ii)-1:x(ii)+1;
ycoords = y(ii)-1:y(ii)+1;
%//Update current based on comparing the coord and its neighbours against the test matrix, be sure to keep the past found points hence the OR
current(xcoords, ycoords) = (P(xcoords, ycoords) == test) | current(xcoords, ycoords);
end
%//The stopping condition is when current == past
condition = current - past;
end
%//Strip off the padded sides
FinalAnswer = current(2:end-1, 2:end-1)
[R, C] = find(FinalAnswer);
coords = [R C] %//This line is unnecessary, it just prints out the results at the end for you.
OK cool you got very close, so here is the final solution with the loops. It runs in about 0.002 seconds so it's pretty quick I think. The output is
FinalAnswer =
0 0 0 0 0 0
0 1 1 0 0 0
0 1 0 1 0 0
1 0 0 1 1 1
0 0 0 0 1 0
0 0 0 0 0 1
coords =
4 1
2 2
3 2
2 3
3 4
4 4
4 5
5 5
4 6
6 6

Evaluating the distribution of words in a grid

I'm creating a word search and am trying to calculate quality of the generated puzzles by verifying the word set is "distributed evenly" throughout the grid. For example placing each word consecutively, filling them up row-wise is not particularly interesting because there will be clusters and the user will quickly notice a pattern.
How can I measure how 'evenly distributed' the words are?
What I'd like to do is write a program that takes in a word search as input and output a score that evaluates the 'quality' of the puzzle. I'm wondering if anyone has seen a similar problem and could refer me to some resources. Perhaps there is some concept in statistics that might help? Thanks.
The basic problem is distribution of lines in a square or rectangle. You can eighter do this geometrically or using integer arrays. I will try the integer arrays here.
Let M be a matrix of your puzzle,
A B C D
E F G H
I J K L
M N O P
Let the word "EFGH" be an existent word, as well as "CGKO". Then, create a matrix which will contain the count of membership in eighter words in each cell:
0 0 1 0
1 1 2 1
0 0 1 0
0 0 1 0
Apply a rule: the current cell value is equal to the sum of all neighbours (4-way) and multiply with the cell's original value, if the original value is 2 or higher.
0 0 1 0 1 2 2 2
1 1 2 1 -\ 1 3 8 2
0 0 1 0 -/ 1 2 3 2
0 0 1 0 0 1 1 1
And sum up all values in rows and columns the matrix:
1 2 2 2 = 7
1 3 8 2 = 14
1 2 3 2 = 8
0 1 1 1 = 3
| | | |
3 7 | 6
14
Then calculate the avarage of both result sets:
(7 + 14 + 8 + 3) / 4 = 32 / 4 = 8
(3 + 7 + 14 + 6) / 4 = 30 / 4 = 7.5
And calculate the avarage difference to the avarage of each result set:
3 <-> 7.5 = 4.5 7 <-> 8 = 1
7 <-> 7.5 = 0.5 14 <-> 8 = 6
14 <-> 7.5 = 6.5 8 <-> 8 = 0
6 <-> 7.5 = 1.5 3 <-> 8 = 5
___avg ___avg
3.25 3
And multiply them together:
3 * 3.25 = 9.75
Which you treat as a distributionscore. You might need to tweak it a little bit to make it work better, but this should calculate distributionscores quite nicely.
Here is an example of a bad distribution:
1 0 0 0 1 1 0 0 2
1 0 0 0 -\ 2 1 0 0 -\ 3 -\ C avg 2.5 -\ C avg-2-avg 0.5
1 0 0 0 -/ 2 1 0 0 -/ 3 -/ R avg 2.5 -/ R avg-2-avg 2.5
1 0 0 0 1 1 0 0 2 _____*
6 4 0 0 1.25 < score
Edit: calc. errors fixed.

Resources