Ternary Tree Path List Matlab - matlab

I have created a ternary tree in matlab as below.
for i=1:4
a(i, j:j+2) = 1;
a(j:j+2, i) = 1;
j=j+3;
end
This code works fine and the numbering of the tree is in pre-order starting with Root Node as 1 and then the nodes are numbered as
1
---------------------------------------------------
2 3 4
---------------------------------------------------------
5 6 7 8 9 10 11 12 13
My question is how to write code that will get the paths
1 2 5, 1 2 6, 1 2 7 and similarly for the rest and save these paths to a file. I am doing some trial and error codes now.

Related

(KDB+/q) Get diagonal elements of a matrix

I want to get all the diagonal elements of a matrix in kdb+/q.
E.g.
q)A:(1 2 3; 4 5 6; 7 8 9)
q)A
1 2 3
4 5 6
7 8 9
would return 1 5 9
My idea is to use "." to get the elements.
q) A . 1 1 / one of the diagonal elements
5
q) 2 #' til 3 / indices
0 0
1 1
2 2
But I tried many ways and can't get it working.
Following code returns diagonal elements of matrix
(1 2 3; 4 5 6; 7 8 9) #' til 3
The code
generates continuous list 0, 1, 2 on the right
Gets an element from every list on the left by applying corresponding index on the right (#' adverb)
Generic form looks like:
getDiagonal: {x#'til count x};
getDiagonal (1 2 3; 4 5 6; 7 8 9)

Stem and leaf plot algorithm

I am trying to implement a stem and plot algorithm in MATLAB for educational purposes. Before I post my code, let me introduce what the steps of my approach are. Let us consider that we have two digit numbers:
A=[20 12 13 21 56 13 16 17 22 23 24];
Stems can be given by
stems=fix(A/10)
stems =
2 1 1 2 5 1 1 1 2 2 2
and leafs can be given by
leaf=fix(mod(A,10))
leaf =
0 2 3 1 6 3 6 7 2 3 4
What I have done, is to sort the stems and according to that sort leafs as well:
[stems, index]=sort(stems,'ascend')
leaf=leaf(index)
stems =
1 1 1 1 1 2 2 2 2 2 5
leaf =
2 3 3 6 7 0 1 2 3 4 6
This is the basic idea:
Count the frequency of occurrence of each number in stems
Take that many elements from leaf
Repeat this procedure for each stem, where at each step I am shortening the leaf array. So for instance for stems = 1, we have [5 1], so I will have
leaf(1:5)
ans =
2 3 3 6 7
leaf(1:5)=[]
leaf =
0 1 2 3 4 6
stems = 2 is again 5 times, so again:
leaf(1:5)
ans =
0 1 2 3 4
leaf(1:5)=[]
leaf =
6
Now for stems = 5, we have 1 leaf
leaf(1)
ans =
6
For this I used a map container and I have created the following code:
function stem_leaf_plot(v)
if ~isnumeric(v) % check that program will accept array as a integers
error( 'Input V must be numeric');
end
stems=fix(v/10);
leaf=fix(rem(v,10));
[stems, index]=sort(stems,'ascend');
leaf=leaf(index);
string_stems=num2str(stems);
%% count occurence of each stem
MAP=containers.Map();
n=length(stems); % total element of stems array
for ii=1:n
if isKey(MAP,string_stems(ii))
MAP(string_stems(ii))= MAP(string_stems(ii))+1;
else
MAP(string_stems(ii))=1;
end
end
MAP_count=length(MAP);
stem=num2str(cell2mat(keys(MAP)));
for jj=1:MAP_count
frequency=(MAP(string_stems(jj)));
fprintf('leafs of stem %d',stem(jj));
disp(leaf(1:frequency));
leaf(1:frequency)=[]; % delete elements step by step
end
end
However, the result of my code is
stem_leaf_plot(A)
leafs of stem 32 2 3 3 6
leafs of stem 49 7 0 1 2 3 4 6
What is wrong?
After suggestion of #Adriaan I used hist to count frequencies, instead of a container. Here is my updated code:
function stem_leaf_plot(v)
if ~isnumeric(v) % check that program will accept array as a integers
error( 'Input V must be numeric');
end
stems=fix(v/10);
leaf=fix(rem(v,10));
[stems, index]=sort(stems,'ascend');
leaf=leaf(index);
[a,b]=hist(stems,unique(stems));
n=length(a);
for ii=1:n
fprintf('leaf of stem %d is ',b(ii));
leaf(1:a(ii))
leaf(1:a(ii))=[];
end
>> A=[20 12 13 21 56 13 16 17 22 23 24];
>> stem_leaf_plot(A)
leaf of stem 1 is
ans =
2 3 3 6 7
leaf of stem 2 is
ans =
0 1 2 3 4
leaf of stem 5 is
ans =
6

for loop logic in matlab / octave incrementing

I have two lines where ii should increment 1:12
1 2 3 4 5 6 7 8 9 10 11 12
for ii=1:6
ii %line1
ii+1 %line2
end
Instead I get ii
1 2 2 3 3 4 4 5 5 6 6 7
Ps: I need to use two lines in the for loop due to functions being called from these lines and filenames are created based on ii variable
If you really need two lines, try:
for ii=1:6
ii*2-1
ii*2
end

Matlab: command to get counts of elements in a list

I need the counts of each element in the list. Is there some ready command for this?
>> [1 1 5 5 10 12 12 2 2 2]
ans =
1 1 5 5 10 12 12 2 2 2
Goal: getting counts like this
>> [1, 2; 5, 2; 10, 1; 12, 2]
ans =
1 2
2 3
5 2
10 1
12 2
I'm not sure if the formatting of the result is important to you, but the following link might come in handy. How can I count the occurrences of each element in a vector in MATLAB?
It's an answer to a similar question on the MathWorks website by their support team. They say there is no single function for it, but they provide 3 options.

matlab: dividing vector into overlapping chunks of fixed size

I've a vector that I would like to split into overlapping subvectors of size cs in shifts of sh. Imagine the input vector is:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
given a chunksize of 4 (cs=4) and shift of 2 (sh=2), the result should look like:
[1 2 3 4]
[3 4 5 6]
[5 6 7 8]
[7 8 9 10]
[9 10 11 12]
note that the input vector is not necessarily divisible by the chunksize and therefore some subvectors are discarded. Is there any fast way to compute that, without the need of using e.g. a for loop?
In a related post I found how to do that but when considering non-overlapping subvectors.
You can use the function bsxfun in the following manner:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;
A = v(bsxfun(#plus,(1:cs),(0:sh:length(v)-cs)'));
Here is how it works. bsxfun applies some basic functions on 2 arrays and performs some repmat-like if the sizes of inputs do not fit. In this case, I generate the indexes of the first chunk, and add the offset of each chunck. As one input is a row-vector and the other is a column-vector, the result is a matrix. Finally, when indexing a vector with a matrix, the result is a matrix, that is precisely what you expect.
And it is a one-liner, (almost) always fun :).
Do you have the signal processing toolbox? Then the command is buffer. First look at the bare output:
buffer(v, 4, 2)
ans =
0 1 3 5 7 9 11
0 2 4 6 8 10 12
1 3 5 7 9 11 13
2 4 6 8 10 12 0
That's clearly the right idea, with only a little tuning necessary to give you exactly the output you want:
[y z] = buffer(v, 4, 2, 'nodelay');
y.'
ans =
1 2 3 4
3 4 5 6
5 6 7 8
7 8 9 10
9 10 11 12
That said, consider leaving the vectors columnwise, as that better matches most use cases. For example, the mean of each window is just mean of the matrix, as columnwise is the default.
I suppose the simplest way is actually with a loop.
A vectorizes solution can be faster, but if the result is properly preallocated the loop should perform decently as well.
v = 1:13
cs = 4;
sh = 2;
myMat = NaN(floor((numel(v) - cs) / sh) + 1,cs);
count = 0;
for t = cs:sh:numel(v)
count = count+1;
myMat(count,:) = v(t-cs+1:t);
end
You can accomplish this with ndgrid:
>> v=1:13; cs=4; sh=2;
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1)
>> chunks = X+Y
chunks =
1 2 3 4
3 4 5 6
5 6 7 8
7 8 9 10
9 10 11 12
The nice thing about the second syntax of the colon operator (j:i:k) is that you don't have to calculate k exactly (e.g. 1:2:6 gives [1 3 5]) if you plan to discard the extra entries, as in this problem. It automatically goes to j+m*i, where m = fix((k-j)/i);
Different test:
>> v=1:14; cs=5; sh=2; % or v=1:15 or v=1:16
>> [Y,X]=ndgrid(1:(cs-sh):(numel(v)-cs+1),0:cs-1); chunks = X+Y
chunks =
1 2 3 4 5
4 5 6 7 8
7 8 9 10 11
10 11 12 13 14
And a new row will form with v=1:17. Does this handle all cases as needed?
What about this? First I generate the starting-indices based on cs and sh for slicing the single vectors out of the full-length vector, then I delete all indices for which idx+cs would exceed the vector length and then I'm slicing out the single sub-vectors via arrayfun and afterwards converting them into a matrix:
v=[1 2 3 4 5 6 7 8 9 10 11 12 13]; % A=[1:13]
cs=4;
sh=2;
idx = 1:(cs-sh):length(v);
idx = idx(idx+cs-1 <= length(v))
A = arrayfun(#(i) v(i:(i+cs-1)), idx, 'UniformOutput', false);
cell2mat(A')
E.g. for cs=5; sh=3; this would give:
idx =
1 3 5 7
ans =
1 2 3 4 5
3 4 5 6 7
5 6 7 8 9
7 8 9 10 11
Depending on where the values cs; sh come from, you'd probably want to introduce a simple error-check so that cs > 0; as well as sh < cs. sh < 0 would be possible theoretically if you'd want to leave some values out in between.
EDIT: Fixed a very small bug, should be running for different combinations of sh and cs now.