Populating and array in a matrix style - arrays

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).

Related

Printing 2D array diagonally right-down

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.

How to make parameter of double dimension arrangement to use in function

#include <stdio.h>
void Turn(int(*ptr)[4], int length, int vertical)
{
int arr[100][100] = { 0, };
for (int i = 0; i < vertical; i++)
{
for (int j = 0; j < length; j++)
{
arr[i][j] = *(*(ptr + (vertical - j - 1)) + i);
}
}
for (int i = 0; i < vertical; i++)
{
for (int j = 0; j < length; j++)
{
*(*(ptr + i) + j) = arr[i][j];
}
}
}
int main(void)
{
int BY[4][4] = {
1,2,3,4,
5,6,7,8,
9,10,11,12,
13,14,15,16,
};
int length = sizeof(BY[0]) / sizeof(int);
int vertical = (sizeof(BY) / sizeof(int)) / length;
Turn(BY, length, vertical);
for (int i = 0; i < vertical; i++)
{
for (int j = 0; j < length; j++)
{
printf("%d ", BY[i][j]);
}
printf("\n");
}
return 0;
}
I wrote a function named Turn to rotate a 2D array right (a 90 degree rotation). I wanted to make this function to turn every array that has same vertical range and length. But I can't hand over
(I used google translate, I don't know how to describe it) parameter of a 2D array.
I first used void Turn(int(*ptr)[] ....)
but it didn't work. So I couldn't help using
int (*ptr)[4] in this function.
How can I make a parameter of a 2D array that can be used with any 2D array?
Using the C99 variable length array (VLA) feature make the problem easy. C11 makes support for VLAs optional, but the implementation must define __STDC_NO_VLA__ to show that it doesn't support VLAs.
Here's one version of the code. I've renamed your Turn() function (which turns the matrix 90° right into TurnR() and added a TurnL() function which turns the matrix 90° left. Because the code handles non-square matrices, the output matrix is separate from the input matrix. (You can simplify the code slightly if you only want to work with square matrices.)
#include <stdio.h>
static void TurnR(size_t rows, size_t cols, int matrix[rows][cols], int result[cols][rows])
{
for (size_t r = 0; r < rows; r++)
{
for (size_t c = 0; c < cols; c++)
result[c][rows - 1 - r] = matrix[r][c];
}
}
static void TurnL(size_t rows, size_t cols, int matrix[rows][cols], int result[cols][rows])
{
for (size_t r = 0; r < rows; r++)
{
for (size_t c = 0; c < cols; c++)
result[cols - 1 - c][r] = matrix[r][c];
}
}
static void Print(const char *tag, size_t rows, size_t cols, int matrix[rows][cols])
{
printf("%s (%zux%zu):\n", tag, rows, cols);
for (size_t r = 0; r < rows; r++)
{
const char *pad = "";
for (size_t c = 0; c < cols; c++)
{
printf("%s%3d", pad, matrix[r][c]);
pad = " ";
}
putchar('\n');
}
}
int main(void)
{
int BY[4][4] = {
{ 1, 2, 3, 4, },
{ 5, 6, 7, 8, },
{ 9, 10, 11, 12, },
{ 13, 14, 15, 16, },
};
int out[4][4];
Print("before", 4, 4, BY);
TurnR(4, 4, BY, out);
Print("right", 4, 4, out);
TurnL(4, 4, BY, out);
Print("left", 4, 4, out);
int m4x6[4][6] =
{
{ 1, 2, 3, 4, 5, 6, },
{ 7, 8, 9, 10, 11, 12, },
{ 13, 14, 15, 16, 17, 18, },
{ 19, 20, 21, 22, 23, 24, },
};
int m6x4[6][4];
Print("before", 4, 6, m4x6);
TurnR(4, 6, m4x6, m6x4);
Print("right", 6, 4, m6x4);
TurnL(4, 6, m4x6, m6x4);
Print("left", 6, 4, m6x4);
int m5x3[5][3] =
{
{ 1, 2, 3, },
{ 4, 5, 6, },
{ 7, 8, 9, },
{ 10, 11, 12, },
{ 13, 14, 15, },
};
int m3x5[3][5];
Print("before", 5, 3, m5x3);
TurnR(5, 3, m5x3, m3x5);
Print("right", 3, 5, m3x5);
TurnL(5, 3, m5x3, m3x5);
Print("left", 3, 5, m3x5);
TurnL(3, 5, m3x5, m5x3);
Print("doubleL", 5, 3, m5x3);
return 0;
}
And sample output is:
before (4x4):
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
right (4x4):
13 9 5 1
14 10 6 2
15 11 7 3
16 12 8 4
left (4x4):
4 8 12 16
3 7 11 15
2 6 10 14
1 5 9 13
before (4x6):
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
right (6x4):
19 13 7 1
20 14 8 2
21 15 9 3
22 16 10 4
23 17 11 5
24 18 12 6
left (6x4):
6 12 18 24
5 11 17 23
4 10 16 22
3 9 15 21
2 8 14 20
1 7 13 19
before (5x3):
1 2 3
4 5 6
7 8 9
10 11 12
13 14 15
right (3x5):
13 10 7 4 1
14 11 8 5 2
15 12 9 6 3
left (3x5):
3 6 9 12 15
2 5 8 11 14
1 4 7 10 13
doubleL (5x3):
15 14 13
12 11 10
9 8 7
6 5 4
3 2 1
I wouldn't dream of writing the code using the *(ptr + index) notation, especially with the double subscripts; it is just too error prone and hard to read (a nightmare, indeed!).

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;
}

Creating a 2D array board

I am trying to create a 2d matrix board which side is determined by the user input. I created the two D array but it is not printing the right numbers. For example if the user enters 3, it is suppose to create a 3 * 3 board with the number 8, 7, 6, 5, 4, 3, 2, 1, 0.
However it keeps printing the same numbers in each row eg 876, 876, 876
I know it is doing what I have written but I cant figure out how to correct it...I am thinking that I need a counter that resets to zero and perhaps the [i][j] = counter's value.
Anyway here is the code that is giving the trouble.
for (i =0; i< row; i++)
{
for (j =0; j < col; j++)
{
game [i][j] = ((row * row)-1) - j;
printf( "%i", game[i][j] );
}
How can I populate the board so it prints from (row * col) - 1 to zero. Thanks a million.
for ((i=0, k=0); i< row; i++)
{
for (j =0; j < col; j++)
{
game [i][j] = ((row * col)-1) - (k++);
printf( "%i", game[i][j] );
}
}
The basic mistake in the code is that, in each iteration, the value getting subtracted from the game[i][j] gets re-initialized to 0. Since, the value of (row * col) is constant for a given value of both, subtracting (0, 1, 2) each time from the sum results in the reproduction of the same numbers.
As given in the example, row=3, col=3, so 3*3 = 9 (Indexed from 0 to 8).
So, we do :
8 - 0 = 8
8 - 1 = 7
8 - 2 = 6
again j gets re-init to 0, so again we have,
8 - 0 = 8
8 - 1 = 7
8 - 2 = 6
.
The solution is, the value getting subtracted should get uniformly reduced, such that it doesn't get re-init inside the loop.
Result :
8 - 0 = 8
8 - 1 = 7
8 - 2 = 6
8 - 3 = 5
.
.
.
.
8 - 8 = 0.
Hope this clears the problem.
As suggested by "self", using a third variable is the easiest way (and actually the most efficient : only one decrement per iteration)
int count = row * col - 1;
for (size_t i =0; i< row; i++)
{
for (size_t j =0; j < col; j++)
{
game [i][j] = count--;
printf( "%i", game[i][j] );
}
}
Output:
24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0

Replace number by sum of other numbers in a list without subtraction

I was asked:
Replace each number in a list by sum of remaining elements, the list is not sorted.
So suppose if we have a list of numbers like {2, 7, 1, 3, 8}, now we are to replace each element with sum of rest of elements. The output should be:
{(7 + 1 + 3 + 8), (2 + 1 + 3 + 8), (2 + 7 + 3 + 8), (2 + 7 + 1 + 8), (2 + 7 + 1 + 3)}
== {19, 14, 20, 18, 13}
I answered an obvious solution:
First evaluate sum of all numbers then subtract each element from sum.
So for above list sum is 2 + 7 + 1 + 3 + 8 = 21, then for output do like:
{sum - 2, sum - 7, sum - 1, sum - 3, sum - 8}
{21 - 2, 21 - 7, 21 - 1, 21 - 3, 21 - 8}
== {19, 14, 20, 18, 13}
It needs only two iterations of list.
Then Interviewer asked me: Now do it without subtraction? and I couldn't answer :(
Is other solution possible? Can some share any other trick? A better trick is possible?
Lets extra memory space can be used (I asked after a few minutes of try, even then I couldn't answer).
One possibility would be to compute prefix and suffix sums of your array and then combine the appropriate entries. This would still be O(n) but needs more memory space so I think your original method is better.
In other words, from {2, 7, 1, 3, 8} compute {2, 2+7, 2+7+1, 2+7+1+3, 2+7+1+3+8} and {2+7+1+3+8, 7+1+3+8, 1+3+8, 3+8, 8} and then add the appropriate entries.
The solution is to sum everything but the element. Then you don't have to subtract after the fact. You just skip adding the element at the current index.
Alternatively, you could get a subset of the list that excludes the element at the current index, then just sum the subset together. Pretty much the same thing as my first suggestion with more implementation detail.
C++ implementation. O(n) and done by keeping sums of all elements before and after a certain index.
#include <iostream>
int main() {
int a[] = {2,7,1,3,8};
int prefix[5]; // Sum of all values before current index
int suffix[5]; // Sum of all values after current index
prefix[0] = 0;
suffix[4] = 0;
for(int i = 1; i < 5; i++) {
prefix[i] = prefix[i-1] + a[i-1];
suffix[4 - i] = suffix[4 - i + 1] + a[4 - i + 1];
}
// Print result
for (int i = 0; i < 5; i++) {
std::cout << prefix[i] + suffix[i] << " ";
}
std::cout << std::endl;
}
I can't think anything better than yours.
But how about this :
Create a (n-1)xn matrix:
[ 2, 7, 1, 3, 8 ]
| 7, 1, 3, 8, 2 | rotate by 1
| 1, 3, 8, 2, 7 | by 2
| 3, 8, 2, 7, 1 | by 3
| 8, 2, 7, 1, 3 | by 4
Then Sum up the columns
C++'s std::rotate_copy can be used to create matrix
std::vector<int> v1 {2, 7, 1, 3, 8 };
std::vector<int> v2 (v1.size());
int i,j;
std::vector< std::vector<int> > mat;
for (int i=1; i<v1.size();++i){
std::rotate_copy(v1.begin(),v1.begin()+i,v1.end(),v2.begin());
mat.push_back(v2);
}
for(j=0;j<v1.size();++j)
for(i=0;i<v1.size()-2;++i)
v2[j]+=mat[i][j];
for(i=0;i<v2.size();++i)
std::cout<<v2[i]<<" ";
#include <iostream.h>
#include <stdio.h>
int main() {
int a[] = {2,7,1,3,8};
int sum[5]={0};
for(int j = 0; j < 5; j++){
for(int i = 1; i < 5; i++) {
sum[j]=sum[j]+a[(j+i+5)%5];
}
printf("%d ", sum[j]); }
}
Instead of subtracting the element you can add the element multiplied by -1. Multiplication and addition are allowed operations, I guess.

Categories

Resources