Printing 2D array diagonally right-down - c

Trying to print a 2D array diagonally, going right to down, other solutions I've found are going in the opposite direction
Example of what I'm trying to achieve:
Input:
0 1 2 3
1 2 3 4
2 3 4 5
3 4 5 6
Intended Output:
0 2 4 6
1 3 5
2 4
3
(and other side 1 3 5, 2 4, 3)
Managed to print a diagonal with
for (x=0; x<12; x++) {
printf("%d ", arr[x][x])
}
But unsure how to replicate it for multiple, following attempt is incorrect
for (x=0; x<12; x++) {
for (y=0;y<x+1;y++) {
printf("%d ", arr[x][y]);
}
printf("\n");
}

The following C program meets your requirements. Try to understand the indexing.
int n, i, j, k;
int arr[5][5] = {
0, 1, 2, 3, 4,
1, 2, 3, 4, 5,
2, 3, 4, 5, 6,
3, 4, 5, 6, 7,
4, 5, 6, 7, 8
};
n = 5;
for (k = 0; k < n; k++) {
int ind = 0;
for (i = k; i < n; i++) {
printf("%d ", arr[i][ind++]);
}
printf("\n");
}
Output of the following program:
0 2 4 6 8
1 3 5 7
2 4 6
3 5
4
You can change the size of the array and change the value of n, it will work for your desired n*n array.

Related

Populating and array in a matrix style

I want to populate an array in a matrix style, on columns. So for example, if I had an array input:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Then the matrix would be (for numRows = 3, numCols=5):
1 4 7 10 13
2 5 8 11 14
3 6 9 12 15
This means the real array would be:
1 4 7 10 13 2 5 8 11 14 3 6 9 12 15
How would I do that?
Here is my take:
int v[15] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int matrix[15];
int row = 0, col = 0;
for (int i = 0; i < 15; ++i) {
matrix[col * 5 + row] = v[i];
printf("row = %d col = %d\n", row, col);
row++;
if (row == 3) {
row = 0;
col++;
}
}
```
You were very close in your last code example. The short answer is that rather than this:
matrix[col * 5 + row] = v[i];
You want:
matrix[row * 5 + col] = v[i];
In other words, 'row' and 'col' need to be the other way around.
Here's your example with that change made, and the results printed at the end:
int main(int argc, const char * argv[]) {
int v[15] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
int matrix[15];
int row = 0, col = 0;
for (int i = 0; i < 15; ++i) {
matrix[row * 5 + col] = v[i];
printf("row = %d col = %d\n", row, col);
row++;
if (row == 3) {
row = 0;
col++;
}
}
for (int i = 0; i < 15; ++i) {
printf("%d ", matrix[i]);
}
printf("\n");
}
The output at the end for me is:
1 4 7 10 13 2 5 8 11 14 3 6 9 12 15
Which appears to match the output you were after in your post.
There are multiple conversions that can be made here: from 2-d row/column indices to 1-d indices in row- or column-major order, and from 1-d indices in row- or column-major order to 2-d row/column indices. The math is fairly simple for all the conversions (converting from 1-d to 2-d indices involves integer division and modulus). Once you figure out the conversions you need, I suggest creating a little library of functions for performing the conversions so that you have the functionality available when you need it.
Lastly, a couple general suggestions. Your original code wrote outside array bounds, which wasn't checked for, at least in what you posted. For exploratory work like this, I'd suggest using bounds checking so that you can detect errors more easily. (For example, in this case you could use std::array and the at() function.) This will help you catch a certain class of mistakes early.
I'd also suggest using named constants, even in a small example like this, e.g. 'numRows' and 'numCols' instead of 3 and 5, and 'numElements' as the product of those instead of 15. This will also help avoid errors, and will also make the code easier to read and understand (both for you and others).

Looping through and comparing subsets of arrays

I have two arrays:
int group_id[] = {1, 1, 2, 2, 2, 3, 3, 3};
int value[] = {1, 0, 3, 5, 0, 2, 1, 6};
From the second array, I need to return the largest value within the group_id index (not including the current index position), the result (in a new array) would be:
{0, 1, 5, 3, 5, 6, 6, 2}
The arrays are a lot longer (~10 millions), so looking for an efficient solution.
Clarification:
The first two elements of value belong to group_id = 1, the first element will return 0 as the highest value as it can't return its self. The second element will will return 1 as it's the largest value in group_id 1.
the third, fourth and fifth elements (3, 5, 0) belong to group_id 2, the first will return 5, the second 3 (as it can't return its own index and the third will return 5).
It isn't clear that all the elements in group_id with the same number are adjacent (but that is crucial for efficiency).
Good point, you can assume they are all adjacent.
It isn't clear what should happen if there was only one entry in group_id with a given value — there isn't an alternative entry to use, so what should happen (or should the code abandon ship if the input is invalid).
Assume invalid.
The problem can be solved in O(N) time; it does not need O(N•log N) and sorting. This code shows how:
/* SO 5723-6683 */
#include <assert.h>
#include <stdio.h>
static void dump_array(const char *tag, int size, int *data);
static void test_array(const char *tag, int size, int *groups, int *values);
int main(void)
{
int groups1[] = { 1, 1, 2, 2, 2, 3, 3, 3 };
int values1[] = { 1, 0, 3, 5, 0, 2, 1, 6 };
int groups2[] = { 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 5 };
int values2[] = { 1, 1, 3, 5, 0, 2, 1, 6, 6, 3, 5, 5, 5, 3, 2, 3, 7, 3 };
enum { NUM_VALUES1 = sizeof(values1) / sizeof(values1[0]) };
enum { NUM_VALUES2 = sizeof(values2) / sizeof(values2[0]) };
test_array("Test 1", NUM_VALUES1, groups1, values1);
test_array("Test 2", NUM_VALUES2, groups2, values2);
return 0;
}
static void test_array(const char *tag, int size, int *groups, int *values)
{
printf("%s (%d):\n", tag, size);
dump_array("values", size, values);
dump_array("groups", size, groups);
int output[size];
int grp_size;
for (int lo = 0; lo < size - 1; lo += grp_size)
{
assert(groups[lo+0] == groups[lo+1]);
grp_size = 2;
int max_1 = (values[lo+0] < values[lo+1]) ? values[lo+1] : values[lo+0];
int max_2 = (values[lo+0] < values[lo+1]) ? values[lo+0] : values[lo+1];
for (int hi = lo + 2; hi < size && groups[hi] == groups[lo]; hi++)
{
grp_size++;
if (values[hi] >= max_1)
{
max_2 = max_1;
max_1 = values[hi];
}
else if (values[hi] >= max_2)
max_2 = values[hi];
}
for (int i = lo; i < lo + grp_size; i++)
output[i] = (values[i] == max_1) ? max_2 : max_1;
}
dump_array("output", size, output);
}
static void dump_array(const char *tag, int size, int *data)
{
printf("%s (%d):", tag, size);
for (int i = 0; i < size; i++)
printf(" %d", data[i]);
putchar('\n');
}
Output from this test program:
Test 1 (8):
values (8): 1 0 3 5 0 2 1 6
groups (8): 1 1 2 2 2 3 3 3
output (8): 0 1 5 3 5 6 6 2
Test 2 (18):
values (18): 1 1 3 5 0 2 1 6 6 3 5 5 5 3 2 3 7 3
groups (18): 1 1 2 2 2 3 3 3 3 3 4 4 4 5 5 5 5 5
output (18): 1 1 5 3 5 6 6 6 6 6 5 5 5 7 7 7 3 7
The following code will do it. Its efficiency is O(sum of all n_ilog(n_i)) in which n_i is the size of each subset i, unless we use MPI or OpenMP (in that case, it will be at best O(mlog(m)), in which m is the size of the greatest subset).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare (const void * e1, const void * e2)
{
int f = *((int*)e1);
int s = *((int*)e2);
return (f>s);
}
int main(int argc, char* argv[])
{
int group_id[] = {1, 1, 2, 2, 2, 3, 3, 3};
int value[] = {1, 0, 3, 5, 0, 2, 1, 6};
int i,j,k,count,*tmp;
for (i=0; i<8; i++)
{
/* find subsets */
count = 1;
for (j=i; j<7 && group_id[j]==group_id[j+1]; j++)
count++;
/* copy subset */
tmp = malloc(sizeof(int)*count);
memcpy(tmp, &value[i], sizeof(int)*count);
/* sort */
qsort (tmp, count, sizeof(*tmp), compare);
/* print */
for (k=i; k<=j; k++)
if (value[k] != tmp[count-1])
printf("%d ", tmp[count-1]);
else
printf("%d ", tmp[count-2]);
i = j;
free(tmp);
}
printf("\n");
return 0;
}
PS: You will probably have to do some modifications to it, but I hope its enough for what you want (or to get you started). Please, be aware, I am assuming each subset has size at least 2, and that the greatest value within a subset appears only once.

Recursive function to search find and change specific cells based on a criteria

I'm trying in C to write a recursive function that takes as an input an NxM matrix, and finds, checks specific cells and changes their content based on a scenario.
Original matrix
The matrix elements are:
1 2 3 4 5 6 7 8
------------------
1| 1 6 7 4 4 1 2 8
2| 1 3 6 3 3 1 3 4
3| 3 4 1 5 7 8 5 1
4| 1 7 8 6 2 6 4 4
5| 7 8 1 6 2 2 7 1
6| 3 8 4 3 1 6 8 6
7| 3 8 7 5 4 6 6 6
8| 7 2 2 1 7 4 6 8
Based on a matrix like the above, a user gives the location of a specific cell, e.g. position (5,6) for the integer 2. I want the recursive function to check the cells in the four directions, up, down, left, right and if it finds the same integer to change them to 0s. This will continue for all the "neighborhood" cells. In this example all twos at positions (5,6), (5,5) and (4,5) will change to 0s.
Another example:
user gives location i.e. position (8,7) for the integer 6. The recursive function has to find and change all 6s at the positions (8,7), (7,7), (7,8), (7,6), (6,6), (6,8) and set them to 0s.
void destroy(int (*arr), int rows, int cols,int search,int rowin, int colin) //rows: total rows of matrxi, cols:total cols of matrix, rowin and colin are the x,y co ordinates of the cell that the user wants to destroy and search has the int i.e 6 ..
{
int i, j;
printf("\n");
printf("\n");
int count = 0,temp = 0;
for (j = 0; j < cols; j++) {
for (i = 0; i < rows; i++) {
if (*(arr + i*cols + j)== search) {
if (*(arr + (i-1)*cols + j) == search){//check neighborhood cell
count++; //counter to know how many similar neighborhood integers have been found
(*(arr + i*cols + j)= 0);
*(arr + (i-1)*cols + j) = 0;
destroy(int (*arr), int rows, int cols,int search, j, i) //call recursive function to check the neighborhood cells of the new position i,j
}
}
}
}
}
You don't need for loops but four recursive calls to check each neighborhood.
void destroy(int *arr, int rows, int cols,int search,int rowin, int colin)
{
if (rowin>=rows || colin >= cols || rowin < 0 || colin <0)
return; //base condition
if (arr[rowin*cols+colin] == search)
{
arr[rowin*cols+colin] = 0;
destroy(arr, rows, cols, search, rowin+1, colin);
destroy(arr, rows, cols, search, rowin, colin+1);
destroy(arr, rows, cols, search, rowin-1, colin);
destroy(arr, rows, cols, search, rowin, colin-1);
}
}
Notice that in C an array index starts from zero (not one).
Here is an example that uses a matrix (aka array of array).
#include <stdio.h>
void destroy(int value, int r, int c, int r_size, int c_size, int arr[][r_size])
{
if (value != arr[r][c]) return; // Nothing to do
arr[r][c] = 0;
if (r+1 < r_size) destroy(value, r+1, c, r_size, c_size, arr); // DOWN
if (r-1 >= 0) destroy(value, r-1, c, r_size, c_size, arr); // UP
if (c+1 < c_size) destroy(value, r, c+1, r_size, c_size, arr); // RIGHT
if (c-1 >= 0) destroy(value, r, c-1, r_size, c_size, arr); // LEFT
}
void pm(int r_size, int c_size, int arr[r_size][r_size])
{
printf("-------------------------------------------\n");
for (int r=0; r < r_size; ++r)
{
for (int c=0; c < c_size; ++c)
{
printf("%d ", arr[r][c]);
}
printf("\n");
}
}
#define MSIZE 8
int main(void) {
int arr[MSIZE][MSIZE] =
{
{1, 6, 7, 4, 4, 1, 2, 8},
{1, 3, 6, 3, 3, 1, 3, 4},
{3, 4, 1, 5, 7, 8, 5, 1},
{1, 7, 8, 6, 2, 6, 4, 4},
{7, 8, 1, 6, 2, 2, 7, 1},
{3, 8, 4, 3, 1, 6, 8, 6},
{3, 8, 7, 5, 4, 6, 6, 6},
{7, 2, 2, 1, 7, 4, 6, 8}
};
pm(MSIZE, MSIZE, arr);
destroy(arr[7][6], 7, 6, MSIZE, MSIZE, arr);
pm(MSIZE, MSIZE, arr);
return 0;
}
Output:
-------------------------------------------
1 6 7 4 4 1 2 8
1 3 6 3 3 1 3 4
3 4 1 5 7 8 5 1
1 7 8 6 2 6 4 4
7 8 1 6 2 2 7 1
3 8 4 3 1 6 8 6
3 8 7 5 4 6 6 6
7 2 2 1 7 4 6 8
-------------------------------------------
1 6 7 4 4 1 2 8
1 3 6 3 3 1 3 4
3 4 1 5 7 8 5 1
1 7 8 6 2 6 4 4
7 8 1 6 2 2 7 1
3 8 4 3 1 0 8 0
3 8 7 5 4 0 0 0
7 2 2 1 7 4 0 8
Version 2
This version a little different because it only changes elements if at least one neighbor is found. Also it counts the number of changes.
#include <stdio.h>
#include <stdlib.h>
int destroy_rec(int value, int r, int c, int r_size, int c_size, int arr[][r_size])
{
if (value != arr[r][c]) return 0; // Nothing to do
int changed = 1;
arr[r][c] = 0;
if (r+1 < r_size) changed += destroy_rec(value, r+1, c, r_size, c_size, arr); // DOWN
if (r-1 >= 0) changed += destroy_rec(value, r-1, c, r_size, c_size, arr); // UP
if (c+1 < c_size) changed += destroy_rec(value, r, c+1, r_size, c_size, arr); // RIGHT
if (c-1 >= 0) changed += destroy_rec(value, r, c-1, r_size, c_size, arr); // LEFT
return changed;
}
int destroy(int r, int c, int r_size, int c_size, int arr[][r_size])
{
if (r+1 < r_size && arr[r+1][c] == arr[r][c]) return destroy_rec(arr[r][c], r, c, r_size, c_size, arr);
if (r-1 >= 0 && arr[r-1][c] == arr[r][c]) return destroy_rec(arr[r][c], r, c, r_size, c_size, arr);
if (c+1 < c_size && arr[r][c+1] == arr[r][c]) return destroy_rec(arr[r][c], r, c, r_size, c_size, arr);
if (c-1 >= 0 && arr[r][c-1] == arr[r][c]) return destroy_rec(arr[r][c], r, c, r_size, c_size, arr);
return 0;
}
void pm(int r_size, int c_size, int arr[r_size][r_size])
{
printf("-------------------------------------------\n");
for (int r=0; r < r_size; ++r)
{
for (int c=0; c < c_size; ++c)
{
printf("%d ", arr[r][c]);
}
printf("\n");
}
printf("-------------------------------------------\n");
}
#define MSIZE 8
int main(void) {
int arr[MSIZE][MSIZE] =
{
{1, 6, 7, 4, 4, 1, 2, 8},
{1, 3, 6, 3, 3, 1, 3, 4},
{3, 4, 1, 5, 7, 8, 5, 1},
{1, 7, 8, 6, 2, 6, 4, 4},
{7, 8, 1, 6, 2, 2, 7, 1},
{3, 8, 4, 3, 1, 6, 8, 6},
{3, 8, 7, 5, 4, 6, 6, 6},
{7, 2, 2, 1, 7, 4, 6, 8}
};
pm(MSIZE, MSIZE, arr);
int changed = destroy(7, 6, MSIZE, MSIZE, arr);
printf("%d cells changed\n", changed);
pm(MSIZE, MSIZE, arr);
int (*dyn_arr)[MSIZE] = malloc(MSIZE * sizeof *dyn_arr);
return 0;
}
Output:
-------------------------------------------
1 6 7 4 4 1 2 8
1 3 6 3 3 1 3 4
3 4 1 5 7 8 5 1
1 7 8 6 2 6 4 4
7 8 1 6 2 2 7 1
3 8 4 3 1 6 8 6
3 8 7 5 4 6 6 6
7 2 2 1 7 4 6 8
-------------------------------------------
6 cells changed
-------------------------------------------
1 6 7 4 4 1 2 8
1 3 6 3 3 1 3 4
3 4 1 5 7 8 5 1
1 7 8 6 2 6 4 4
7 8 1 6 2 2 7 1
3 8 4 3 1 0 8 0
3 8 7 5 4 0 0 0
7 2 2 1 7 4 0 8
-------------------------------------------
I don't know what you want to achieve with this because in your code you're already traversing through whole array and after checking one element you want to traverse again.
In my point of view you don't need another iteration to remove the elements. You can perform this in a single iteration.
If the element you're searching exists then remove the neighbor elements
(i,j => (i-1,j : i+1,j : i,j-1 : i,j+1))
In this way you might need to put some checks on index value to avoid undefined behaviour.

Sorting multidimensional array without pointers

Ok, so I've got multidimensional array "int Array[3][4];" so let's say for instance I have such scanned information:
2 5 6 4
3 4 8 3
1 8 8 7
So I need to sort every column (growing) Like so:
1 4 6 3
2 5 8 4
3 8 8 7
So I'd like to ask you how can I sort such multidimensional array without using pointers? Previously I used bubble method, however I couldn't get it working this time...
My code example:
for(i=0;i<3;i++){
for(z=i+1;z<4;z++){
if(Array[i][z-1]>Array[i][z]) {
int x=Array[i][z-1];
Array[i][z-1]=Array[i][z];
Array[i][z]=x;
}
}
}
the number of elements to compare is 3 , So it can be as follows.
#include <stdio.h>
int main(void){
int Array[3][4] = {
2, 5, 6, 4,
3, 4, 8, 3,
1, 8, 8, 7
};
int i,j;
int min, max, mid;
int min_i, max_i;
for(i=0;i<4;++i){
max_i = Array[0][i] < Array[1][i];
min_i = !max_i;
if(Array[min_i][i] > Array[2][i])
min_i = 2;
if(Array[max_i][i] < Array[2][i])
max_i = 2;
max=Array[max_i][i];
mid=Array[3-max_i-min_i][i];
min=Array[min_i][i];
Array[0][i]=min;
Array[1][i]=mid;
Array[2][i]=max;
}
for(i=0;i<3;++i){
for(j=0;j<4;++j)
printf("%d ", Array[i][j]);
printf("\n");
}
return 0;
}

How to iterate over the series: 0, 1, 2, 3, 4, 4, 5, 6, 7, 7, 8, 7, 8, 8, 9 … without using recursion?

Is am trying to figure out how to generate this sequence of numbers in C.
0, 1, 2, 3, 4, 4, 5, 6, 7, 7, 8, 8, 9 …
The sequence is generated by forming a triangle of numbers as shown below:
0
1 2
3 4 5
6 7 8 9 ...
Next two numbers in series are located as follows:
Next number is located directly below
Next to next is located one place to the right.
0
|\
1 2
Series -> 0, 1, 2
0
|\
1 2
|\|\
3 4 5
Series -> 0, 1, 2, 3, 4, 4, 5, ........
How can I traverse this number triangle to get this sequence in C?
It means that
0 is replaced with 1 and 2
1 is replaced with 3 and 4
2 is replaced with 4 and 5
0
|\
1 2
|\|\
3 4 5
|\|\|\
6 7 8 9
Series -> 0, 1, 2, 3, 4, 4, 5, 6, 7, 7, 8, 7, 8, 8, 9 ........
It means that
I. Solving 0
0 leads to 1 and 2
0 -> 1 - 2
0 1 2
II. Solving 1 and 2
1 leads to 3 and 4
1 -> 3 - 4
0 1 2 3 4
2 leads to 4 and 5
2 -> 4 - 5
0 1 2 3 4 4 5
III. Solving 3, 4, 4, 5
3 leads to 6 and 7
3 -> 6 - 7
0 1 2 3 4 4 5 6 7
4 leads to 7 and 8
4 -> 7 - 8
0 1 2 3 4 4 5 6 7 7 8
4 leads to 7 and 8
4 -> 7 - 8
0 1 2 3 4 4 5 6 7 7 8 7 8
5 leads to 8 and 9
5 -> 8 - 9
0 1 2 3 4 4 5 6 7 7 8 7 8 8 9
My apologies for not explaining properly. I hope I explain it this time.
I assume (based on the description) your sequence should be indeed
0
1 2
3 4 4 5
6 7 7 8 8 9
10 11 11 12 12 13 13 14
etc.
You can work with it with the code like that:
int nextRowStart = 0;
int nextRowSize = 1;
for (int curr = 0; /*put some ending condition here*/; curr++)
{
yield(curr)
if (curr != nextRowStart - 1 && curr != nextRowStart)
yield(curr);
if (curr == nextRowStart)
{
nextRowStart += nextRowSize;
nextRowSize++;
}
}
void yield(int x)
{
printf("%d ", x);
}
With the changed question, the new one can be done recursively
This is the solution in C#:
IEnumerable<int> Generate(int level)
{
if (level == 0)
{
yield return 0;
yield break;
}
int diff = level;
foreach (int n in Generate(level - 1))
{
yield return n + diff;
yield return n + diff + 1;
}
}
var result = Enumerable.Range(0, maxLevel).SelectMany(Generate);
It would take some time to translate it into C...
C solution:
void Generate(int level, int* resultsize, int** result)
{
if (level == 0)
{
*result = (int*)malloc(sizeof(int));
(*result)[0] = 0;
*resultsize = 1;
}
else
{
int recResultSize;
int* recResult;
Generate(level - 1, &recResultSize, &recResult);
*resultsize = recResultSize * 2;
*result = (int*)malloc(*resultsize * sizeof(int));
for (int i = 0; i < recResultSize; i++)
{
(*result)[2*i] = recResult[i] + level;
(*result)[2*i + 1] = recResult[i] + level + 1;
}
free(recResult);
}
}
This is the code which gives the exact result and solves the problem. I came at this result just when #Lundin asked me to post my code , I tried again and I was successful. Thanks guys.
#include<stdio.h>
int in;
int main(){
int ik, it, icount = 0, ih, temp, ig = 1;
int aisum[100];
aisum[0] = 0;
scanf("%d",&in);
printf("0\n");
it = 1;ih = 0;temp = 2;
for(icount = 0,ig = 1; icount <= in; icount++){
for(ik = 0; ik<2; ik++){
aisum[ig] = aisum[icount] + it + ik ;
printf("%d ",aisum[ig]);
ig++;
}
if(aisum[icount] == ih){
printf("\n");
it++;
ih += temp;
temp++;
}
}
return 0;
}
/*Input the number of elements to be processed*/
/*icount will account for new elements to be formed like if we look
at pascal triangle
0 will form 1 and 2
1 will form 3 and 4
*/
/*ig will account for array indices*/
/*it will account for the periodic addition */
/*ih checks for the codnition for it to increement
0
1 2
3 4 5
it will be increemented at 0, 2, 5 ...
*/
The simplest solution I can give from below triangle to required order is...
0
1 2
3 4 5
6 7 8 9
printing start and end nodes of each line and printing center elements 2 times each...
for each line start will be equals to previous end+1...
end will be equal to end+1+count...
count will be incremented by 1 for each line...
CPP Program:
#include<iostream>
using namespace std;
int main()
{
int start=1,end=2,count=1;
cout<<0<<" ";
while(count<5)
{
cout<<start<<" ";
for(int i=start+1;i<end;i++)
{
cout<<i<<" "<<i<<" ";
}
cout<<end<<" ";
count++;
start=end+1;
end=start+count;
}
return 0;
}

Resources