Check if the array is a lower triangular matrix - c

Write a function in c that takes a single 2d nxn matrix. If the matrix is a lower triangular matrix, the program should output 1 and output 0 if it is not a lower triangular matrix.
Here is my code.
// function code
#include <stdio.h>
#include <stdlib.h>
#define NUMS 5
int isLowerTriangularMatrix(int array[NUMS][NUMS]) {
for (int row = 0; row < NUMS; row++) {
for (int col = 0; col < NUMS; col++) {
if (row > col && array[row][col] == 0) {
return 1;
}
else {
return 0;
}
}
}
}
// test code
int main(void) {
int matrix[5][5] = {{1,2,3,4,5},
{7,8,9,2,3},
{7,8,9,2,3},
{7,8,9,2,3},
{7,8,9,2,3}};
int result = isLowerTriangularMatrix(matrix, 5);
printf("%d", result);
return 0;
}
My question is that how to modify my code?
Here is the compiler warnings
q23.c:16:1: warning: control reaches end of non-void function [-Wreturn-type]
16 | }

The warning is spurious. Or rather, it should have issued a different warning, one that indicated you have code that will never be executed.
That is to say that while your code doesn't suffer from the identified problem, it is nonetheless incorrect. It always returns zero. The first pass through the loops, you check if row > col. Since it's false, you execute the else clause and return zero.
You shouldn't be returning 0 in that case. But you shouldn't be returning 1 either. You can only return 1 after you've checked the entire matrix, so the return 1 should be outside the loops.
This fixes these problems:
int isLowerTriangularMatrix( int array[ NUMS ][ NUMS ] ) {
for ( int row = 0; row < NUMS; ++row ) {
for ( int col = 0; col < NUMS; ++col ) {
if ( col > row && array[ row ][ col ] != 0 ) {
return 0;
}
}
}
return 1;
}
There's one last issue to address, and it's the needless "visiting" of cells in the lower triangle. It's trivial to skip these.
int isLowerTriangularMatrix( int array[ NUMS ][ NUMS ] ) {
for ( int row = 0; row < NUMS; ++row ) {
for ( int col = row+1; col < NUMS; ++col ) {
if ( array[ row ][ col ] != 0 ) {
return 0;
}
}
}
return 1;
}

As I mentioned in my top comments ...
For your original question as to how to initialize a matrix:
With an initializer:
int mtx[3][3] = {
{ 3, 9, 7 },
{ 0, 5, 6 },
{ 0, 0, 1 }
};
Or, with assignment statements:
int mtx[3][3];
mtx[0][0] = 3;
mtx[0][1] = 9;
mtx[0][2] = 7;
mtx[1][0] = 0;
mtx[1][1] = 5;
mtx[1][2] = 6;
mtx[2][0] = 0;
mtx[2][1] = 0;
mtx[2][2] = 1;
#Craig Estey Yes, it is a method, but it also means the n not working very well on my code. –
Cedric xu
You do not have a true 2D int array. You have a 1D array of int * to int arrays. Do this instead:
#define NUMS 5
int mtx[NUMS][NUMS];
You can define the function as:
int isLowerTriangularMatrix(int arr[NUMS][NUMS])
Or, if you want the function to handle the size dynamically:
int isLowerTriangularMatrix(int n,int arr[n][n])
The first one will be a bit faster and the second a bit more flexible [albeit a bit slower].
Edit: Your function is being [correctly] flagged as reaching the end of the function and not having a return statement. It can't [seem to] determine that the code will always do one of the return statements inside the loops. Note that both gcc and clang flag it the same way.
I'm not sure your function will return a valid result because the if does a return on both the if and the else. So, it will never examine all the elements [that it needs to].
Usually, the inner return is just on the if part. Then, at the function bottom do: (e.g.) return 1;
Here's a refactored version:
// function code
#include <stdio.h>
#include <stdlib.h>
#define NUMS 5
int
isLowerTriangularMatrix(int array[NUMS][NUMS])
{
// we only need to probe the upper right part of the matrix
// if we see non-zero, it's _not_ triangular
for (int row = 0; row < NUMS; row++) {
for (int col = row + 1; col < NUMS; col++) {
//printf("arr[%d][%d] = %d\n",row,col,array[row][col]);
if (array[row][col] != 0)
return 0;
}
}
return 1;
}
// test code
int
main(void)
{
// this is _not_ a triangular matrix
int matrix[5][5] = {
{1, 2, 3, 4, 5},
{7, 8, 9, 2, 3},
{7, 8, 9, 2, 3},
{7, 8, 9, 2, 3},
{7, 8, 9, 2, 3}
};
int result = isLowerTriangularMatrix(matrix);
printf("%d\n", result);
// this _is_ a triangular matrix
int m2[5][5] = {
{ 1, 0, 0, 0, 0 },
{ 3, 1, 0, 0, 0 },
{ 4, 5, 1, 0, 0 },
{ 7, 6, 2, 1, 0 },
{ 8, 9, 7, 3, 1 }
};
result = isLowerTriangularMatrix(m2);
printf("%d\n", result);
return 0;
}
Here is the program output (with the debug printf):
arr[0][1] = 2
0
arr[0][1] = 0
arr[0][2] = 0
arr[0][3] = 0
arr[0][4] = 0
arr[1][2] = 0
arr[1][3] = 0
arr[1][4] = 0
arr[2][3] = 0
arr[2][4] = 0
arr[3][4] = 0
1

Related

Can I replace my Nested if loop with something more efficient?

I try to figure out how many 1, 2, 3, 4 and 5 there is by using a for loop and if else statement. My question is: is there a more efficient way of writing it?
int A[15] = {1,5,4,1,3,1,3,4,5,2,3,2,5,3,2};
int B[5] = {};
for (int i = 0; i <= 14; i++)
{
if (A[i] == 1)
{
B[0]++;
}
else if (A[i] == 2)
{
B[1]++;
}
else if (A[i] == 3)
{
B[2]++;
}
else if (A[i] == 4)
{
B[3]++;
}
else if (A[i] == 5)
{
B[4]++;
}
}
int[] a = {1, 5, 4,...};
int[] b = new int[5];
for (int n: a) {
assert 1 <= n && n <= 5;
b[n - 1]++;
}
n will be set to every element of a.
Array elements are initialized with 0, 0.0, false, null, that is the default value of the type.
You used square brackets in a C/C++ compatible syntax. Normally the more logical notation above is used: part of the type.
Variable and function names start with a small letter by convention, and names are in camelCase.
int[] studentScores =
Asserts one rarely sees: my bad conscience for the assumption no value is out of range.
Provided that the elements of array A are greater than 0:
#include <stdio.h>
int main()
{
int A[15] = { 1, 5, 4, 1, 3, 1, 3, 4, 5, 2, 3, 2, 5, 3, 2 };
int B[5] = { 0, 0, 0, 0, 0 };
for (int i = 0 ; i < sizeof(A)/sizeof(A[0]) ; i++)
++B[A[i] - 1];
for (int i = 0 ; i < sizeof(B)/sizeof(B[0]) ; i++)
printf("%d ", B[i]);
return 0;
}
This code produces the following output:
3 3 4 2 3

How to check if two arrays have the same set of digits in C?

I want to check if two integer type arrays have the same set of digits. For example, if array 1 is 5 1 2 3 3 4 6 1, and array 2 is 1 2 3 4 5 6, the program returns 1. If any number from either array isn't in the second one, the program returns a 0.
I tried doing something like this, but I can't get it to work:
#include <stdio.h>
int main()
{
int i, j, a[8]={5, 1, 2, 3, 3, 4, 6, 1}, b[6]={1, 2, 3, 4, 5, 6}, x=0;
for(i=0; i<6; i++)
{
for(j=0; j<8; j++)
{
if(a[j]==b[i])
{
x=1;
continue;
}
else
{
x=0;
break;
}
}
}
return x;
}
EDIT:
Thank you Some programmer dude
#include <stdio.h>
void sort(int arr[], int n)
{
int i, j, a;
for (i=0; i<n; i++)
{
for (j=i+1; j<n; j++)
{
if (arr[i]>arr[j])
{
a=arr[i];
arr[i]=arr[j];
arr[j]=a;
}
}
}
}
int main()
{
int i, j, k;
int a[8]={5, 1, 2, 3, 3, 4, 6, 1};
int b[6]={1, 2, 3, 4, 5, 6};
int na=8, nb=6;
for(i=0; i<na; i++) // removing duplicates from a
{
for(j=i+1; j<na; j++)
{
if(a[i]==a[j])
{
for(k=j; k<na; k++)
{
a[k]=a[k+1];
}
na--;
j--;
}
}
}
for(i=0; i<nb; i++) // removing duplicates from b
{
for(j=i+1; j<nb; j++)
{
if(b[i]==b[j])
{
for(k=j; k<nb; k++)
{
b[k]=b[k+1];
}
nb--;
j--;
}
}
}
sort(a, na);
sort(b, nb);
if(na!=nb)
return 0;
for(i=0; i<na; i++)
{
if(a[i]!=b[i])
return 0;
}
return 1;
}
You have several ways you can approach this, you can use two sets of nested loops swapping the order you loop over the two arrays validating each element is found in the other. Two full sets of nested loops are needed as you have a 50/50 chance any single outlier will be contained in either of the arrays. This is the brute-force method and has the potential worst-case number of iterations.
Since an outlier is what drove the need for looping with one arrays as outer and the other inner and then swapping a repeating, e.g. to catch 5, 1, 2, 3, 3, 4, 6, 1 and 1, 2, 3, 4, 5, 6, 7, if you can catch the outlier with another method that requires fewer iterations you can make your algorithm more efficient.
An outlier would be detected in a comparison of the min and max from each array, and to find min and max only requires a single linear traversal of each array. Much better than the worst-case nested loop over all elements.
The min and max check provide a way to shorten your work, but do not eliminate the need to press forward with a second set of nested loops if the result is inconclusive at that point. Why? Consider the following sets, where the min and max are equal, but one element within the range is not included in both arrays, e.g.:
int a[] = { 5, 1, 2, 3, 3, 4, 6, 112 },
b[] = { 1, 2, 3, 4, 5, 6, 7, 112 };
The only way the 7 will be detected is by nested loop with the array containing 7 being the outer loop.
So you could write a short function to test for the common set as:
#include <stdio.h>
#include <limits.h>
int commonset (int *a, int *b, int sza, int szb)
{
int maxa = INT_MIN, maxb = INT_MIN,
mina = INT_MAX, minb = INT_MAX;
for (int i = 0; i < sza; i++) { /* find max/min of elements of a */
if (a[i] > maxa)
maxa = a[i];
if (a[i] < mina)
mina = a[i];
}
for (int i = 0; i < szb; i++) { /* find max/min of elements of b */
if (b[i] > maxb)
maxb = b[i];
if (b[i] < minb)
minb = b[i];
}
if (maxa != maxb || mina != minb) /* validate max & mins equal or return 0 */
return 0;
for (int i = 0; i < sza; i++) { /* compare of each element between arrays */
int found = 0;
for (int j = 0; j < szb; j++)
if (a[i] == b[j]) {
found = 1;
break;
}
if (!found)
return 0;
}
for (int i = 0; i < szb; i++) { /* compare of each element between arrays */
int found = 0;
for (int j = 0; j < sza; j++)
if (a[j] == b[i]) {
found = 1;
break;
}
if (!found)
return 0;
}
return 1;
}
Adding a short example program:
int main (void) {
int a[] = { 5, 1, 2, 3, 3, 4, 6, 1 },
sza = sizeof a / sizeof *a,
b[] = { 1, 2, 3, 4, 5, 6 },
szb = sizeof b / sizeof *b,
result;
result = commonset (a, b, sza, szb);
if (result)
puts ("arrays have common set of numbers");
else
puts ("arrays have no common set of numbers");
return result;
}
Example Use/Output
$ ./bin/arr_commonset
arrays have common set of numbers
$ echo $?
1
With b[] = { 1, 2, 3, 4, 5, 6, 7 }:
$ ./bin/arr_commonset
arrays have no common set of numbers
$ echo $?
0
With a[] = { 5, 1, 2, 3, 3, 4, 6, 112 } and b[] = { 1, 2, 3, 4, 5, 6, 7, 112 }:
$ ./bin/arr_commonset
arrays have no common set of numbers
$ echo $?
0
There are probably even ways to combine the two and shave off a few iterations, and, if you have a guaranteed range for your input sets, you can use a simple frequency array for each and then two simple linear iterations would be needed to increment the element that corresponds to the index for each value in the array, and then a third linear iteration over both frequency arrays comparing that like indexes either both are non-zero or both are zero to confirm the common set -- that is left to you.
Look things over and let me know if you have any further questions.

Why it is this program not finding pairs in an array that sum to a given value?

My code so far:
#include<stdio.h>
int main() {
int a[5][5] = {
{-1, 2, 3, 4 },
{ 5, 3, -2, 1 },
{ 6, 7, 2, -3 },
{ 2, 9, 1, 4 },
{ 2, 1, -2, 0 }
};
int sum = 11;
int i, j;
for (i = 0; i < 5; i++) {
for (j = 0; j < 5; j++) {
if (a[i][j] + a[j][i] == sum && i != j) {
printf("%d %d\n", i, j);
}
}
}
}
I want to find pairs with given sum such that elements of pair are in different rows.
Note that a is a 5x5 array with an extra column of zeros. That has a benign effect.
Your algorithm is faulty! If you adjust your conditional to
if (a[i][j] + a[j][i] == sum && i != j) {
printf("Yes %d %d\n", i, j);
} else {
printf("No %d %d\n", i, j);
}
it becomes obvious that you are not considering the sum of every possible pair. The ones that get missed out are, by coincidence, the pairs that sum to 11.
Essentially you need 4 nested loops, and you need to consider every number with every other number in the array.
First, you should notice that you defined a 5X5 int array but only filled in 4 ints in each sub-array. If you would print out your array, you'll see the values are:
-1 2 3 4 0
5 3 -2 1 0
6 7 2 -3 0
2 9 1 4 0
2 1 -2 0 0
I guess that wasn't your intention...
Now, for your question - you want to find a[i][j] + a[j][i] == 11 for i!=j. The reason you get no output is because there aren't such elements that satisfy your conditions in the array you defined.
Below program will solve your problem,
#include<stdio.h>
int main()
{
int a[5][5] = {
{-1, 2, 3, 4 },
{ 5, 3, -2, 1 },
{ 6, 7, 2, -3 },
{ 2, 9, 1, 4 },
{ 2, 1, -2, 0 }
};
int sum=11,i,j,k,l;
for(i=0;i<5;i++)
{
for(j=i+1;j<5;j++)
{
for(k=0;k<5;k++)
{
for(l=0;l<5;l++)
{
if(a[i][k]+a[j][l]==sum)
printf("a[%d][%d] = %d\ta[%d][%d] = %d\n",i,k,a[i][k],j,l,a[j][l]);
}
}
}
}
}
if you want "pairs with given sum such that elements of pair are in different rows." then you should try code like this:
#include<stdio.h>
int main()
{
const int rows = 5;
const int cols = 4;
int sum = 11;
int i, j, i1, j1;
int a[rows][cols] =
{
{-1, 2, 3, 4 },
{ 5, 3, -2, 1 },
{ 6, 7, 2, -3 },
{ 2, 9, 1, 4 },
{ 2, 1, -2, 0 }
};
for(i = 0; i < rows; i++)
for(j = 0; j < cols; j++)
for(i1 = i + 1; i1 < rows; i1++)
for(j1 = 0; j1 < cols; j1++)
if(a[i][j] + a[i1][j1] == sum)
printf("[%d %d](%d); [%d %d](%d)\n", i, j, a[i][j], i1, j1, a[i1][j1]);
}

Moving all zeros to the begining of array

I'm trying to write a function which moves all numbers from begining of array to the end of it. order should not change.
for example i have this array:
1, 2, 3, 4, 5, 0, 0, 0, 0
i want to change it to:
0, 0, 0, 0, 1, 2, 3, 4, 5
I already wrote a version of it but it can't keep the order. (array[] is original and a[] is sorted)
#include <stdio.h>
#define SIZE_MAX 20
int main()
{
int array[SIZE_MAX] = {1, 2, 3, 4, 5, 0, 0, 0, 0};
int a[SIZE_MAX];
int i;
int p = 0;
for (i = SIZE_MAX-1; i >= 0; i--, p++)
{
a[i] = array[p];
}
for (i = 0; i < SIZE_MAX; i++)
{
printf("%d", a[i]);
}
}
One option would be to loop through the array twice, first copying over the zeros, then the rest of the values:
#include <stdio.h>
#define SIZE_MAX 10
int main()
{
int array[SIZE_MAX] = {1, 2, 0, 0, 3, 4, 5, 0, 0, 0};
int a[SIZE_MAX];
int i;
int p = 0;
for (i = 0; i < SIZE_MAX; ++i) {
if (array[i] == 0) {
a[p++] = 0;
}
}
for (i = 0; i < SIZE_MAX; ++i) {
if (array[i] != 0) {
a[p++] = array[i];
}
}
for (i = 0; i < SIZE_MAX; i++) {
printf("%d", a[i]);
}
}
I changed SIZE_MAX to 10, so that it matches the number of elements in the array.
The sentence "I'm trying to write a function which moves all numbers from beginning of array to the end of it." sounds like it should be done in place - and it turns out with this problem it is quite easy to do an in-place algorithm. Note that unlike other algorithms here, this just scans the array once, and writes the array once. Here I wrote it into a function:
void relocate_zeroes(size_t length, int *array) {
int *target = array + length - 1;
int *source = target;
for (; source >= array; source--) {
if (*source) {
*target-- = *source;
}
}
while (target >= array) {
*target-- = 0;
}
}
Basically we scan the source array once from end to beginning; and if we meet a non-zero integer, we relocate it just before the previous non-zero integer. When the whole array has been scanned, the area between the base (array) and target is filled with zeroes.
In the beginning both target and source point to the last value of the array; if the *source is not 0, we replace *target with *source; that is, if the last element is non-zero, we replace it by itself and decrease both target and source pointers; if the last element is 0, we don't copy it anywhere, only decrease the source pointer; continuing this way at the end we have copied all non-zero elements, and we can fill the remaining array elements with zeroes.
Given program:
#define SIZE_MAX 9
int main() {
int array[SIZE_MAX] = {1, 0, 2, 3, 0, 4, 0, 0, 5};
int i;
relocate_zeroes(SIZE_MAX, array);
for (i = 0; i < SIZE_MAX; i++) {
printf("%d ", array[i]);
}
}
The output will be
0 0 0 0 1 2 3 4 5
If the 2-array version is required, then this is easy to modify for that too:
void relocate_zeroes(size_t length, int *source_array, int *target_array) {
int *target = target_array + length - 1;
int *source = source_array + length - 1;
for (; source >= source_array; source--) {
if (*source) {
*target-- = *source;
}
}
while (target >= target_array) {
*target-- = 0;
}
}
If you need all the 0 at the beginning and rest of the numbers in same order try this :
#include <stdio.h>
#define SIZE_MAX 9
int main()
{
int array[SIZE_MAX] = {1, 2, 3, 4, 5, 0, 0, 0, 0};
int a[SIZE_MAX];
int i;
int temp[SIZE_MAX];
int ind1=0,ind2=0;
// separating all the 0's and store it at the beginning
for (i = 0; i < SIZE_MAX; i++)
{
if(array[i]==0)
a[ind1++]=0;
else
temp[ind2++]=array[i];
}
// storing rest of the numbers in order
for (i = 0; i < ind2; i++)
{
a[ind1++]=temp[i];
}
for (i = 0; i < SIZE_MAX; i++)
{
printf("%d", a[i]);
}
}
NOTE:
first i stored all the 0's in the result array and in the meantime all the non zero value are being stored in temp array.
later, i just merged the temp array to the result array.
Integer fullArray[] = { 1, 10, 20, 0, 59, 63, 0, 88, 0 };
for (int i = 0; i <= fullArray.length - 1; i++) {
if (fullArray[i] == 0 && i > 0) {
int temp = fullArray[i - 1];
if (temp != 0) {
fullArray[i - 1] = 0;
fullArray[i] = temp;
i = -1;
}
}
}
System.out.println(Arrays.asList(fullArray).toString());
Here is an in-place method using swap()
#include <stdio.h>
#define SIZE_MAX 20
swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
moveZerosLeft(int length, int *array)
{
int i = 0;
int cur = length - 1;
for( i = length - 1; i >= 0; --i)
if(array[i] != 0)
{
swap(&array[i], &array[cur--]);
}
}
int main()
{
int array[SIZE_MAX] = {1, 2, 3, 4, 5, 0, 0, 0, 0};
int i;
int length = 9;
moveZerosLeft(length, array);
// display the result
for(i = 0; i < length; i++)
{
printf("%d ", array[i]);
}
}
We scan from the right of the array to the left. When we see a non-zero value, we swap it with a zero which we saw previously.
This method requires only 1 scan of the array.
public class Demo{
public static void moveZeros() {
int[] num = {1, 0, 0 , 6, 7, 0};
int temp=-1;
for (int i = 0; i < num.length;i++)
{
if(num[i]!=0)
{
++temp;
if(num[temp] ==0){
int val = num[i];
num[i]=num[temp];
num[temp]=val;
}
else
{
num[temp]=num[i];
}
}
}
}
public static void main(String args[])
{
Demo.moveZeros();
}
}

Function to left shift a 2D array in C

I'm writing a function within my program to left shift all the numbers in an array that was passed to the function. An example is:
1 2 3
4 5 6
becomes
2 3 4
5 6 1
My code is:
void LeftShift(int array[][N])/*Get the array from main*/
{
int r, c, temp;
for(r = 0; r < M; r++) { //Start at row 0 and add one each time
for(c = 0; c < N; c++) { //Start at column 0 and add one each time
if(c > 0) {
array[r][c] = array[r][c-1]; //Number is moved over one if its not the first column
}
else if(c == 0 && r > 0) { //If its first column but not first row
array[r][c] = array[r-1][N-1];//Move number up one row and too last column
}
else {
temp = array[r][c];//If its first column and first row store value in temp
}
}
}
array[M-1][N-1] = temp;//Put temp value at end of array
}
When I print this out all I get is the first number from the original array in every spot in the array. M is defined at the top to be 6 and N is defined to be 5. After this runs, I call a function that prints out the new array and all I get is the first value 30 times in an array.
2-D arrays are contiguous in memory, so you can iterate over it as if it were a 1-D array:
void left_rotate(int array[][N])
{
int *flat = (int *)array;
int temp = flat[0];
for ( size_t i = 1; i < M*N; ++i )
flat[i-1] = flat[i];
flat[M*N-1] = temp;
}
The for loop could also be replaced with a single block move:
memmove(&flat[0], &flat[1], (M*N-1) * sizeof *flat);
array[r][c] = array[r][c-1];
should be
array[r][c-1] = array[r][c];
Likewise for the row shift.
You can go throw the array, having a pointer following the last place you visited, and moving the elements, as in this example:
#define nrows 4
#define ncols 4
int array[nrows][ncols] = {
{ 1, 2, 3, 4, },
{ 5, 6, 7, 8, },
{ 9, 10, 11, 12, },
{ 13, 14, 15, 16, },
};
int main()
{
int row, col;
int saved_int;
int *p = &saved_int;
/* rotate elements */
for(row = 0; row < nrows; row++)
for (col = 0; col < ncols; col++) {
*p = array[row][col];
p = &array[row][col];
} /* for */
*p = saved_int;
/* print matrix */
for (row = 0; row < nrows; row++) {
for (col = 0; col < ncols; col++)
printf( "%s%d",
(col ? "\t" : ""),
array[row][col]);
printf("\n");
} /* for */
return 0;
} /* main */

Resources