C - Nested loops and stack? - c

I am trying to find the location of a target inside of a 1-D array that acts like a table with rows and cols. I could do it using divide and mod, but I am stuck on finding it using nested loops. specifically, I can't seem to assign values inside the nested loop.
here is my code:
#include <stdio.h>
int main()
{
int arr[9] = // act as a 3 X 3 table
{ 2, 34, 6,
7, 45, 45,
35,65, 2
};
int target = 7;// r = 1; c = 0
int r = 0; // row of the target
int c = 0; // col of the target
int rows = 3;
int cols = 3;
for (int i = 0; i < rows; i++){
for (int j = 0; j + i * cols < cols + i * cols; i++ ){
if (arr[j] == target){
c = j; // columns of the target
r = i; // rows of the target
}
}
}
printf ("%d, %d",c, r);
return 0;
}
The code outputs: 0,0.

The problem isn't with the assignment, it's with the wrong loop and if condition.
The outer loop should loop over the i rows
The inner loop should loop over the j columns
within both loops, the cell to evaluate is i * cols + j
Put it all together and you'll get:
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++ ) {
if (arr[i * cols + j] == target) {
c = j; // columns of the target
r = i; // rows of the target
}
}
}

Since arr is 1D array and inside for loop, for any i value j will reach upto max 3 only so its not checking after arr[3]
To avoid this problem take int pointer and points to arr and do the operation as below
int *p = arr;
for (i = 0; i < rows; i++){
for ( j = 0; j < cols ; j++ ){
if (p[j] == target){
c = j; // columns of the target
r = i; // rows of the target
}
}
p = p + j;/*make p to points to next row */
}

A better solution would use only one loop:
for (int i = 0; i < rows * cols; i++){
if (arr[i] == target){
r = i / 3;
c = i % r;
}
}

Related

shift matrix columns in c

how can i shift each column of a matrix to the left by the row number ?
for example
0, 1, 2, 3
4, 5, 6, 7
8, 9,10,11
12,13,14,15
this is a 4*4 matrix, the index of the first row is 0, therefore the columns will not move,
the second row's index is 1, therefore each column will move 1 spot to the left (cyclically).
the output for the given matrix is
example
my function code is:
void ShiftRows(int message[M][M])
{
int temp = 0;
for (int i = 1; i < M ; i++)
{
for (int j = 0; j < M; j++)
{
temp = message[i][(j-i)%M];
message[i][(j-i)%M] = message[i][j];
message[i][j] = temp;
}
temp = 0;
}
}
You only swap 2 values. That does not work for cyclically shift a whole row.
void ShiftRows(int message[M][M])
{
for (int i = 1; i < M ; i++)
{
int temp[M];
// First shift using a copy
for (int j = 0; j < M; j++)
{
temp[j] = message[i][(j+i)%M];
}
// After whole row is shifted, copy back
for (int j = 0; j < M; j++)
{
message[i][j] = temp[j];
}
}
}

Printing unique values of the array in C

I wrote a function creating a dynamic array of random values and another function creating a new array consisting of unique values of the previous array. The algorithm used counts unique values correctly. However, I faced a problem in printing all values. In the example below the program printed 7 2 12714320 4 5 instead of 7 2 4 5 6 .
This is the program which can be tested:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int *delduplicate(int *v, int size_old, int *size_new);
main()
{
int n;
int *norepeat;
float *results;
int dim, size_norepeat, i;
int a[7] = {7,2,2,4,5,6,7};
norepeat = delduplicate(a, 7, &size_norepeat);
for (int i = 0; i < size_norepeat; i++)
printf("%d ", norepeat[i]);
}
// delduplicate function
int *delduplicate(int *v, int size_old, int *size_new)
{
int i, j, k = 1, uniques = 1, repeats, *new_v, temp;
// count the number of unique elements
for (i = 1; i < size_old; i++)
{
int is_unique = 1;
for (j = 0; is_unique && j < i; j++)
{
if (v[i] == v[j])
is_unique = 0;
}
if (is_unique)
uniques++;
}
*size_new = uniques;
// create new array of unique elements
new_v = (int*) malloc(*size_new * sizeof(int));
// fill new array with unique elements
new_v[0] = v[0];
for (i = 1; i < size_old; i++)
{
int is_unique = 1;
for (j = 0; j < i; j++)
{
if (v[i] == v[j])
is_unique = 0;
}
if (is_unique)
new_v[k] = v[i];
k++;
}
return new_v;
}
The problem should be happening here:
// fill new array with unique elements
new_v[0] = v[0];
for (i = 1; i < size_old; i++)
{
int is_unique = 1;
for (j = 0; j < i; j++)
{
if (v[i] == v[j])
is_unique = 0;
}
if (is_unique)
new_v[k] = v[i];
k++;
}
Your problem is probably occurring in the following section -
if (is_unique)
new_v[k] = v[i];
k++;
Here you are incrementing k at each iteration. However, you only want to increment it whenever you have found a unique element. if() without brackets only considers the first statement. So change it to this -
if (is_unique){
new_v[k] = v[i];
k++;
}
This change should make your program run fine.
Side Note : If you do not want to use brackets for an if() , for() , etc, you can separate the statements by commas and use without having the brackets. Like this -
if (is_unique)
new_v[k] = v[i],
k++;

How to correctly implement an insertion sort algorithm in a 2D array?

I need to sort the columns of my 2D array based on the first row of the array. This is my 2d array before sorting:
cargo
AFADA
DAFGF
DXAFA
DDFFX
GFXF
and this is the image of my 2D array:
acrgo
FAADA
ADFGF
XDAFA
DDFFX
FGXF
The correct output looks like this
acgor
FADAA
ADGFF
XDFAA
DDFXF
FGF X
. This is the code of my function to sort the array using insertion sort algorithm
void sort(char** newTable, int row, int col) {
for (int top = 1; top < col; col++) {
char item = newTable[0][top];
int i = top;
while (i > 0 && item < newTable[0][i - 1]) {
for (int j = 0; j < row + 1; j++) {
char temp = newTable[j][i];
newTable[j][i] = newTable[j][i - 1];
newTable[j][i - 1] = temp;
}
i--;
}
newTable[0][i] = item;
}
}
I called the function like this
sort(newTable, row, strlen(key));
here, key is the string 'cargo'
The definition of newTable:
char** newTable = (char**)calloc(row + 1, sizeof(char*));
for (int i = 0; i < row + 1; i++) {
newTable[i] = (char*)calloc(strlen(key), sizeof(char));
}
newTable is indeed an array of pointers and not a 2D array, so using char **newTable makes sense.
The major error is close to a typo: in the first for loop of sort, you increment col when you want to increment top. And the last line newTable[0][i] = item; is useless.
This should work (even if the loop for (int j = 0; j < row + 1; j++) suggests that row is not the number of rows in newTable but only the number of *additional rows):
void sort(char** newTable, int row, int col) {
for (int top = 1; top < col; top++) {
char item = newTable[0][top];
int i = top;
while (i > 0 && item < newTable[0][i - 1]) {
for (int j = 0; j < row + 1; j++) {
char temp = newTable[j][i];
newTable[j][i] = newTable[j][i - 1];
newTable[j][i - 1] = temp;
}
i--;
}
}
}

Duplicates within 2 arrays

So what i'm doing is populating 2 arrays x_cord and y_cord with a maximum amount of values in each. In this case both arrays can hold a maximum amount of unique elements of 5 and each element must be between 0 and 2. Afterwards once the arrays are completely randomized I am writing the values into a file
It would look something like this:
0 0
1 2
2 1
2 2
0 1
I don't want any of the rows to be duplicates of no another, however I am running into trouble where I am creating duplicates of one another, any help would be appreciated.
Code:
for (j=0; j < num_pt; j++){
(x_cord[j] = rand()%max_x+1);
(y_cord[j] = rand()%max_y);
for(m=j+1; m < num_pt; m++){
if ((x_cord[j]==x_cord[m]) && (y_cord[j]==y_cord[m])){
x_cord[j] = rand()%max_x+1;
}
}
}
for (j=0; j < num_pt;j++){
fprintf(fp, "%d\t%d\n", x_cord[j], y_cord[j]);
}
Rather than repeatedly generating a pair until you find a unique pair, generate all pairs, then shuffle the pairs.
int max_y = 2;
int max_x = 2;
size_t num_eles = (max_x+1)*(max_y+1);
size_t desired_num_eles = 6;
if (desired_num_eles > num_eles)
desired_num_eles = num_eles;
int* y_cord = malloc(sizeof(int) * num_eles);
int* x_cord = malloc(sizeof(int) * num_eles);
for (int y = max_y; y--; ) {
for (int x = max_x; x--; ) {
size_t i = y * max_x + x;
y_cord[i] = y;
x_cord[i] = x;
}
}
for (size_t i = 0; i<desired_num_eles; ++i) {
size_t j = rand() % (num_eles - i) + i;
// Swap i and j
y_cord[i] ^= y_cord[j]; y_cord[j] ^= y_cord[i]; y_cord[i] ^= y_cord[j];
x_cord[i] ^= x_cord[j]; x_cord[j] ^= x_cord[i]; x_cord[i] ^= x_cord[j];
}
num_eles = desired_num_eles;
y_cord = realloc(sizeof(int) * num_eles);
x_cord = realloc(sizeof(int) * num_eles);

Unexpected output at a particular row for a dynamic 2D array

I was solving a programing question for displaying Pascal triangle. In the code, I have set the last element of every row equal to zero. Still, the 6th row produces the output as 50 for the last element. I'm unable to figure out the reason for this. Kindly help. The code is attached.
int ** generate(int A, int *number_of_rows) {
*number_of_rows = A;
int i,j,nc=0;
int **result = (int**)malloc(A * sizeof(int *));
for(i=0;i<A;i++)
{
nc=i+1;
result[i]=(int)malloc(nc*sizeof(int));
result[i][0]=nc;
result[i][1] = 1;
for(j=2;j<nc;j++)
{
result[i][j]=result[i-1][j]+result[i-1][j-1];
}
}
return result;
}
Edit:
The first element of every row displays the number of columns in that row.
#include <stdio.h>
#include <stdlib.h>
int ** generate(int A, int *number_of_cols) {
int **result = malloc(A * sizeof(int *));
int nc;//number of columns
for(int i = 0; i < A; ++i){
number_of_cols[i] = nc = i + 1;
result[i] = malloc(nc * sizeof(int));
result[i][0] = result[i][nc-1] = 1;
if(i > 1)
for(int j = 1; j < nc -1; ++j){
result[i][j] = result[i-1][j-1] + result[i-1][j];
}
}
return result;
}
int main(void){
int n;
scanf("%d", &n);
int *number_of_cols = malloc(n * sizeof(int));
int **pascal_triangle = generate(n, number_of_cols);
for(int i = 0; i < n; ++i){
printf("%*s", 2 * (n-i-1), "");
for(int j = 0; j < number_of_cols[i]; ++j){
printf("%4d", pascal_triangle[i][j]);
}
puts("");
free(pascal_triangle[i]);
}
free(pascal_triangle);
free(number_of_cols);
return 0;
}
I can't understand the purpose of passing the *number_of_row just to assign it the other parameter address. However, I'd split your main for loop in 2:
one to allocate all memory and another to fill it.
for(i=0;i<A;i++)
result[i]=(int)malloc((i+1)*sizeof(int));
result[0][0]=1; //in your code, result[i-1] was accessed with i=0
for(i=1;i<A;i++) {
result[i][0] = i+1;
result[i][1] = 1;
for(j=2;j<i;j++)
result[i][j] = result[i-1][j] + result[i-1][j-1]; //when j reaches the last value,
//[i-1][j] won't work! So put j<i instead.
result[i][j] = 1;
}
The rest of code was OK, check if this is what you wanted. The resulting triangle shoud be:
1
2 1
3 1 1
4 1 2 1
5 1 3 3 1
6 1 4 6 4 1 etc.

Resources