Matlab Recursion Not Working as Intended - arrays

So I'm trying to write some pretty basic code to essentially create an array of random numbers, based on certain rules. My end goal is to try to have an array of numbers, in which none of them match one another. However, it seems like the end array that my code is outputting has numbers that match, and I can't seem to figure out why.
I've pasted a sample output below, and as you can see, some of the numbers in the 'Totals' array match. I'm guessing something is wrong with the way I wrote the recursive 'addboard' function, but I have no clue what's wrong. If anyone could provide some advice, that'd be great. Thanks.
function [Components,Totals] = BoardForm1()
BoardLengths = [4,6,8,10,12];
Initial = [0,1,2,3,4,5,6,7];
Components = zeros(8,14);
Totals = zeros(8,14);
for i=1:14
for row = 1:length(Initial)
[currentboard,test] = addboard(row,BoardLengths,Initial,Totals);
Initial(row) = test;
Components(row,i) = currentboard
Totals(row,i) = test
end
end
end
function [currentboard,test] = addboard(x,BoardLengths,Initial,Totals)
currentboard = BoardLengths(randi(length(BoardLengths)));
test = Initial(x) + currentboard;
if ismember(test,Totals)
addboard(x,BoardLengths,Initial,Totals);
end
end
Totals =
12 16 28 34 44 56 68 76 84 94 106 114 118 128
13 25 35 39 43 49 53 61 65 75 83 91 95 103
6 18 22 34 42 50 54 66 72 82 86 92 104 112
15 23 35 41 51 57 63 69 73 81 87 99 105 111
14 26 36 48 58 68 80 90 100 104 108 114 120 130
9 13 23 27 31 37 43 49 55 61 65 75 87 91
12 24 34 42 46 54 60 64 72 76 82 88 92 96
19 29 33 39 47 57 69 77 83 89 101 109 119 125

MATLAB passes by value, so any changes made in the recursed addboard is ignored since its output values are ignored. Fix by setting the output values of [currentboard, test] = addboard
In general, I recommend doing this iteratively (while loop) instead of recursively. There may even be a one-liner that can do this, but I'm not sure from the comments what the requirements of the board are.

I am unable to understand your code, maybe some comments what the functions are supposed to do would be helpful, but just on a formal level reading the code there is at least one error in these lines:
if ismember(test,Totals)
addboard(x,BoardLengths,Initial,Totals);
end
You are calling addboard without output arguments which has no effect. It should probably be:
if ismember(test,Totals)
[currentboard,test] = addboard(x,BoardLengths,Initial,Totals);
end

Related

Matlab colon in getting all values of array have different pattern value as compare to without colon

I have created an array in Matlab and am facing an issue that when I ask to show all value of array not using colon, e.g., allfriendsmarks=m(), the result is:
allfriendsmarks =
45 65 57 86 49 56 99 87 67 60
But when I use a colon, allfriendsmarks=m(:) results in:
allfriendsmarks =
45
65
57
86
49
56
99
87
67
60
Why do both methods return a different result?

Insertion sort algorithm, weird behaviour

I am learning C programming and I'm currently on a classic one, the insertion sort algorithm.
For contextualization, I have a set of 3 arrays to test on :
the first one which is disordered
the second one is in a descending order
and the last one is is the ordered one but with a swap between 2 elements.
Here is my code :
int insertionSort(int* tab, int n){
int i;
for (i=1; i<n; i++){
int j = i;
while(tab[j] < tab[j-1]) {
swap(&tab[j-1], &tab[j]);
j-=1;
}
}
affiche(tab, n);
return 0;
}
For the 2 last arrays, it works fine.
But for the first one I got :
6 6 7 8 10 32521 14 15 17 19 20 21 23 25 26 28 28 28 32 32 34 35 38 38 39 43 44 46 48 49 50 58 59 62 64 65 69 71 75 79 79 79 81 84 86 89 92 93 97 99
instead of
3 6 6 7 8 10 14 15 17 19 20 21 23 25 26 28 28 28 32 32 34 35 38 38 39 43 44 46 48 49 50 58 59 62 64 65 69 71 75 79 79 79 81 84 86 89 92 93 97 99
As you can see, the algorithm works fine for a big part of the array, but for the sixth minimal values, I have random values (sometimes there are 92,93,97... for the first ones).
I don't have any core dump, which means that I am in the array's space in memory, but some values like 32521 let me think that my index j goes too far in memory.
Frankly, I don't see where the problem is.
Look at this loop
while(tab[j] < tab[j-1]) {
swap(&tab[j-1], &tab[j]);
j-=1;
}
j can run happily all over the place. There needs to be something that detects that j isnt < 0 (actually < 1 since you access 'tab[j-1]')
maybe
while((j >= 1) && (tab[j] < tab[j-1]) ) {
swap(&tab[j-1], &tab[j]);
j-=1;
}

How to copy an array

I have defined an array like this:
uint8_t brightnessvariants[4][101]={{1,2,...},{3,4,...},{5,6,...},{7,8,...}};
Now for my application i have to fill another array with one of the 4 arrays:
uint8_t brightnesstable[] = brightnessvariants[index][];
But that doesn't work. Index is counted from 0 to 3.
brightnesstable and brightnessvariants are defined in a header file as extern
How can I do it right?
Simply do
uint8_t brightnesstable[101];
memcpy(brightnessstable, brightnessvariants[index], 101*sizeof(uint8_t));
brightnessvariants[index] is the address of the first item in the (index+1)nth row and the number of bytes you want to copy is
ROWSIZE*sizeof(ITEM_SIZE).
It really depends on what you need to do. If you need to create separate storage for a duplication of one of the rows of brightnessvariants, then you can simply declare a separate array and copy the values as discussed in the comments and the other answer.
If, however, you simply need to access one of the rows of brightnessvariants in the current scope, then there is no need for separate storage and copying. All that is required is to declare a pointer and assign the starting address of the desired row. Then you can access the desired row of brightnessvariants as if it were a separate array. e.g.
uint8_t brightnessvariants[4][101] = {{0}}, *btable = NULL;
Above, btable (short for your brightnesstable) is simply a uint8_t pointer. It can be assigned the the address of any of the rows in brightnessvariants. e.g. for the second row
btable = brightnessvariants[1];
btable can then be used to access any value within the second row, just as if it were a separate array. Here is a short example that may help:
#include <stdio.h>
#include <stdint.h>
int main (void) {
uint8_t brightnessvariants[4][101] = {{0}}, *btable = NULL;
int nrows = sizeof brightnessvariants / sizeof *brightnessvariants;
for (int i = 0; i < 101; i++) {
brightnessvariants[0][i] = i + 1;
brightnessvariants[1][i] = i + 3;
brightnessvariants[2][i] = i + 5;
brightnessvariants[3][i] = i + 7;
}
for (int i = 0; i < nrows; i++) {
printf ("\nbrightnesstable[%d] :\n\n", i);
btable = brightnessvariants[i];
for (int j = 0; j < 101; j++) {
if (j && j % 10 == 0) putchar ('\n');
printf (" %3hhu", btable[j]);
}
putchar ('\n');
}
return 0;
}
Example Use/Output
$ ./bin/ptrtobtable
brightnesstable[0] :
1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 17 18 19 20
21 22 23 24 25 26 27 28 29 30
31 32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49 50
51 52 53 54 55 56 57 58 59 60
61 62 63 64 65 66 67 68 69 70
71 72 73 74 75 76 77 78 79 80
81 82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99 100
101
brightnesstable[1] :
3 4 5 6 7 8 9 10 11 12
13 14 15 16 17 18 19 20 21 22
23 24 25 26 27 28 29 30 31 32
33 34 35 36 37 38 39 40 41 42
43 44 45 46 47 48 49 50 51 52
53 54 55 56 57 58 59 60 61 62
63 64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81 82
83 84 85 86 87 88 89 90 91 92
93 94 95 96 97 98 99 100 101 102
103
brightnesstable[2] :
5 6 7 8 9 10 11 12 13 14
15 16 17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 32 33 34
35 36 37 38 39 40 41 42 43 44
45 46 47 48 49 50 51 52 53 54
55 56 57 58 59 60 61 62 63 64
65 66 67 68 69 70 71 72 73 74
75 76 77 78 79 80 81 82 83 84
85 86 87 88 89 90 91 92 93 94
95 96 97 98 99 100 101 102 103 104
105
brightnesstable[3] :
7 8 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24 25 26
27 28 29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45 46
47 48 49 50 51 52 53 54 55 56
57 58 59 60 61 62 63 64 65 66
67 68 69 70 71 72 73 74 75 76
77 78 79 80 81 82 83 84 85 86
87 88 89 90 91 92 93 94 95 96
97 98 99 100 101 102 103 104 105 106
107
Look things over and let me know if you have any questions. If you need an example of copying instead of the use of a pointer, let me know and I'm happy to help.

Count frequency of each row in an array using Matlab

I have this huge array. I extracted the unique rows in a separate array. Now I would like to create a vector in which to store the occurrences of each unique row. How could I do that? Tried using histc. I found about tabulate, but only works on vectors.
x=[62 29 64
63 32 61
63 32 61
63 32 61
63 31 62
62 29 64
62 29 64
65 29 60
62 29 64
63 32 61
63 32 61
63 29 62
63 32 61
62 29 64
];
uA=unique(x)
[row, count] = histc(x,unique(x,'rows'))
I get the following error: Edge vector must be monotonically non-decreasing. Also encountered this error in a couple of other attempts.
Use unique this way -
[unique_rows,~,ind] = unique(x,'rows')
counts = histc(ind,unique(ind))
unqiue_rows and counts would be the outputs you might be interested in.
With your given data it yields -
unique_rows =
62 29 64
63 29 62
63 31 62
63 32 61
65 29 60
counts =
5
1
1
6
1
Bonus: You can improve on performance by avoiding the second use of unique this way -
counts = histc(ind,1:max(ind));

Runtime error in codechef practice questions

I'm getting "sigsegv" , a runtime error from the following code when i try to run it on codechef while the code works fine on my computer with various test inputs.I've also kept in mind the constraints given in the problem but I'm still unable to debug it. The question is not from any contest but a practice problem . Please point out any mistake you can find .
Actual codechef question
#include<stdio.h>
int cash[101][101]={0};
int rec[101][2];
int ri=0;
int sumx(int mat[101][101],int i,int j,int lines)
{
int n=0,a=0,b=0;
if(cash[i][j]!=0)
{
return cash[i][j];
}
else if(i==lines-2)
{
n=(mat[i+1][j]>mat[i+1][j+1])?mat[i+1][j]:mat[i+1][j+1];
cash[i][j]=n+mat[i][j];
rec[ri][0]=i;
rec[ri++][1]=j;
return n+mat[i][j];
}
else
{
a=sumx(mat,i+1,j,lines);
b=sumx(mat,i+1,j+1,lines);
n=(a>b)?a:b;
cash[i][j]=n+mat[i][j];
rec[ri][0]=i;
rec[ri++][1]=j;
return n+mat[i][j];
}
}
int main()
{
int i=0,k=0;
int lines=0,n=0;
int r=0;
int tc=0;
int mat[101][101];
scanf("%d",&tc);
while(tc--)
{
scanf("%d",&lines);
i=0;
k=0;
while(i<lines)
{
while(k<=i)
{
scanf("%d",&mat[i][k]);
k++;
}
k=0;
i++;
}
if(lines==1)
{
r=mat[0][0];
}
else
{
r=sumx(mat,0,0,lines);
}
i=0;
while(i<ri)
{
cash[(rec[i][0])][(rec[i][1])]=0;
rec[i][0]=0;
rec[i][1]=0;
i++;
}
ri=0;
printf("%d\n",r);
}
return 0;
}
The error is with lines
while(i<ri)
{
cash[(rec[i][0])][(rec[i][1])]=0;
rec[i][0]=0;
rec[i][1]=0;
i++;
}
the values of rec[i][0] rec[i][1] can be undefined in some cases ie they may return garbage values
You can Use memset instead to change the values to 0
memset(rec,0,sizeof(rec));
memset(cash,0,sizeof(cash));
I ran your solution , there's a bug in your algorithm implementation try finding it yourself
I can provide you a test case(using a testcase generator) for which it fails
21
79
89 28
14 6 63
96 58 67 48
80 8 22 27 8
24 21 23 96 97 72
38 90 95 83 57 60 94
13 96 9 24 65 27 67 40
26 20 58 42 29 8 52 49 37
80 65 65 34 79 10 89 11 20 84
57 59 72 79 51 67 84 70 43 62 96
16 4 18 9 5 40 34 2 15 4 28 50
29 1 60 39 28 92 38 65 95 57 10 71 37
25 78 96 43 17 51 88 19 0 30 20 80 39 35
55 41 63 76 4 20 97 72 43 93 76 11 82 33 25
61 85 41 77 42 90 20 5 69 51 4 54 41 18 83 72
12 56 21 82 7 1 84 26 47 26 22 52 84 39 75 70 89
12 39 83 92 49 20 35 20 31 96 66 75 48 79 13 51 49 50
42 81 0 58 70 40 16 83 27 34 79 64 14 26 19 22 38 55 93
64 81 26 29 47 22 73 61 3 2 61 99 18 43 33 10 13 46 24 53
5 56 0 0 3 0 71 12 82 34 17 11 14 51 1 82 73 53 85 75 89
correct answer is 1431 while your code returns 1299
#Randomizer : The code runs fine with the output as 1431 , not 1299 . Anyways , as you suggested about the garbage being generated from rec[i][0] rec[i][1], It never appeared to me that rec[i][0] rec[i][1] could be generating garbage as I only accessed the used up cells . However , memset eliminated the need of rec , so cash was easily reset to zero . All i did was remove the rec matrix and reset cash using memset and the code ran fine on codechef. I couldn't figure out how it could be generating garbage , still , its accepted on codechef since I removed rec part . Thank you for the help.

Resources