How to store multiple 2D array locations in C? - c

I'm trying to make a simple program, that generates random numbers into a 15x15 2D array and then works with the array later on.
This function finds the largest value in the array and then prints out the value and its location.
void maxValue(int array[ROWS][COLUMNS]){
int maxNum = array[0][0];
int rowMaxLocation;
int columnMaxLocation;
for(int c = 0; c < ROWS; c++) {
for(int d = 0; d < COLUMNS; d++) {
if(maxNum < array[c][d]) {
maxNum = array[c][d];
rowMaxLocation = c;
columnMaxLocation = d;
}
}
}
printf("Largest value in the array is %d, located in [%d][%d]", maxNum, rowMaxLocation, columnMaxLocation);
return;
What I can't figure out is how to store multiple locations of the same maximal value, e.g. "Largest value in the array is 99, located in [1][3] and [5][12]".
Thanks in advance.

you can follow a two pass approach:
First pass: Find maximum element in array
Second pass: Find all indices where array value is equal to maximum element
In order to store multiple locations you can have arrays of rowMaxLocations[] or columnMaxLocations[] and store values in them accordingly as you scan the array during second pass. If you don't need these values, you can simply skip storing them in some array and just do printing in second pass as well.
I would recommend having a Location struct for storing location values like this:
typedef struct Location {
int row;
int column;
} Location;
Here is how this two pass approach would look like:
void maxValue(int array[ROWS][COLUMNS]){
int maxNum = array[0][0];
// Array of locations to store max locations
Location maxLocations[ROWS * COLUMNS];
// Index of max locations array
int maxLocationIndex = 0;
// First pass; Get Max value
for(int c = 0; c < ROWS; c++) {
for(int d = 0; d < COLUMNS; d++) {
if(maxNum < array[c][d]) {
maxNum = array[c][d];
}
}
}
// Seconds pass; Get all values equal to max value
for (int c = 0; c < ROWS; c++) {
for (int d = 0; d < COLUMNS; d++) {
if (array[c][d] == maxNum) {
maxLocations[maxLocationIndex].row = c;
maxLocations[maxLocationIndex].column = d;
maxLocationIndex++;
}
}
}
// Print the max locations array
printf("Largest value in the array is %d\n", maxNum);
for (int i = 0; i < maxLocationIndex; i++) {
printf("[%d][%d] \n", maxLocations[i].row, maxLocations[i].column);
}
}
Update:
Thanks to suggestion from #Ian Abbott, there is also a way to do all this in one pass. We would just need to reset the maxLocationIndex whenever we find a new max value:
for(int c = 0; c < ROWS; c++) {
for(int d = 0; d < COLUMNS; d++) {
if(maxNum < array[c][d]) {
maxNum = array[c][d];
// Reset Max locations index
maxLocationIndex = 0;
}
if (array[c][d] == maxNum) {
maxLocations[maxLocationIndex].row = c;
maxLocations[maxLocationIndex].column = d;
maxLocationIndex++;
}
}
}

Related

Sorting integers by sum of their digits

I'm trying to write a program that will sort an array of 20 random numbers by the sums of their digits.
For example:
"5 > 11" because 5 > 1+1 (5 > 2).
I managed to sort the sums but is it possible to return to the original numbers or do it other way?
#include <stdio.h>
void sortujTab(int tab[], int size){
int sum,i;
for(int i=0;i<size;i++)
{
while(tab[i]>0){//sum as added digits of an integer
int p=tab[i]%10;
sum=sum+p;
tab[i]/=10;
}
tab[i]=sum;
sum=0;
}
for(int i=0;i<size;i++)//print of unsorted sums
{
printf("%d,",tab[i]);
}
printf("\n");
for(int i=0;i<size;i++)//sorting sums
for(int j=i+1;j<=size;j++)
{
if(tab[i]>tab[j]){
int temp=tab[j];
tab[j]=tab[i];
tab[i]=temp;
}
}
for(int i=0;i<20;i++)//print of sorted sums
{
printf("%d,",tab[i]);
}
}
int main()
{
int tab[20];
int size=sizeof(tab)/sizeof(*tab);
for(int i=0;i<=20;i++)
{
tab[i]=rand()%1000;// assamble the value
}
for(int i=0;i<20;i++)
{
printf("%d,",tab[i]);//print unsorted
}
printf("\n");
sortujTab(tab,size);
return 0;
}
There are two basic approach :
Create a function that return the sum for an integer, say sum(int a), then call it on comparison, so instead of tab[i] > tab [j] it becomes sum(tab[i]) > sum (tab[j])
Store the sum into a different array, compare with the new array, and on swapping, swap both the original and the new array
The first solution works well enough if the array is small and takes no extra memory, while the second solution didn't need to repeatedly calculate the sum. A caching approach is also possible with map but it's only worth it if there are enough identical numbers in the array.
Since your numbers are non-negative and less than 1000, you can encode the sum of the digits in the numbers itself. So, this formula will be true: encoded_number = original_number + 1000 * sum_of_the_digits. encoded_number/1000 will decode the sum of the digits, and encoded_number%1000 will decode the original number. Follow the modified code below. The numbers enclosed by parentheses in the output are original numbers. I've tried to modify minimally your code.
#include <stdio.h>
#include <stdlib.h>
void sortujTab(int tab[], int size)
{
for (int i = 0; i < size; i++) {
int sum = 0, n = tab[i];
while (n > 0) { //sum as added digits of an integer
int p = n % 10;
sum = sum + p;
n /= 10;
}
tab[i] += sum * 1000;
}
for (int i = 0; i < size; i++) { //print of unsorted sums
printf("%d%c", tab[i] / 1000, i < size - 1 ? ',' : '\n');
}
for (int i = 0; i < size; i++) { //sorting sums
for (int j = i + 1; j < size; j++) {
if (tab[i] / 1000 > tab[j] / 1000) {
int temp = tab[j];
tab[j] = tab[i];
tab[i] = temp;
}
}
}
for (int i = 0; i < size; i++) { //print of sorted sums
printf("%d(%d)%c", tab[i] / 1000, tab[i] % 1000, i < size - 1 ? ',' : '\n');
}
}
int main(void)
{
int tab[20];
int size = sizeof(tab) / sizeof(*tab);
for (int i = 0; i < size; i++) {
tab[i] = rand() % 1000; // assamble the value
}
for (int i = 0; i < size; i++) {
printf("%d%c", tab[i], i < size - 1 ? ',' : '\n'); //print unsorted
}
sortujTab(tab, size);
return 0;
}
If the range of numbers doesn't allow such an encoding, then you can declare a structure with two integer elements (one for the original number and one for the sum of its digits), allocate an array for size elements of this structure, and initialize and sort the array using the digit sums as the keys.
You can sort an array of indexes rather than the array with data.
#include <stdio.h>
//poor man's interpretation of sumofdigits() :-)
int sod(int n) {
switch (n) {
default: return 0;
case 5: return 5;
case 11: return 2;
case 1000: return 1;
case 9: return 9;
}
}
void sortbyindex(int *data, int *ndx, int size) {
//setup default indexes
for (int k = 0; k < size; k++) ndx[k] = k;
//sort the indexes
for (int lo = 0; lo < size; lo++) {
for (int hi = lo + 1; hi < size; hi++) {
if (sod(data[ndx[lo]]) > sod(data[ndx[hi]])) {
//swap indexes
int tmp = ndx[lo];
ndx[lo] = ndx[hi];
ndx[hi] = tmp;
}
}
}
}
int main(void) {
int data[4] = {5, 11, 1000, 9};
int ndx[sizeof data / sizeof *data];
sortbyindex(data, ndx, 4);
for (int k = 0; k < sizeof data / sizeof *data; k++) {
printf("%d\n", data[ndx[k]]);
}
return 0;
}

How to compare jagged array to another array in C?

I've been trying to use a jagged array for a project of mine, meanwhile this is just a test furthermore I'll use it in my project. The question is the following How could I compare each element from each array, so in the code below I have three arrays, after them, I have one more which will be used to compare to the first ones,here what I have so far.
#include <stdio.h>
#include <stdlib.h>
int main(){
int row0[4] = {0,1,3,0};
int row1[4] = {5,6,9,10};
int row2[4] = {9,0,1,10};
int aux[4] = {9,6,9,10};
int *result[3] = {row0,row1,row2};
int size[3] = {4,4,4}, k =0;
for (int i = 0; i < 3; i++) {
int *ptr = result[i];
for (int j = 0; j < size[k]; j++) {
if(ptr[j] == aux[j])
{
printf("%d\n",ptr[j]);
}
ptr++;
}
printf("\n");
k++;
result[i]++;
}
return 0;
}
The result of it is 5, but I'd like to loop over all the values from the array that starts with 5, to find out if the all the other values are equal, in other words I want to know which array is equal to the "aux" array.
You have the (inner) loop:
int *ptr = result[i];
for (int j = 0; j < size[k]; j++)
{
if(ptr[j] == aux[j])
{
printf("%d\n",ptr[j]);
}
ptr++;
}
Since you increment both j and ptr, you're doing far too much incrementing. It's probably best to remove the ptr++; line.

How to find the items in the optimal solution of the knapsack problem using dynamic programming?

I want to find which items are eventually chosen in the optimal solution of the knapsack problem using the method of dynamic programming.
This is my interpretation so far...
#include<stdio.h>
int getMax(int x, int y) {
if(x > y) {
return x;
} else {
return y;
}
}
int main(void) {
//the first element is set to -1 as
//we are storing item from index 1
//in val[] and wt[] array
int val[] = {-1, 100, 20, 60, 40};
int wt[] = {-1, 3, 2, 4, 1};
int A[] = {0,0,0,0,0};
int n = 4; //num
int W = 5;//cap
int i, j;
// value table having n+1 rows and W+1 columns
int V[n+1][W+1];
// fill the row i=0 with value 0
for(j = 0; j <= W; j++) {
V[0][j] = 0;
}
// fill the column w=0 with value 0
for(i = 0; i <= n; i++) {
V[i][0] = 0;
}
//fill the value table
for(i = 1; i <= n; i++) {
for(j = 1; j <= W; j++) {
if(wt[i] <= j) {
V[i][j] = getMax(V[i-1][j], val[i] + V[i-1][j - wt[i]]);
} else {
V[i][j] = V[i-1][j];
}
}
}
//max value that can be put inside the knapsack
printf("Max Value: %d\n", V[n][W]);
//==================================find items
int n1,c;
n1=n;
c=W;
int A2[n1][c];
while(c>0){
if(A2[n1][c]==A2[n1-1][c]){
A[n1]=0;
} else {
A[n1]=1;
}
n1=n1-1;
c=c-wt[n1];
}
printf("Final array of items: ");
for(i = 0; i < n; i++){
printf("%d",A[i]);
}
} // end of main
And this is the output:
Max Value: 140
Final array of items: 0001
This string of ones and zeros is meant to be the finally chosen items, but from the solution this seems to be wrong!
I followed this algorithm:
While the remaining capacity is greater than 0 do
If Table[n, c] = Table[n-1, c] then
Item n has not been included in the optimal solution
Else
Item n has been included in the optimal solution
Process Item n
Move one row up to n-1
Move to column c – weight(n)
So, is this algorithm wrong / not suitable for this method, or am I missing something?

Seg fault trying to assign an array of structs in C

I've been away from C for a little bit, so there are some growing pains here.
Basically I'm trying to create an array of all possible RGB values.
#include <stdio.h>
#define MAX 3
struct rgb_val {
int r;
int g;
int b;
};
int main(void) {
struct rgb_val rgb[MAX];
int index = 0;
for (int r = 0; r < MAX; r++) {
for (int g = 0; g < MAX; g++) {
for (int b = 0; b < MAX; b++) {
rgb[index].r = r;
rgb[index].g = g;
rgb[index].b = b;
index++;
}
}
}
return 0;
}
Accessing array out of bounds.Its an undefined behavior.
Right now, you access out of your array's bounds, which has size MAX. You need to change your loop to :
int index = 0;
for (int index = 0; index < MAX; index++) {
rgb[index].r = r; //some r
rgb[index].g = g; //some g
rgb[index].b = b; //some b
}
This way, you will access only your array's elements.
Now, if you do want to increase the r, g and b's value by one for each struct, all you have to do is
rgb[index].r = index;
rgb[index].g = index;
rgb[index].b = index;
All right, if you want to assign all possible combinations, then you need 27 of them, not 3 (because 3 possible r/g/b values each).
So you need to have enough entries in your array:
struct rgb_val rgb[MAX * MAX * MAX];
Right now your code is accessing indexes 3, 4, ... 26 of array that is only 3 elements long, hence UB.
I believe you're accessing the array outside of bounds due to increasing the index count beyond MAX.
You would be better off using:
struct rgb_val rgb[MAX * ((sizeof(rgb_val)/sizeof(int)) * (sizeof(rgb_val)/sizeof(int)))];
int index = 0;
for (int r = 0; r < MAX; r++) {
for (int g = 0; g < MAX; g++) {
for (int b = 0; b < MAX; b++) {
rgb[index].r = r;
rgb[index].g = g;
rgb[index].b = b;
index++;
}
}
}

array bucket sort in C

I am trying to read list of numbers from txt file and then sort them with Bucket sort.
so here is my code:
void bucketSort(int array[],int *n)
{
int i, j;
int count[*n];
for (i = 0; i < *n; i++)
count[i] = 0;
for (i = 0; i < *n; i++)
(count[array[i]])++;
for (i = 0, j = 0; i < *n; i++)
for(; count[i] > 0; (count[i])--)
array[j++] = i;
}
int main(int brArg,char *arg[])
{
FILE *ulaz;
ulaz = fopen(arg[1], "r");
int array[100];
int i=0,j,k,n;
while(fscanf(ulaz, "%d", &array[i])!=EOF)i++;
fclose(ulaz);
n=i;
for (j = 0; j<i; j++)
{
printf("Broj: %d\n", array[j]);
}
BucketSort(array,&n);
for (k = 0; k<i; k++)
printf("%d \n", array[i]);
return 0;
}
There are no errors in code,but when i call my function instead of sorted array i get array length random numbers(example: 2 3 5 4,after sorting i get 124520 124520 124520 124520 or some other random number) since i am a beginner,could someone help me with my code and what i did wrong? (sorry for bad english)
As Cool Guy correctly pointed out you have issues with memory access but on top of it the code does not sort anything. First you should read how Bucket Sort actually works.
In general:
You divide the input data among buckets by some criteria that guarantees that the buckets will not mess up the input order
Sort each bucket either using some other sorting method or recursively with bucket sort
Concatenate the sorted data (this is why the first point has the restriction of not messing up the input order)
Here is an example of your original code, I tried to adjust it as little as possible you it is easier for you to understand. This code divides a predefined input array among 3 buckets by range:
[-infinity][-1] -> first bucket
[0;10] -> second bucket
[11;infinity] -> third bucket
then performs Quicksort on each bucket and concatenates the result. I hope this helps to understand how this algorithm works.
#include <stdio.h>
#include <stdlib.h>
struct bucket
{
int count;
int* values;
};
int compareIntegers(const void* first, const void* second)
{
int a = *((int*)first), b = *((int*)second);
if (a == b)
{
return 0;
}
else if (a < b)
{
return -1;
}
else
{
return 1;
}
}
void bucketSort(int array[],int n)
{
struct bucket buckets[3];
int i, j, k;
for (i = 0; i < 3; i++)
{
buckets[i].count = 0;
buckets[i].values = (int*)malloc(sizeof(int) * n);
}
// Divide the unsorted elements among 3 buckets
// < 0 : first
// 0 - 10 : second
// > 10 : third
for (i = 0; i < n; i++)
{
if (array[i] < 0)
{
buckets[0].values[buckets[0].count++] = array[i];
}
else if (array[i] > 10)
{
buckets[2].values[buckets[2].count++] = array[i];
}
else
{
buckets[1].values[buckets[1].count++] = array[i];
}
}
for (k = 0, i = 0; i < 3; i++)
{
// Use Quicksort to sort each bucket individually
qsort(buckets[i].values, buckets[i].count, sizeof(int), &compareIntegers);
for (j = 0; j < buckets[i].count; j++)
{
array[k + j] = buckets[i].values[j];
}
k += buckets[i].count;
free(buckets[i].values);
}
}
int main(int brArg,char *arg[]) {
int array[100] = { -5, -9, 1000, 1, -10, 0, 2, 3, 5, 4, 1234, 7 };
int i = 12,j,k,n;
n=i;
for (j = 0; j<i; j++)
{
printf("Broj: %d\n", array[j]);
}
bucketSort(array, n);
for (k = 0; k<i; k++)
printf("%d \n", array[k]);
return 0;
}
Your code exhibits Undefined Behavior as you try to write into memory location which are not owned by your program.
for (i = 0; i < *n; i++)
(count[array[i]])++;
The above loop is causing the problem. You say that i is 4 which means that *n is also 4 and array contains 2 3 5 4. In the above code,count is an array of *n elements(in this case 4 elements) and the valid indices for the array are count[0],count[1],count[2] and count[3]. Doing
count[array[i]]
when i is zero is okay as it is same as count[2]. This is the same when i is 1 as it would be count[3] . After that ,when i is 4 and 5,count[4] and count[5] are wrong as you try to write to a invalid memory location.
Also,your code dosen't sort the values.

Resources