Unexpected behavior while using end to grow arrays - arrays

while building a video array from a directory of images I encounter unexpected behavior. Original code:
vid = [];
for i =startframe:endframe
image = [directoryOfImages ,'\', images_names{1,i}];
vid(:,:,:,end+1) = imread(image);
waitbar((i-startframe) / (endframe-startframe));
end
Then I ran this code to check thing up:
a = []; size(a)
a(end+1) = 1; size(a)
The first size was [0, 0] and the second size was [1, 1]. The same expected behavior I got in this code:
b = []; size(b)
b(:,end+1) = 1; size(b)
The first size was [0, 0] and the second size was [1, 1]. But in this code, something weird happened:
c = []; size(c)
c(:,:,end+1) = 1; size(c)
while here the first size was [0,0] and the second one was [1,1,2].
This was very unexpected. I printed c and I got this:
>>c
c(:,:,1) =
0
c(:,:,2) =
1
Finally, I ran this script:
c=[]; c(:,:,end)=1; size(c)
and I got [1, 1].
can someone explain what is going on here? when I use c=[] do I get an empty array with the size of [0,0,1]? so how come size(c) doesn't mention it? and why when I use c(:,:,end)=1; its size is not [1,1,1]? and what about when I use c(:,:,:,end)=1?

This is just MATLAB choosing what to display.
In MATLAB, matrices are infinite dimensional. As a nice example, lets try your b:
b = [];
b(:,end+1) = 1;
As you know, you can query the size of an specific dimension with size. E.g. size(b,2) returns 1. But what does size(b,12345) return?, well, it returns 1 also, as matrices are infinite dimensional. In the 12345th dimension, the size of b is 1.
However, what horrible would the display function be, if every time you type size(b) it outputs an infinite amount of dimensions! Thus when displaying, MATLAB defaults to displaying 2 dims OR N-dims, where N is the furthest dimension with data on it (non-singleton dimension).
Thus, what you are seeing with your c example is weird behaviour by the display function, not the size function. size(c,3) returns 1. This is caused also by the [] only setting the size of the first two dimensions to zero, to avoid having a MxPx0 variable when filling it up (c(:,:,end)=img, what happens with end ?), which is essentially an empty variable.

Related

Recursive function that returns the number of possible combinations

I had an interview and was asked a question that I'd like to understand the solution.
The Question
Create a recursive function that returns the number of possible combinations of arrays of a given length that could be made from an array of non-repeating consecutive integers.
f(array, length) = Combinations
Example 1
array = [0,1,2,3]
length = 2
Combinations = 10 (all combinations: [0,0] [0,1] [0,2] [0,3] [1,1] [1,2] [1,3] [2,2] [2,3] [3,3])
Note that [0,0] is allowed but [1,0] is not because [0,1] is defined
Example 2
array = [0,1]
length = 3
Combinations = 4 (all combinations: [0,0,0] [0,0,1] [0,1,1] [1,1,1])
One "hint" was offered. The interviewer said the array itself shouldn't matter; the length was all that was needed.
This algorithm can be expressed recursively because the solution can be expressed in terms of solutions for smaller inputs. "Smaller" here has two meanings:
A subset of the array; specifically the sub-array after the current element index
Solutions for smaller length; these can be added together to give the solution for length + 1
Stopping conditions:
When the array size A = 1 - only one combination can be generated
When the length L = 1 - number of combinations = number of elements in array
The fully recursive procedure is a surprisingly simple one-liner:
return [recursive call to rest of array, same length] +
[recursive call to same array, length - 1]
This is called dynamic programming.
Code:
int F(int A, int L)
{
if (A <= 1) return 1;
if (L <= 1) return A;
return F(A - 1, L) + F(A, L - 1);
}
Tests:
F(4, 2) = 10
F(2, 3) = 4
F(3, 5) = 21 (trace it with pen-and-paper to see for yourself)
EDIT: I've given an elegant and simple solution, but I perhaps haven't explained it as well as #RoryDaulton. Consider giving his answer credit too.
You do not give a target language and you do not say just how much help you want. So I'll give the overall idea of an algorithm that should be simple to code if you know recursion in a certain language. Ask if you want more code in Python, my current preferred language.
You know you need to do recursion, and you have two things you could recurse on: the length of the given array or the length of the desired arrays. Let's recurse on the second, and let's say the given array is [0, 1, ..., n-1] since you know that the actual contents are irrelevant.
If the desired length r is 1 you know there are only n desired arrays, namely [0], [1], ..., [n-1]. So there is the base case for your recursion.
If you have a "combination" of length r-1, how can that be expanded to length r and keep the requirements? Look at the last element in the array of length r-1--let's call it k. The next element cannot be less than that, so all the possible arrays extended to length r are the r-1 array appended with k', 'k+1, ..., n-1. Those are n-k arrays of length r.
Is it clear how to code that? Note that you do not need to keep all the arrays of length r-1, you only need the count of how many arrays there are that end with the element 0 or 1 or ... n-1. That makes it convenient to code--not much memory is needed. In fact, things can be reduced further--I'll leave that to you.
Note that the interviewer probably did not want the code, he wanted your thought-process leading to the code to see the way you think. This is one way to think the problem through.

Matlab : Confusion over find() function

find() function returns the indices where the elements are non-zero. I tried with different array sizes but both give error :
In an assignment A(I) = B, the number of elements in B and I must be the same.
I am confused because when the array size is same, still I am getting this error.
This is just to understand what went wrong:
LEt,
Example 1: Same array size
A = [20;21;3;45;5;19;1;8;2;1];
B = A;
for i =1:length(B)
pos(i) = find(A == B(i));
end
I should have got pos = [1,2,3,4,5,6,7,8,9,10]. But the loops exits after i = 7, giving `pos = [1,2,3,4,5,6]'
Example 2: Dissimilar array size
C = [20;1;10;3];
for i =1:length(C)
pos(i) = find(A == C(i));
end
Can somebody please explain what is wrong in my understanding and an illustration of how I can work with same and different array length of A and B? Thank you.
The problem is that find(A == 1) returns two indexes, both 7 and 10, and that can't be stored in pos(i), since pos(i) can only hold a single number.
Unfortunately, the generic error message happened to have the same name for the matrices as two of your matrices, which can be confusing before you'we seen it a few times.

Matlab: creating 3D arrays as a function of 2D arrays

I want to create 3d arrays that are functions of 2d arrays and apply matrix operations on each of the 2D arrays. Right now I am using for loop to create a series of 2d arrays, as in the code below:
for i=1:50
F = [1 0 0; 0 i/10 0; 0 0 1];
B=F*F';
end
Is there a way to do this without the for loop? I tried things such as:
F(2,2) = 0:0.1:5;
and:
f=1:0.1:5;
F=[1 0 0; 0 f 0; 0 0 1];
to create them without the loop, but both give errors of dimension inconsistency.
I also want to perform matrix operations on F in my code, such as
B=F*F';
and want to plot certain components of F as a function of something else. Is it possible to completely eliminate the for loop in such a case?
If I understand what you want correctly, you want 50 2D matrices stacked into a 3D matrix where the middle entry varies from 1/10 to 50/10 = 5 in steps of 1/10. You almost have it correct. What you would need to do is first create a 3D matrix stack, then assign a 3D vector to the middle entry.
Something like this would do:
N = 50;
F = repmat(eye(3,3), [1 1 N]);
F(2,2,:) = (1:N)/10; %// This is 1/10 to 5 in steps of 1/10... or 0.1:0.1:5
First pre-allocate a matrix F that is the identity matrix for all slices, then replace the middle row and middle column of each slice with i/10 for i = 1, 2, ..., 50.
Therefore, to get the ith slice, simply do:
out = F(:,:,i);
Minor Note
I noticed that what you want to do in the end is a matrix multiplication of the 3D matrices. That operation is not defined in MATLAB nor anywhere in a linear algebra context. If you want to multiply each 2D slice independently, you'd be better off using a for loop. Doing this vectorized with native operations isn't supported in this context.
To do it in a loop, you'd do something like this for each slice:
B = zeros(size(F));
for ii = 1 : size(B,3)
B(:,:,ii) = F(:,:,ii)*F(:,:,ii).';
end
... however, examining the properties of your matrix, the only thing that varies is the middle entry. If you perform a matrix multiplication, all of the entries per slice are going to be the same... except for the middle, where the entry is simply itself squared. It doesn't matter if you multiple one slice by the transpose of the other. The transpose of the identity is still the identity.
If your matrices are going to be like this, you can just perform an element-wise multiplication with itself:
B = F.*F;
This will not work if F is anything else but what you have above.
Creating the matrix would be easy:
N = 50;
S = cell(1,N);
S(:) = {eye(3,3)};
F = cat(3, S{:});
F(2,2,:) = (1:N)/10;
Another (faster) way would be:
N = 50;
F = zeros(3,3,N);
F(1,1,:) = 1;
F(2,2,:) = (1:N)/10;
F(3,3,:) = 1;
You then can get the 3rd matrix (for example) by:
F(:,:,3)

Array is filled with undefined values (Erlang)

Updated Question; Original below.
I am trying to create an array which represents a grid of cells, which have tuples containing the walls they are surrounded by.
I have come up with this:
rooms(Array) ->
Size = array:size(Array),
if
Size == ?HSIZE * ?VSIZE ->
Array;
true ->
HFactor = Size rem ?VSIZE,
VFactor = Size div ?HSIZE,
Room = {1+HFactor+11*VFactor,
7+HFactor+11*VFactor,
12+HFactor+11*VFactor,
6+HFactor+11*VFactor},
rooms(array:set(Size, Room, Array))
end.
When I run this with rooms(array:new()). I get the following array back:
{array,25,100,undefined,
{{{1,7,12,6},
{2,8,13,7},
{3,9,14,8},
{4,10,15,9},
{5,11,16,10},
{12,18,23,17},
{13,19,24,18},
{14,20,25,19},
{15,21,26,20},
{16,22,27,21}},
{{23,29,34,28},
{24,30,35,29},
{25,31,36,30},
{26,32,37,31},
{27,33,38,32},
{34,40,45,39},
{35,41,46,40},
{36,42,47,41},
{37,43,48,42},
{38,44,49,43}},
{{45,51,56,50},
{46,52,57,51},
{47,53,58,52},
{48,54,59,53},
{49,55,60,54},
undefined,undefined,undefined,undefined,undefined},
10,10,10,10,10,10,10,10}}
Which is quite close to the desired result, but there are two things I can't quite put my finger on (The numbers are correct). Why does it look like it is split up into multiple subarrays? What are those undefineds and 10's doing there? These are mostly due to my lack of erlang knowledge, because array:get produces the expected results, but I couldn't find anything which explains where they come from.
Original Question
rooms(Array) ->
Size = array:size(Array),
if
Size == 5 ->
Array;
Size rem 5 == 0 ->
rooms(array:set(Size, array:new(), Array));
true ->
In_Array = array:get(array:size(Array), Array),
In_Size = array:size(In_Array),
Room = {1+In_Size+11*In_Size,
7+In_Size+11*In_Size,
12+In_Size+11*In_Size,
6+In_Size+11*In_Size},
New_In = array:set(In_Size, Room, In_Array),
rooms(array:set(Size, New_In, Array))
end.
I call it with rooms(array:new()). but the result is
** exception error: bad argument
in function array:size/1 (array.erl, line 317)
in call from framework_kamer:rooms/1 (framework_kamer.erl, line 195)
Which makes sense because In_Array is not an array, but undefined. However, I can't figure out why.
Side question, is there an easier/cleaner/better way to do this?
You are (in the second call of the recursion) trying
In_Array = array:get(array:size(Array), Array),
As array is zero-indexed this will always fail, as the access will be always be off by one. Change this line to
In_Array = array:get(array:size(Array) - 1, Array),
and you are fine.
A few comments on your code:
Conventional variable naming in Erlang would be CamelCase without underscores (i.e. InArray)
Expressing a 2-dimensional array as nested arrays is almost never a good idea. Linearalise it by writing simple wrappers that recalculate a one-dimensional index from x and y as index = y * max_x + x.

How to build an array by function handle

I am trying to produce something like this in MATLAB with function handle
f=#(x,y)(x(1)*x(2)+y);
c=[2 3 4;5 9 2];
h=[5 1 2];
f(c,h)
The answer should be:
15 11 12
But when I write this code below, it just builds a number not an array.
f=#(x)(x(1)*x(2))
f(c)
answer:
10
Can someone explain me where I went wrong?
I do not know what you expected here. The cause of the problem is quite clear.
a = 1;
b = 2;
c = [3 4];
d = a*b+c;
is a scalar + vector operation which always returns
ans = [a*b+c(1), a*b+c(2)];
however scalar*scalar which was the second case always returns a scalar. What you do is that you multiply the first matrix element of x (or c) with the second element. That is to say element c(1,1)*c(2,1) since matlab works columnwise. If you looks at your values you would probably notice the answer is incorrect as well, if you are trying to do what I think you are. You could try this instead,
f=#(x,y)(x(1,:).*x(2,:)+y);
c=[2 3 4;5 9 2];
h=[5 1 2];
f(c,h)
which multipies the elements on the first row of x with the same column on the second row and then adds y. An anonymous function takes a number of inputs and perform a defined operation, the same as ordinary functions or ordinary codes. You can see them as functions that does not require a call to another m file. The main differences (except that ordinary functions gives more freedom), are how they are handled by matlab and not in the syntax.

Resources