L1xL2 array on 8x8 blocks - c

Given an array of size L1xL2 divide the array by blocks of 4x4. For example the size of the array is 8x8 so there will be four blocks of 4x4.
Here is an example:
1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 6 6 6 6 7 7 7 7 8 8 8 8
...............
First block 4x4 will be:
1 1 1 1 3 3 3 3 5 5 5 5 7 7 7 7
The second block will be:
2 2 2 2 4 4 4 4 6 6 6 6 8 8 8 8
I wrote this code (I have a matrix that is stored as an array and it's size is 8*8):
for (p = 0; p < nr_blocks; p ++) {
for (i = p*4; i < p*4 + 4; i++) {
for (j = 0; j < 4; j++) {
printf(" %d ", array[i*4 + j]);
}
}
}
But this code take the first block like this:
1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4
I want to divide in all the blocks and print them => 4 blocks.
What it is wrong?

When your array stores the 8x8 matrix you need access it with the dimension 8.
for(p = 0; p < nr_blocks; p ++){
for(i = p*nr_blocks; i < p*nr_blocks + 4; i++) { // please note the change
for(j = 0; j < 4; j++){
printf(" %d ", array[i*4 + j]);
}
printf("\n");
}
}

You seem to be storing what you call a matrix as one array, that is not a matrix. A matrix is
an array of arrays, thats what is making this difficult for you.
for (p = 0; p < nr_blocks; p ++) {
for (i = p*4; i < p*4 + 8; i=i+2) {
for (j = 0; j < 4; j++) {
printf(" %d ", array[i*4 + j]);
}
}
}

First
You are describing a 2 dimensional array, but using a 1 dimensional array in your code.
Second
Keep in mind C arrays are row major order. The order you extract elements must obey that construct.
For example, given this 3X4 array: (3 rows, 4 columns)
|1 1 1 1|
|2 2 2 2|
|3 3 3 3|
A C variable to contain such a matrix could be defined as:
int array[3][4]={{1,1,1,1},{2,2,2,2},{3,3,3,3}};
In memory, although it is a 2 dimensional array the elements are stored contiguously (Starting from array[0][0]) like this:
1 1 1 1 2 2 2 2 3 3 3 3
The offset from the beginning of the array to any one element is given by:
offset = row * (number_of_columns) + column;
Working in the opposite way, if you have an element's linear offset, you can get the row or column as follows:
row = offset/(number_of_columns);
column = offset%(number_of_columns);
In the example data you have shown (before you edited your original post), row 1 contains 4 1s, & 4 2s, then row 2: 4 3s & 4 4s, and so on. In extracting, you would have to set your for loop indexes to go from 0 to 3 for each of the 4 rows as you traverse the columns to get the first block. Then use 4 to 7 to traverse the columns again on the same 4 rows to get the second block.
For an 8x8, the same procedure would be used. Just keep in mind the row major order of the array.
Getting the first blocks for 8x8:
int i, j, r=8, c=8;
//first row 2nd 3rd and so on
int array[8][8]={{1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4},{...},{...}, (8 blocks total)...};
for(i=0;i<r/2;i++) //traverse 4 of 8 rows
for(j=0;c/2<j++) //traverse 4 of 8 columns
printf(" %d ", array[i][j]); //note this array is a two dimensional array,
//while you are showing a 1 dimensional array in your example
//(this is only 1 dimensional: array[i*4 + j])
Change indexes accordingly for remaining blocks

Related

MPI Gatherv ordering data incorrectly when different 2-D array sizes

I'm trying to take a N*N 2-D array, have each process be responsible for a number of columns, carry out an action on the elements and gather them back together into a single 2-D array again.
I have managed to divide the columns among the processes, carry out the action and bring them back together using MPI subarrays and Gatherv. However, when I give the program a number of processes that doesn't equally divide into the number of columns, the returned data is misplaced.
With the master matrix being 12x12, I provide four processes and get the correct result back:
FINAL MATRIX
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
1 1 1 2 2 2 3 3 3 4 4 4
When the matrix is still 12x12 and I provide five processes, I get this output:
FINAL MATRIX
1 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 3 3 4 4 5 5
5 1 1 2 2 2 0 0 0 0 0 0
1 1 1 2 2 2 0 0 0 0 0 0
1 1 1 2 2 2 0 0 0 0 0 0
1 1 1 2 2 2 0 0 0 0 0 0
Can someone inform me as to what I've configured incorrectly for this to be the result? Ultimately, after resolving this, I wish to switch the Gatherv to Allgatherv so that each process has the entire 2-D array locally for further alterations.
Update (11/04/2021)
As suggested by Gilles I have attempted to use column vectors instead but could not find a way in which to recombine with Gatherv. I believe my issue with my current solution may be due to displacements as manually altering these causes changes in the output (populating some of the zero cells).
Full code:
#include <stdio.h>
#include <stdlib.h>
#include <mpi.h>
void print_matrix (double ** X, int rows, int cols)
{
for (int i = 0; i < rows; ++i) {
for (int j = 0; j < cols; ++j)
printf ("%.0f ", X[i][j]);
printf ("\n");
}
}
double **alloc_2d_array(int m, int n) {
double **x;
int i;
x = (double **)malloc(m*sizeof(double *));
x[0] = (double *)calloc(m*n,sizeof(double));
for ( i = 1; i < m; i++ )
x[i] = &x[0][i*n];
return x;
}
void main(int argc, char *argv[]) {
int n = 12;
int ndims = 2;
int rank, size;
int root_rank = 0;
MPI_Datatype sendsubarray, recvsubarray, resizedrecvsubarray;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
MPI_Comm_size(MPI_COMM_WORLD, &size);
// Report active to console
printf("Rank: %d, reporting!\n", rank);
// Make master matrix
double ** master_matrix = alloc_2d_array(n, n);
// Set starting values in master matrix
for (int i=0; i<n; i++) {
for (int j=0; j<n; j++) {
master_matrix[i][j] = 0;
}
}
// Calculate sub matrices no. of columns and displacements
int interval, modulus, section_end, section_start, section_length;
int counts[size];
int displs[size];
interval = n/size;
modulus = n % size;
for (int i=0; i < size; i++) {
if (modulus != 0) {
counts[i] = interval+1;
modulus--;
} else {
counts[i] = interval;
}
displs[i] = (i == 0) ? 0 : displs[i-1]+counts[i-1];
}
// Calculate subarray info
int master_size[2] = {n, n};
int subsize[2] = {n, counts[rank]};
int startat[2] = {0, displs[rank]};
// Populate sub matrix in main matrix
for (int i = startat[0]; i < startat[0] + subsize[0]; i++)
for (int j = startat[1]; j < startat[1] + subsize[1]; j++)
master_matrix[i][j] = rank + 1;
// Print adjusted matrix
// printf("ADJUSTED MATRIX\n");
// print_matrix(master_matrix, n, n);
// Create the subarray type for use by each send node (incl. the root):
MPI_Type_create_subarray(ndims, master_size, subsize, startat, MPI_ORDER_C,
MPI_DOUBLE, &sendsubarray);
MPI_Type_commit(&sendsubarray);
// Create the subarray type for use by the receive node (the root):
if (rank == 0) {
MPI_Type_create_subarray(ndims, master_size, subsize, startat, MPI_ORDER_C,
MPI_DOUBLE, &recvsubarray);
MPI_Type_commit(&recvsubarray);
MPI_Type_create_resized(recvsubarray, 0, 1 * sizeof(double),
&resizedrecvsubarray);
MPI_Type_commit(&resizedrecvsubarray);
}
// Gather the send matrices into the receive matrix:
MPI_Gatherv(master_matrix[0], 1, sendsubarray,
master_matrix[0], counts, displs, resizedrecvsubarray,
0, MPI_COMM_WORLD);
if (rank == 0) {
printf("FINAL MATRIX\n");
print_matrix(master_matrix, n, n);
}
MPI_Finalize();
}

Please help me transpose the matrix in C (with dynamic memory allocation)

I have this assignment to get and transpose a matrix using dynamic memory allocation in C
I did it by converting the linear position to (i,j) and swapping i,j
old and new element positions are perfect,
somehow the swap is not working as i intended,
might seem like i'm making others problem solve for me, but i'm blank at this point so help will be really appreciated
Here's the code:
#include <stdio.h>
#include <stdlib.h>
int main(){
int m,n;
printf("Enter the order of matrix, m*n:\n");
scanf("%d %d",&m,&n);
int *matrix_ptr;
matrix_ptr = (int *) malloc(m*n*sizeof(int));
printf("Enter the elements of %d*%d matrix\n",m,n);
for(int i=0; i<m*n; i++){
scanf("%d", matrix_ptr+i);
}
// Transposing the matrix
for(int i=0; i<m*n; i++){
int i_index = i / n;
int j_index = i % n;
// (i_index)*n + j_index gives the linear position
int new_linear_pos = (j_index)*n + i_index;
int temp = *(matrix_ptr + new_linear_pos);
*(matrix_ptr + new_linear_pos) = *(matrix_ptr + i);
*(matrix_ptr + i) = temp;
if(i==0){
printf("\nThe transpose is:\n");
}
printf("%d ", *(matrix_ptr+i));
if((i+1)%n == 0){
printf("\n");
}
}
}
The output:
You are swapping all values twice and you are printing the ones at the beginning of the line after the second swap. The first swap happened with i equal 1 and 2
Let's say you have this matrix at the begin:
1 2 3
4 5 6
7 8 9
swap index 0 with 0 stays the same thing. Prints 1
swap index 1 with 3: prints 4
1 4 3
2 5 6
7 8 9
swap index 2 with 6: prints 7\n
1 4 7
2 5 6
3 8 9
swap index 3 with 1: prints 4
1 2 7
4 5 6
3 8 9
etc...
The solution would be to swap elements only once.
The easiest fix would be a if (i > new_linear_pos) continue; //already swapped

Making an empy Sudoku solver on C

So i got an assignment in class to make an empty sudoku that every time creates a random solution of 9x9.
I got to the point where i get different number each row and column but not on every 3x3 matrix and i cannot figure out how to go on from here.
We didnt learn recursion yet and can use only the libraries listed in the code.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define NINE 9
#define ONE 1
void solve_sudoku(int board[9][9])
{
srand(time(0));
int count = 0;
for (int i = 0;i <= NINE;i++)
{
for (int j = 0;j < NINE;j++)
{
board[i][j] =(rand() % NINE)+ONE;
for (int k = 0;k < 9;k++)
{
int clone_i = i;
int clone_j = j;
while (board[i][k] == board[i][j])
{
if (j == k)
{
break;
}
count++;
board[i][j] = (rand() % NINE) + ONE;
k = 0;
}
while(board[k][j]==board[i][j])
{
if (i == k)
{
break;
}
count++;
board[i][j] = (rand() % NINE) + ONE;
k = 0;
}
if (count > 300 || (board[i][j] == board[i][k] && j != k))
{
for (int i = clone_i;i < clone_i + 1;i++)
for (int l = 0;l < 9;l++)
{
board[i][l] = 0;
}
count = 0;
k = 0;
j = 0;
}
}
}
}
}
void print_sudoku(int board[][9])
{
printf("The soduko solution is: \n");
for (int i = 0;i < NINE;i++)
{
for (int k = 0;k < NINE;k++)
{
printf("%d ", board[i][k]);
}
printf("\n");
}
}
int main()
{
int sud[9][9] = { 0 };
int matrix_size = 9;
solve_sudoku(sud);
print_sudoku(sud);
return 0;
}
I take you to mean that you need to generate random 9 x 9 grids of digits that meet the Sudoku criterion that each row, column and block contains all nine digits. In that case, you are going about it a very difficult way. Perhaps that was inspired by viewing the program as a solver, instead of what it really needs to be: a generator.
Consider that it is easy to write down at least one valid Sudoku algorithmically:
1 2 3 | 4 5 6 | 7 8 9
4 5 6 | 7 8 9 | 1 2 3
7 8 9 | 1 2 3 | 4 5 6
------+-------+------
2 3 4 | 5 6 7 | 8 9 1
5 6 7 | 8 9 1 | 2 3 4
8 9 1 | 2 3 4 | 5 6 7
------+-------+------
3 4 5 | 6 7 8 | 9 1 2
6 7 8 | 9 1 2 | 3 4 5
9 1 2 | 3 4 5 | 6 7 8
Now consider that you can always transform one valid Sudoku into a different one by swapping two rows or two columns such that no entries move from one block to another. For example, you can swap the first row with the third, or the fifth column with the sixth. If you perform a bunch of random swaps of that kind on a valid starting Sudoku then you will end up with a random grid that meets the Sudoku criteria.
Note that it is a different story if you need to produce only Sudoku that can be solved by deduction alone, without trial & error. For that you probably do need a solver-based approach, but that starts with a bona fide solver, and nothing in your code is anything like that.

Place an array as an element to another array in C

I'm new to C and I'm having a hard time grasping the concept of making arrays.
I created the first 2d array to get the inputs by initializing the maximum possible entries I can have.
int max;
scanf("%d", &max);
int(*first)[n] = malloc(sizeof(int[n][n]));
After encoding the inputs, I have different unused space for every first[i] since each has different length. I received a memory limit exceeded so I would like to remove unused spaces. So, I created the second array and was planning to copy only the used spaces in the first array but I can't initialized the second array.
int second[n];
for (int i = 0; i < n; i++)
{
int len = length of first[i];
int length[len];
second[i] = length;
}
There are specialized data structures optimized for these cases, like sparse matrix, but they may be a bit difficult to implement depending on your level of knowledge.
An easy solution (at the cost of fragmenting the memory) is to use the first element of each row as a sentinel indicating the number of columns that the row is going to have, I omit the error checks for brevity:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
srand((unsigned)time(NULL));
size_t rows = (size_t)(rand() % 10 + 10);
int **array = malloc(sizeof *array * rows);
for (size_t row = 0; row < rows; row++)
{
int cols = rand() % 10 + 1;
array[row] = malloc(sizeof **array * (size_t)(cols + 1));
array[row][0] = cols;
for (int col = 1; col < cols + 1; col++)
{
array[row][col] = rand() % 10;
}
}
for (size_t row = 0; row < rows; row++)
{
int cols = array[row][0];
printf("%d cols: ", cols);
for (int col = 1; col < cols + 1; col++)
{
printf("%d ", array[row][col]);
}
printf("\n");
free(array[row]);
}
free(array);
return 0;
}
Output:
9 cols: 7 7 4 7 4 7 5 6 9
2 cols: 6 6
3 cols: 4 6 7
2 cols: 4 6
6 cols: 4 0 9 3 6 0
7 cols: 0 7 2 9 4 1 3
2 cols: 6 0
9 cols: 2 0 9 0 8 2 4 4 1
9 cols: 0 7 5 7 8 4 2 4 6
9 cols: 4 3 3 3 8 4 8 1 2
2 cols: 0 4
2 cols: 1 5
2 cols: 5 1
7 cols: 6 1 8 4 6 5 4
3 cols: 7 0 9
9 cols: 6 2 3 2 2 7 0 6 0
When you have a 2D array and don't know the size of each element, make an array of pointers. Then allocate exactly as much memory you need for each individual element.
A simple example would be storing each line of a file. Each line is an array of characters, but you don't know how long a line can be. It would be a huge waste to allocate a 2D array large enough to hold the biggest possible line. Instead, allocate a char **. This will be a list of char * strings.
const int max_lines = 1024;
char **lines = malloc(sizeof(char*) * max_lines);
This is 1024 pointers. Each pointer is only 4 or 8 bytes. So only about 8k of memory. There are ways to also avoid needing to allocate a fixed size here, but that's another answer.
Then read each line and only store as much as you need for each line.
int i = 0;
char line[BUFSIZ];
while( fgets(line, sizeof(line), stdin) ) {
lines[i] = strdup(line);
i++;
}
line is allocated using BUFSIZ to be large enough to fit most any line. And we reuse that to read lines of the file. But instead of storing all that extra memory, we use strdup to copy the line to the minimum memory and store a pointer to that in lines.

Is this logical approach right for my program?

Program - Rotating matrix 90 degrees clockwise.
I am a beginner in coding. I came across this question on GeeksforGeeks. I found the solutions very complex so tried applying my logic. But I don't know if my logic is appropriate for the program. Kindly guide me.
#include<stdio.h>
int main()
{
int A = 0 , a = 0 , b = 0;
int arr[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
printf("90 Degree rotation: \n");
printf("\n");
for(A = 2; A >= 0; A--)
{
for(a = 0; a < 3 ; a++)
{
for(b = 0; b < 3 ; b++)
{
if(b==A)
printf("%d\t",arr[a][b]);
}
}
printf("\n");
}
}
Input
1 2 3
4 5 6
7 8 9
Output
3 6 9
2 5 8
1 4 7
This is you matrix, with the axis you chose :
b ->
a 1 2 3
| 4 5 6
V 7 8 9
That is, for a fixed a for instance, if you increase b, you print "the next number" (provided b is not 2). Similarly, if you increase a with the same b, you take the same column, but the next line.
So, you can have the following pseudo program, to print a full column (on a line):
print_column(b):
for a from 0 to 2
print arr[a][b]
print newline
What do you want ? You want to print the following :
3 6 9
2 5 8
1 4 7
That is printing the last column, then the middle one, then the first one, which is done by the following pseudo-program:
print the 3rd column of arr
print the 2nd column of arr
print the 1st column of arr
or, more concisely :
for b from 2 to 0
print the b-th column of arr.
So, the final pseudo code is (inlining the print_column procedure):
for b from 2 to 0
for a from 0 to 2
print arr[a][b]
print newline
Or, in C:
for(b = 2; b >= 0 ; b--)
{
for(a = 0; a < 3 ; a++)
{
printf("%d\t",arr[a][b]);
}
printf("\n");
}

Resources