Find max value in multidimensional array recursively - c

I'm studying an algorithm to recursively find the highest value in a multidimensional array (of any size). But it is not working properly.
#include <stdio.h>
int N = 5;
int maxInRow(int matrix[][N], int row, int cols)
{
if (cols == 0){
return matrix[row][cols];
}
int maxCandidate = matrix[row][cols - 1];
int maxSublist = maxInRow(matrix, row, cols - 1);
int max = (maxSublist > maxCandidate) ? maxSublist : maxCandidate;
return max;
}
int main()
{
int mtx[5][5] = {{8,1,2,6,7}, {1,80,3,9,6}, {4,5,5,1,8}, {1,2,3,4,5}, {5,4,3,5,300}};
printf("%d\n", maxInRow(mtx, 1, N-1));
}
It should return 300, but it returns 80. Where am I going wrong?

What you have done is to find out maximum value of a particular row and NOT the max value of the multidimensional arrays. To get the maximum value of whole arrays , need to recursively compare all items of all the rows.
Here is one of the way to achieve this(code below)
#include <stdio.h>
int N = 5;
int maxInRow(int matrix[][N], int row, int cols)
{
if (cols == 0 ){
if(row==1) {
// the last element of the matrix
return matrix[0][0];
}
else{
// Comparing all items of row is done, begin next row
row--;
cols=N;
}
}
int maxCandidate = matrix[row-1][cols - 1];
int maxSublist = maxInRow(matrix, row, cols - 1);
int max = (maxSublist > maxCandidate) ? maxSublist : maxCandidate;
return max;
}
int main()
{
int mtx[5][5] = {{8,1,2,6,7}, {1,80,3,9,6}, {4,5,5,1,8}, {1,2,3,4,5}, {5,4,3,5,300}};
printf("%d\n", maxInRow(mtx, N, N));
}

Related

Using functions to lesser repetitiveness

I have been working on this problem for a while now: basically I need to put the for loop in a function so I can call for it, but I don't how to to make a function return a 2D array, I want to solve this by creating a 1D array, but the problem is that my task is to compute the sum of numbers under the diagonal of a matrix, so I need it to be 2D first, then it can only become 1D. Does anyone have a solution?
Maybe my thought process is just wrong and somebody could just recommend how to put the for loops in functions? If it was without the if clause inside then I might have an idea, but now I really don't.
#include <math.h>
#include <stdio.h>
#include <stdlib.h> // libraries added from example
#include <time.h>
//(*) For a square matrix calculate the sum of elements under the main diagonal excluding it.
#define A -10
#define B 10
int main() {
void enter(int *x, int *y);
int get_random(int lbound, int ubound); // telling the programs that functions are declared
int r;
int c;
int row, col, sum = 0;
enter(&r, &c); // calling the function
srand48(time(NULL)); //Call srand48 with current time reported by `time` casted to a long integer.
// srand48 is used to reinitialize the most recent 48-bit value in this storage
int array[r][c]; // we decided its gonna be r rows and c columns
int line[r * c]; // turning 2d into 1d array
for (row = 0; row < r; ++row) // we cycle numeration of rows of matrix
{
for (col = 0; col < c; col++) // we cycle numeration of columns of matrix
{
array[row][col] = get_random(B, A);// filling array with random numbers, taken from example
printf("%d ", array[row][col]);
if (row > col) { //since we want the sum numbers below the diagonal row>col must be true
sum = sum + array[row][col];// if row>col then we add the number to our sum;
};
}
printf("\n"); // this is to break line after row 1,2 col 3, so it looks nicer
}
for (row = 0; row < r; ++row) // we cycle numeration of rows of matrix
{
for (col = 0; col < c; col++) // we cycle numeration of columns of matrix
{
line[row * r + col] = array[row][col];
}
}
printf("the array in 1D: ");
for (row = 0; row < r * c; row++) {
printf("%d ", line[row]);
}
printf("\n");
printf("sum of array below the diagonal: %d\n", sum);
return 0;
}
void enter(int *x, int *y) { // we have to use pointers if we want more then one return from a function
printf("How man rows in array? "); // just like the last lab we decide how big the matrix will be
scanf("%d", x); // we use x instead of &x because we need the address of the number not the value
printf("How man columns in array? ");
scanf("%d", y); // we use y instead of &y because we need the address of the number not the value
}
int get_random(int lbound, int ubound) {
return mrand48() % (ubound - lbound + 1) + lbound; // function for generating random numbers
}
Conditions have to be met:
the user decides size of square matrix
the matrix has to be filled with random numbers
the array is called by the function has to be 1D using i*N+j, 2D array can't be passed
Let's consider your assignment
Conditions have to be met:
the user decides size of square matrix
the matrix has to be filled with random numbers
the array is called by the function has to be 1D using i*N+j, 2D
array can't be passed
Firstly the matrix must be square.
So this your function
void enter(int *x, int *y) { // we have to use pointers if we want more then one return from a function
printf("How man rows in array? "); // just like the last lab we decide how big the matrix will be
scanf("%d", x); // we use x instead of &x because we need the address of the number not the value
printf("How man columns in array? ");
scanf("%d", y); // we use y instead of &y because we need the address of the number not the value
}
does not make sense. The user can enter different values for the numbers of rows and columns of the matrix. You need to enter only one positive value.
Secondly as we are speaking about a matrix then it means that you have to define a two-dimensional array.
Also you need to write a function that will calculate the sum of elements under the main diagonal of a matrix. The function is declared such a way that it can accept only a one-dimensional array. This means that you need to pass your matrix to the function casting it to a pointer of the type int *. There is no need to create an auxiliary one-dimensional array,
Here is a demonstration program that shows how the function can be declared and defined and how the matrix can be passed to the function.
#include <stdio.h>
long long int sum_under_dioganal( const int a[], size_t n )
{
long long int sum = 0;
for (size_t i = 1; i < n; i++)
{
for (size_t j = 0; j < i; j++)
{
sum += a[i * n + j];
}
}
return sum;
}
int main( void )
{
enum { N = 5 };
int a[N][N] =
{
{ 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0 },
{ 2, 3, 0, 0, 0 },
{ 4, 5, 6, 0, 0 },
{ 7, 8, 9, 10, 0 }
};
printf( "sum of elements under the main diagonal = %lld\n",
sum_under_dioganal( ( int * )a, N ) );
}
The program output is
sum of elements under the main diagonal = 55
Another approach to define the function and call it is the following
#include <stdio.h>
long long int sum_under_dioganal( const int a[], size_t n )
{
long long int sum = 0;
size_t m = 0;
while (m * m < n) ++m;
if (m * m == n)
{
for (size_t i = 1; i < m; i++)
{
for (size_t j = 0; j < i; j++)
{
sum += a[i * m + j];
}
}
}
return sum;
}
int main( void )
{
enum { N = 5 };
int a[N][N] =
{
{ 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 0 },
{ 2, 3, 0, 0, 0 },
{ 4, 5, 6, 0, 0 },
{ 7, 8, 9, 10, 0 }
};
printf( "sum of elements under the main diagonal = %lld\n",
sum_under_dioganal( ( int * )a, N * N ) );
}
The program output is the same as shown above.
sum of elements under the main diagonal = 55
2d arrays don't really exist. The compiler just allows you to write a[i][j] so that you can believe in them. Here's some simple code to demonstrate a few methods:
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
void *
make_array(size_t size)
{
int *a = malloc(sizeof *a * size * size);
int *t = a;
if( a == NULL ){
perror("malloc");
exit(1);
}
for( int row = 0; row < size; row += 1 ){
for( int col = 0; col < size; col += 1 ){
*t++ = rand() % 32 - 16;
}
}
return a;
}
int
trace(void *v, size_t s)
{
int *a = v;
int sum = 0;
for( size_t i = 0; i < s; i += 1 ){
sum += *a;
a += s + 1;
}
return sum;
}
int
main(int argc, char **argv)
{
srand(time(NULL));
size_t s = argc > 1 ? strtol(argv[1], NULL, 0) : 5;
void *v = make_array(s);
/* a, b, c, and d will demonstrate different access techniques */
int *a = v; /* a is the conventional "1-d array" (1)*/
int (*b)[s] = v; /* b is a "two-d" array */
int *c = v; /* c iterates through each element */
int *d = v; /* d treats each row as a 1-d array */
for( int i = 0; i < s; i += 1 ){
for( int j = 0; j < s; j += 1 ){
printf("%3d ", b[i][j]);
assert( a[i * s + j] == b[i][j] );
assert( *c == b[i][j] );
assert( d[j] == b[i][j] );
c += 1;
}
d += s;
putchar('\n');
}
printf("trace: %d\n", trace(v, s));
}
/* (1) These comments are not strictly accurate. `a` is *not* an
* array, and `b` is *not* a 2-d array. `a` is a pointer, and `b` is
* an array of pointers. Arrays are not pointers, and pointers are
* not arrays.
*/

Dynamically 2D array in C using the single pointer:

I'm trying to dynamically allocate memory to a 2d array using a single pointer. For that, I have 3 functions that allocate the respective memory newarray() and to store individual elements in it store(), to fetch elements from it fetch(). I don't know why I get execution errors while I test it, also I should allocate the the exact amount of memory for it, that might be the problem but I'm not sure how to do that. This probrams deals with a triangular matrix which should have the number of columns lower than the number of rows when It comes to adding elements, like I, have a 5x5 array where (4,2) and (4,4) its OK but (4,5) its NOT.
Here is the code
typedef int* triangular;
triangular newarray(int N){
triangular mat = NULL; //pointer to integer
//Allocate memory for row
mat = (int *)malloc(N * N * sizeof(int));
//Check memory validity
if(mat == NULL)
{
return 1;
}
return mat;
}
int store(triangular as, int N, int row, int col, int val){
if(row >= col){
as[row * N + col] = val;
return 1;
}else if(row < col){
return -1;
}else if((row > N) ||(col > N) || (row + col > N + N))
return -1;
}
int fetch(triangular as, int N, int row, int col){
int value;
value = as[row * N + col];
if((row > N) ||(col > N) || (row + col > N + N) )
return -1;
else if(row < col)
return -1;
return value;
}
nt main()
{
int iRow = 0; //Variable for looping Row
int iCol = 0; //Variable for looping column
int N;
triangular mat = newarray(5);
printf("\nEnter the number of rows and columns = ");
scanf("%d",&N); //Get input for number of Row
store(mat,N,3,2,10);
store(mat,N,3,3,10);
store(mat,N,4,2,111);
store(mat,N,3,5,11);
printf("the element at [3,5] is : %i", fetch(mat,N,3,5));
//Print the content of 2D array
for (iRow =0 ; iRow < N ; iRow++)
{
for (iCol =0 ; iCol < N ; iCol++)
{
printf("\nmat[%d][%d] = %d\n",iRow, iCol,mat[iRow * N + iCol]);
}
}
//free the allocated memory
free(mat);
return 0;
}
int store(triangular as, int N, int row, int col, int val){
if(row >= col){
as[row * N + col] = val;
return 1;
}else if(row < col){
return -1;
}else if((row > N) ||(col > N) || (row + col > N + N))
return -1;
}
in store function, first if condition is so weird. Why you dont set the value to the array when the parameters passed to function is 2(row), 3(column).
I changed your store in the following way. index and array size are different things because of that index is equal to N - 1. In your code, there are a lot of if checks I guess checking only row and col is enough to understand that they are inside boundaries.
int store(triangular as, int N, int row, int col, int val){
int index = N - 1;
if((row > N) ||(col > N))
return -1;
as[row * index + col] = val;
return 1;
}
I changed your fetch function like below because the reason I mentioned about your store function.
int fetch(triangular as, int N, int row, int col){
int value;
int index = N - 1;
if((row > index) ||(col > index))
return -1;
value = as[row * index + col];
return value;
}
You are making this needlessly complicated. All those functions and manual run-time calculations aren't really necessary.
Also, you have the following problems:
Don't hide pointers behind typedef, it just makes the code unreadable for no gain.
Initialize the data returned from malloc or instead use calloc which sets everything to zero, unlike malloc.
Arrays in C are zero-indexed so you can't access item [3][5] in an array of size 5x5. This is a common beginner problem since int array[5][5]; declares such an array but array[5][5] for index accessing goes out of bounds. The syntax for declaration and access isn't the same, access needs to start at 0.
You didn't include any headers, I'm assuming you left that part out.
Here's a simplified version with bug fixes that you can use:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int N=5;
int (*mat)[N] = calloc( 1, sizeof(int[N][N]) ); // allocate 2D array dynamically
if(mat == NULL)
return 0;
mat[3][2] = 10;
mat[3][3] = 10;
mat[4][2] = 111;
mat[3][4] = 11;
for(int i=0; i<N; i++)
{
for(int j=0; j<N; j++)
{
printf("[%d][%d] = %d\n", i, j, mat[i][j]);
}
}
free(mat);
return 0;
}
Further study: Correctly allocating multi-dimensional arrays

add and remove elements from an array

i m working on this small C program to fill an array, insert and remove elements from an array and finally printing that array.
The program consists of a main() function, the addToArray() function,
remFromArray() function and the printArray() function.
here's my main method:
which prompts the user for a sequence of positive integers
• for each integer entered by the user, call the addToArray function to insert the integer into the array
• call the printArray function to print out the content of the array.
NOTE:do not prompt the user for the number of integers to be entered; you must accept input until the user enters a negative number
#include <stdio.h>
#define maxSize 100 //maxSize for array
int addToArray(int* arr, int size, int numToAdd);
int remFromArray(int* arr, int size, int numToGo);
void printArray(int* arr, int size);
int main (void){
int arr[maxSize];
int i, j;
printf("Enter a positive integer to add to an array\n");
while (i >= 0 ){
scanf("%d",&i);
if (i >= 0 ) {
addToArray(arr, maxSize, i);
printf("Enter another positive integer for array\n");
}
else{
printArray(arr, maxSize);
}
}
}
these are my other function that i created:
addToArray() =>
/*find the correct index in the array where to insert the
new element, so array in ascending order
- make room for the new element by moving other elements
- store the new element at the correct index
- return the new size (number of elements) of the array */
int addToArray(int* arr, int size, int numToAdd){
int i, n, m, pos;
for (int i = 0; i < maxSize; i++)
{
if (numToAdd < arr[i])
{
pos = i;
break;
}
if (numToAdd > arr[n-1])
{
pos = maxSize;
break;
}
}
if (pos != maxSize)
{
m = maxSize - pos + 1 ;
for (int i = 0; i <= m; i++)
{
arr[maxSize - i + 2] = arr[maxSize - i + 1] ;
}
}
arr[pos] = numToAdd;
}
void printArray(int* arr, int size){
printf("Resultant array is\n");
for (int c = 0; c <= maxSize; c++){
printf("%d\n", arr[c]);
}
}
as you can see I've tried writing the main(), addToArray(), printArray(), but for some reason its not working right. my printArray() is not displaying the desired result.
I'll be glad if you could look at this code and guide me through it.
thanks a million
First, you don't set values to the variables you create. For exemple, all of those int i, n, m, pos; have indeterminate values, not 0 as you might expect. Don't forget to asign them a value before using to avoid bad surprises.
Second, be carefull about indexes of your array. For example, arr[maxSize - i + 2], when i == 0, then the index will be maxSize + 2, witch is invalid position and can lead to segmentation fault.

Find the maximum value in a 2D matrix (recursively)

I'm struggling to find the error in my code, I'm trying to find the maximum value in my 2D matrix, in a certain row. Can you help me locate where my logic fails?
int maxInRowmaxInRow(int mtx[][N], int row, int cols);
int main()
{
int mtx[][N] = { {8,1,2,6,7},{1,8,3,9,6},{4,5,-5,1,8},{1,2,3,4,5},{5,4,3,5,3} };
printf("%d", maxInRow(mtx, 1,N));
getch();
}
int maxInRow(int mtx[][N], int row, int cols)
{
int possibleMax = maxInRow(mtx, row, cols - 1);
if (cols == 0) return mtx[row][cols];
int max = mtx[row][cols - 1];
max = (max < maxInRow(mtx, row, cols - 1)) ? possibleMax : max;
return max;
}
You're doing the recursion termination case in the wrong order. You're also do two recursions instead of one. Simplifying your code:
int maxInRow(int mtx[][N], int row, int cols)
{
if (cols == 0) return mtx[row][cols];
int possibleMax = mtx[row][cols - 1];
int sublistMax = maxInRow(mtx, row, cols - 1);
int max = (sublistMax > possibleMax) ? sublistMax : possibleMax;
return max;
}
int main()
{
int mtx[][N] = {{8,1,2,6,7}, {1,8,3,9,6}, {4,5,-5,1,8}, {1,2,3,4,5}, {5,4,3,5,3}};
printf("%d\n", maxInRow(mtx, 1, N));
}

Shorter way to get 5 highest and 5 lowest values without changing the stack

So here is my code . I am trying to find a short way to make this programme work withouth changing any of the arregment.I have been tought the buble way i think its called to arrange a group from highest to lowest but it clearly say in my given orders not to change the entire group.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int randomInRange (unsigned int min, unsigned int max)
{
//srand(time(NULL));
int base_random = rand();
if (RAND_MAX == base_random) return randomInRange(min, max);
int range = max + 1 - min,
remainder = RAND_MAX % range,
bucket = RAND_MAX / range;
if (base_random < RAND_MAX - remainder) {
return min + base_random/bucket;
} else {
return randomInRange (min, max);
}
}
int main()
{
int ari,i,min,max;
printf("Gi'me length of the group")
scanf("%d",&ari);
int pinakas[ari];
printf("Gi'me lowest and highest values");
scanf("%d",&min);
scanf("%d",&max);
for(i = 0; i < ari; i++)
{
pinakas[ari] = randomInRange(min,max);
}
int el,meg,c;
el = max+1;
meg = min-1;
c = 0;
printf("Highest Lowest");
while( c != 4;)
{
for(i = 0; i < ari; i++)
{
if(el > pinakas[ari])
{
el = pinakas[ari];
}
if( meg < pinakas[ari])
{
meg = pinakas[ari];
}
if(i == 4)
{
printf("%d %d",el,meg);
( is there something that i can put here is order to make el,meg to go for the second lowest ,second highest? and so on till i get the 5 highest and 5 lowests.Keep in mind the the lowest length of my group will be pinakas[5].)
}
}
c++;
}
For each item in the array, up to 5 comparisons are done for the min list and 5 for the max list.
Suggest calling a function to do this in a tidy fashion.
#include<assert.h>
// `list` is `const` as OP says "withouth changing any of the arregment".
void sort_ends(const int *list, size_t listlen, int *minlist, int *maxlist,
size_t mlen) {
assert(list);
assert(minlist);
assert(maxlist);
assert(mlen >= 1);
assert(listlen >= mlen);
minlist[0] = list[0];
// For each element after the first ...
for (size_t i = 1; i < listlen; i++) {
int mincandidate = list[i];
size_t mini = i;
if (mini > mlen) mini = mlen;
do {
mini--;
if (mincandidate >= minlist[mini])
break;
// swap mincandidate and minlist[mini]
int t = mincandidate;
mincandidate = minlist[mini];
minlist[mini] = t;
} while (mini > 0);
}
// Do similar for maxlist, left for OP
}
int main() {
int ari;
// ...
int pinakas[ari];
// ...
int mlen = 5;
int minlist[mlen];
int maxlist[mlen];
sort_ends(pinakas, ari, minlist, maxlist, mlen);
return 0;
}
Alternative approach, find min index and then memove().

Resources