Hi everyone I made some changes in the code so that it's easy to understand, looks what I have so far, I kept the function's prototype at the beginning of the code and it works fine, but it just works fine just when I try a 2x2 matrix because if I try a 3x3, 4x4 or 6x6 matrix it does not works fine the determinant is not calculated right, I guess that's the problem the determinant but I don't know how to solve it. Here is the code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<math.h>
float determinant(int tam,float [][tam]);
void cofactor(int tam,float [][tam]);
void transpose(int tam,float [][tam],float [][tam]);
int validate(){
int val;
char *buf = (char *) malloc(10);
memset(buf,0,10);
while(fgets(buf, 10, stdin) != NULL ){
if(buf[0]!='\n') {
val = atoi(buf);
break;
}
}
free(buf);
return val;
}
float determinant(int tam, float matrix[][tam])
{
float s = 1, det = 0, b[tam][tam];
int i, j, m, n, c;
if (tam == 1)
{
return (matrix[0][0]);
}
else
{
det = 0;
for (c = 0; c < tam; c++)
{
m = 0;
n = 0;
for (i = 0;i < tam; i++)
{
for (j = 0 ;j < tam; j++)
{
b[i][j] = 0;
if (i != 0 && j != c)
{
b[m][n] = matrix[i][j];
if (n < (tam - 2))
n++;
else
{
n = 0;
m++;
}
}
}
}
det = det + s * (matrix[0][c] * determinant( tam - 1,b));
s = -1 * s;
}
}
return (det);
}
void cofactor( int tam,float num[][tam])
{
float b[tam][tam], fac[tam][tam];
int p, q, m, n, i, j;
float x = 0;
for (q = 0;q < tam; q++)
{
for (p = 0;p < tam; p++)
{
m = 0;
n = 0;
for (i = 0;i < tam; i++)
{
for (j = 0;j < tam; j++)
{
if (i != q && j != p)
{
b[m][n] = num[i][j];
if (n < (tam - 2))
n++;
else
{
n = 0;
m++;
}
}
}
}
x = pow(-1, q + p) * determinant( tam - 1,b);
fac[p][q] = x;
}
}
transpose(tam,num, fac);
}
void transpose(int tam,float num[][tam], float fac[][tam])
{
int i, j;
float b[tam][tam], inverse[tam][tam], d;
for (i = 0;i < tam; i++)
{
for (j = 0;j < tam; j++)
{
b[i][j] = fac[j][i];
}
}
d = determinant(tam,num);
for (i = 0;i < tam; i++)
{
for (j = 0;j < tam; j++)
{
inverse[i][j] = b[i][j] / d;
}
}
printf("\n\n\nThe inverse of matrix is : \n");
for (i = 0;i < tam; i++)
{
for (j = 0;j < tam; j++)
{
printf("\t%f", inverse[i][j]);
}
printf("\n");
}
}
int verify_Size(int line){
if((line > 0) && (line <= 6))
{
return 1;
}
return 0;
}
int create_Matrix(int LINE){
int matrix[LINE][LINE];
float aux[LINE][LINE];
printf("\n\n\nPle:", (LINE * LINE));
printf("\n--------------------------------\n");
for(int i=0;i<LINE;i++)
{
for(int j=0;j<LINE;j++)
{
printf("Value[%d][%d]: ",i,j);
matrix[i][j] = validate();
}
}
printf("\n\nYour Bidimensional Matrix is:");
printf("\n--------------------------------\n");
for(int i=0;i < LINE;i++)
{
for(int j=0; j< LINE;j++)
{
printf("\t%2d",matrix[i][j]);
aux[i][j] = (float) matrix[i][j];
}
printf("\n");
}
float d = determinant(LINE,aux);
printf("\n\nDeterminante Main: %f \n",d);
if (d == 0)
printf("\nInverse of Entered Matrix is not possible\n");
else
cofactor(LINE,aux);
return 0;
}
int main(){
int flag,line;
do{
printf("Enter the order of the Matrix:\n");
printf("-------------------------------\n");
printf("Lines: ");
line = validate();
if(verify_Size(line)== 1)
{
create_Matrix(line);
}else{
printf("\nMatrix must to be till 6 X 6!\n");
flag = 0;
}
}while(flag != 1);
return 0;
}
It looks like you are finding the inverse matrix by Cramer's rule. While it works Ok for 2x2 or 3x3 matrix sizes, the hard part about implementing Cramer's rule generally is evaluating determinants. If you compute an NxN determinant following the definition, the computation is recursive and has factorial O(N!) computational complexity (Wikipedia).
I suggest switching to another algorithm. LUP factorization is fast and relatively simple, and Wikipedia has an example implementation.
Related
#include <stdio.h>
int main() {
int n, i, j, k, l;
int temp;
printf("Enter how many element on the array : ");
scanf("%d", &n);
int arr1[100] = {};
for (i = 0; i < n; i++) {
scanf("%d", &arr1[i]);
}
for (j = 0; j < n; j++) {
for (k = j + 1; k < n; k++) {
if (arr1[j] > arr1[k]) {
temp = arr1[j];
arr1[j] = arr1[k];
arr1[k] = temp;
}
}
}
for (i = 0; i < n; i++) {
printf("%d \t", arr1[i]);
}
}
My code for sorting an array in ascending order works properly. And it doesn't have any error but when I am changed the array size then the code doesn't work properly and has an error called stack smashing detected. What causes this problem?
#include <stdio.h>
int main() {
int n, i, j, k, l;
int temp;
printf("Enter how many element on the array : ");
scanf("%d", &n);
int arr1[] = {};
for (i = 0; i < n; i++) {
scanf("%d", &arr1[i]);
}
for (j = 0; j < n; j++) {
for (k = j + 1; k < n; k++) {
if (arr1[j] > arr1[k]) {
temp = arr1[j];
arr1[j] = arr1[k];
arr1[k] = temp;
}
}
}
for (i = 0; i < n; i++) {
printf("%d \t", arr1[i]);
}
}
Neither int arr1[100] = {}; nor int arr1[] = {}; is valid C code.
The program compiles because your compiler implements GNU extensions that allow empty initializers and zero length arrays.
The reason your program no longer works when you remove the length 100 is the array becomes too short for the elements you try and store into it.
You probably meant to write int arr1[n] = {}; which does not compile because VLAs (variable sized arrays) cannot have an initializer.
Here is a modified version:
#include <stdio.h>
int main() {
int n, i, j, k, l;
printf("Enter how many element on the array : ");
if (scanf("%d", &n) != 1 || n <= 0) {
fprintf(stderr, "invalid size\n");
return 1;
}
int arr1[n];
for (i = 0; i < n; i++) {
if (scanf("%d", &arr1[i]) != 1) {
fprintf(stderr, "invalid input\n");
return 1;
}
}
for (j = 0; j < n; j++) {
for (k = j + 1; k < n; k++) {
if (arr1[j] > arr1[k]) {
int temp = arr1[j];
arr1[j] = arr1[k];
arr1[k] = temp;
}
}
}
for (i = 0; i < n; i++) {
printf("%d%c", arr1[i], "\t\n"[i == n - 1]);
}
return 0;
}
This is the code i am talking about. It checks if a matrix is sparse or not . If it is then it changes it to sparse form and transposes it. When I run it with Vscode it runs and displays till it is sparse matrix but doesn't show its sparse form and transpose form but on online compiler it runs successfully till the end.
#include <stdio.h>
int checksparse();
int changematrix();
int main()
{
int a[100][100];
int i, j, r, c;
printf("Enter number of rows and columns in the matrix\n");
scanf("%d%d", &r, &c);
printf("\nEnter the elements in the matrix");
for (i = 0; i < r; i++)
{
for (j = 0; j < c; j++)
{
printf("\na[%d][%d] = ", i, j);
scanf("%d", &a[i][j]);
}
}
int check = checksparse(a, r, c);
if (check == 1)
{
printf("\nIts a sparse matrix\n");
changematrix(a, r, c);
}
else if (check == 0)
{
printf("\nIts not a sparse matrix");
}
return 0;
}
int checksparse(int array[100][100], int r, int c)
{
int counter = 0, flag = 1;
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
if (array[i][j] == 0)
counter++;
}
}
if (counter > ((r * c) / 2))
{
return flag;
}
else
{
flag = 0;
return flag;
}
}
int changematrix(int array[100][100], int r, int c)
{
int b[100][100], temp, counter = 0;
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
if (array[i][j] != 0)
{
b[temp][0] = i;
b[temp][1] = j;
b[temp][2] = array[i][j];
temp++;
counter++;
}
}
}
printf("\nSparse Matrix : \n");
for (int i = 0; i < counter; i++)
{
for (int j = 0; j < 3; j++)
{
printf("%d ", b[i][j]);
printf("\t");
}
printf("\n");
}
printf("\nTranspose of Sparse Matrix : \n");
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < counter; j++)
{
printf("%d ", b[j][i]);
printf("\t");
}
printf("\n");
}
return 0;
}
How do I get to write to 2D pointers where I have pnumber[2%4][2%4] and how can I get pnumber with more than 3 ciphers to be displayed?
I'm making a program to write pascals triangle in C.
When the pointer pnumbers[i][j] have both i and j = 2 mod 4, except for when i and j = 2, then my program won't write to the address and give the error message:
pascals triangle: malloc.c:2406: sysmalloc: Assertion '{old_top == initial_top (av) && ((unsigned long) old_end & (pagesize - 1)) == 0)' failed.
Aborted.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int factorial(int p) {
if (p>=1) {
return p*factorial(p-1);
}
else {
return 1;
}
}
int NchooseM(int n, int m) {
return factorial(n)/(factorial(n-m)*factorial(m));
}
int main() {
int n =7;
int x = n-2;
int i, j, k;
/*
printf("How many rows of Pascals triangle do you want to write?\n");
scanf("%d", &n);
*/
int **pnumbers;
pnumbers = (int **) malloc(n *sizeof(int *));
/* Allocate memory for storing the individual elements in a row */
for (i = 0; i < n; i++) {
pnumbers[i] = (int *) malloc(i * sizeof(int));
}
pnumbers[0][1] = 1;
/* Calculating the value of pnumbers[k][l] */
for (i = 0; i < n; i++) {
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
/*
if (!(i % 4 == 2 && i != 2))
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
} else if (i > 2) {
for (j = 0; j <= i-1; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
}
*/
}
/* Writing out the triangle */
for (i = 0; i < n; i++) {
for (k = 0; k <= x; k++){
printf(" ");
}
for (j = 0; j <= i; j++) {
printf("%d ", pnumbers[i][j]);
}
x = x-1;
printf("\n");
}
for (i = 0; i < n; i++) {
free(pnumbers[i]);
}
free(pnumbers);
return 0;
}
When I avoid writing to these addresses and just print them out I get some seemingly random integer at these memory addresses.
Also when avoid these addresses and just print out so many rows that I get some spots with a higher integer with more than 3 siphers, it seems to overflow - and I don't see the logic behind it.
The result of running the second code
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int factorial(int p) {
if (p>=1) {
return p*factorial(p-1);
}
else {
return 1;
}
}
int NchooseM(int n, int m) {
return factorial(n)/(factorial(n-m)*factorial(m));
}
int main() {
int n =20;
int x = n-2;
int i, j, k;
/*
printf("How many rows of Pascals triangle do you want to write?\n");
scanf("%d", &n);
*/
int **pnumbers;
pnumbers = (int **) malloc(n *sizeof(int *));
/* Allocate memory for storing the individual elements in a row */
for (i = 0; i < n; i++) {
pnumbers[i] = (int *) malloc(i * sizeof(int));
}
pnumbers[0][1] = 1;
/* Calculating the value of pnumbers[k][l] */
for (i = 0; i < n; i++) {
/*
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
*/
if (!(i % 4 == 2 && i != 2))
for (j = 0; j <= i; j++) {
pnumbers[i][j] = NchooseM(i,j);
} else if (i > 2) {
for (j = 0; j <= i-1; j++) {
pnumbers[i][j] = NchooseM(i,j);
}
}
}
/* Writing out the triangle */
for (i = 0; i < n; i++) {
for (k = 0; k <= x; k++){
printf(" ");
}
for (j = 0; j <= i; j++) {
printf("%d ", pnumbers[i][j]);
}
x = x-1;
printf("\n");
}
for (i = 0; i < n; i++) {
free(pnumbers[i]);
}
free(pnumbers);
return 0;
}
But row number 13 is still quite messed up.
Code is experiencing int overflow and thus undefined behavior (UB).
With 32-bit int and int factorial(int p), p > 12 oveflows the int range.
Code could use a wider integer type (long long works up to p==20), but improvements can be made at NchooseM() to avoid overflow for higher values.
Something like the below. Works up to int n = 30;
int NchooseM(int n, int m) {
// return factorial(n)/(factorial(n-m)*factorial(m));
int nm = 1;
int den = 1;
for (int i = m+1; i <= n; i++) {
assert(INT_MAX/i >= nm);
nm *= i;
assert(nm % den == 0);
nm /= den++;
}
return nm;
}
Tried unsigned long long and works up to int n = 62;
Edit: Another bug:
I "fixed" by initializing all to 1, yet I suspect something remains amiss in /* Calculating the value of pnumbers[k][l] */ for (i = 0; i < n; i++) { code.
pnumbers[i] = malloc((i + 1) * sizeof pnumbers[i][0]);
for (int j = 0; j < i + 1; j++) {
pnumbers[i][j] = 1;
}
Aside: rather than pnumbers[i] = (int *) malloc((i+1) * sizeof(int));, consider below with no unneeded cast nor trying to match the right type.
pnumbers[i] = malloc(sizeof pnumbers[i][0] * (i+1));
So I'm creating a sudoku solver in C. Here's my full code as of now, I've mostly been using python and just got into C, I basically converted a lot of python functions to C to get this but I think it'll work:
#include <stdio.h>
#include <stdlib.h>
int is_empty();
int possible_v();
int solver();
int main(){
int s_array[9][9];
FILE * fpointer;
int i;
int j;
fpointer = fopen("sudoku001.txt", "r");
for (i=0; i<9; i++){
for(j = 0; j<9; j++){
fscanf(fpointer, "%d", &s_array[i][j]);
}
}
for (i=0; i<9; i++) {
if (i % 3 == 0) {
printf("------------------------------\n");
}
for (j = 0; j < 9; j++) {
printf(" %d ", s_array[i][j]);
if ((j + 1) % 3 == 0) {
printf("|");
}
}
printf("\n");
}
solver(s_array);
for (i=0; i<9; i++) {
if (i % 3 == 0) {
printf("------------------------------\n");
}
for (j = 0; j < 9; j++) {
printf(" %d ", s_array[i][j]);
if ((j + 1) % 3 == 0) {
printf("|");
}
}
printf("\n");
}
return 0;
}
int is_empty(int board[9][9]){
int i;
int j;
int is_empty= 0;
for (i=0; i<9; i++){
for(j = 0; j<9; j++){
if (board[i][j] == 0) {
is_empty = 1;
break;
}
}
if (is_empty == 1){
break;
}
}
return is_empty;
}
int possible_v(int board[9][9], int i, int j) {
int p_array[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
int x;
int y;
int temp;
for (x = 0; x < 9; x++) {
if (board[x][j] != 0) {
temp = board[x][j];
p_array[temp - 1] = temp;
}
}
for (y = 0; y < 9; y++) {
if (board[i][y] != 0) {
temp = board[i][y];
p_array[temp - 1] = temp;
}
}
int m;
int n;
int temp1;
int temp2;
if (i>= 0 && i <= 2) {
m = 0;
}
else if (i>= 3 && i<=5) {
m = 3;
}
else{
m = 6;
}
if (j>= 0 && j <= 2) {
n = 0;
}
else if (j>= 3 && j<=5) {
n = 3;
}
else{
n = 6;
}
temp1 = m;
temp2 = n;
for (temp1; temp1<temp1+3; temp1++){
for (temp2; temp2<temp2+3; temp2++){
if (board[temp1][temp2] != 0){
p_array[board[temp1][temp2]] = 1;
}
}
}
temp1 = 1;
for (temp1; temp1<10){
if (p_array[temp1] == 0){
p_array[temp1] = temp1;
}
else{
p_array[temp1] = 0;
}
}
return p_array;
}
int solver(int board[9][9]){
int i;
int j;
int x;
int y;
int empty_check;
int p_values;
int temp;
if (is_empty(board) == 0){
printf("Board Completed");
empty_check = 0;
return empty_check;
}
else{
for (x = 0; x < 9; x++){
for (y = 0; y< 9; y++){
if (board[x][y] == 0){
i = x;
j = y;
break;
}
}
}
p_values = possible_v(board, i, j);
for (temp = 1; temp <10; temp++){
if (p_values[temp] != 0){
board[i][j] = p_values[temp];
solver(board);
}
}
board[i][j] = 0;
}
}
My main issue when compiling is getting the last two functions work with each other.
Function 'solver' calls and binds function 'possible_v'. Possible_V returns an array which I need to solve the puzzle. How can I make this work? .
You have the array locally declared, hence it cannot be passed back since it is destroyed once the function is exited. The workaround to this is to dynamically declare the array using malloc int *parray = (int*)malloc(9*sizeof(int)); and using the return type int* instead of int. But do not forget to free the allocated memory, else you will just keep allocating new memory from heap for every call you make.
As a side note, your implementation of Sudoku solver is a bit complex, and there is no need to return an array. You need to pass only the board. Here is an implementation of Sudoku Solver. This works both for 9x9 and 6X6 boards.
Edit : As advised by David Rankin, I have converted the C++ code to C.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
int n;
int issafe(int **board,int i,int j,int num){
for(int k=0;k<n;k++)
if(board[i][k] == num || board[k][j] == num)
return 0;
int cellx,celly;
if(n==6){
cellx = (i/2)*2;
celly = (j/3)*3;
for(int l=cellx;l<cellx+2;l++)
for(int m=celly;m<celly+3;m++)
if(board[l][m] == num){
return 0;
}
return 1;
}
int root = sqrt(n);
cellx = (i/(root))*root;
celly = (j/(root))*root;
for(int l=cellx;l<cellx+root;l++)
for(int m=celly;m<celly+root;m++)
if(board[l][m] == num)
return 0;
return 1;
}
int solve(int **board,int i,int j){
if(i == n)
return 1;
if(j == n){
return solve(board,i+1,0);
}
if(board[i][j] != 0)
return solve(board,i,j+1);
for(int k=1;k<n+1;k++)
if(issafe(board,i,j,k)){
board[i][j] = k;
if(solve(board,i,j+1))
return 1;
//backtrack
board[i][j] = 0;
}
return 0;
}
int main(){
do{
printf("Enter size of board(9 or 6): ");
scanf("%d",&n);
}while(n != 9 && n != 6);
int **board;
board = malloc(sizeof *board * n);
for(int i=0;i<n;i++)
board[i] = malloc(sizeof *board * n);
// input
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%d",&board[i][j]);
if(solve(board,0,0))
for(int i=0;i<n;i++){
for(int j=0;j<n;j++)
printf("%d ",board[i][j]);
printf("\n");
}
return 0;
}
I've been working on a program that generates an array of random numbers, splits the array into two equal parts, sorts each part, and then recombines the two parts back into a singular sorted array. When attempting an insert sort I get the following:
http://i.imgur.com/70J4eLG.png
Can you guys see a reason why the first half array is sorted correctly but the second half is not?
int cmpfunc (const void *a, const void *b) {
return ( *(int*)a - *(int*)b );
}
void insertion_sort (int ar[], int size) {
int c, d, t;
for (c = 1; c <= size - 1; c++){
d = c;
while(d > 0 && ar[d] < ar[d - 1]) {
t = ar[d];
ar[d] = ar[d - 1];
ar[d - 1] = t;
d--;
}
}
}
void check_sort (int ara[], int size_t) {
int b;
int c_i;
c_i = 0;
for (b = 1; b < size_t; b++) {
if (ara[b - 1] > ara[b]) {
printf("Array is not sorted correctly\n");
break;
} else {
c_i++;
}
}
if (c_i == size_t - 1) {
printf("Array is sorted correctly\n");
}
}
void combine_array(int a_ar[], int b_ar[], int c_ar[], int size_1, int size_2) {
int i, j, k;
i, j, k = 0;
while (i < size_1 && j < size_2) {
if (a_ar[i] < b_ar[j]) {
c_ar[k] = a_ar[i];
i++;
} else {
c_ar[k] = b_ar[j];
j++;
}
k++;
}
if (i >= size_1) {
while (j < size_2) {
c_ar[k] = b_ar[j];
j++;
k++;
}
}
if (j >= size_2) {
while (i < size_1) {
c_ar[k] = a_ar[i];
i++;
k++;
}
}
}
int main (int argc, char *argv[]) {
int a_size, t_num;
char s_type;
int i, j, k;
int two_s[1];
a_size = atoi(argv[1]);
t_num = atoi(argv[2]);
s_type = argv[3][0];
int array_m[a_size];
for (i = 0; i < a_size; i++) {
array_m[i] = rand();
}
for (i = 0; i < a_size; i++) {
printf("%d \n", array_m[i]);
}
printf("\n");
if (t_num == 2) {
two_s[0] = ((a_size/2));
two_s[1] = (a_size);
int array_s1[two_s[0]];
int array_s2[two_s[0]];
printf("First half \n");
for (j = 0; j < two_s[0]; j ++) {
array_s1[j] = array_m[j];
printf("%d \n", array_s1[j]);
}
printf("Second half \n");
for (k = two_s[0]; k < two_s[1]; k++) {
array_s2[k] = array_m[k];
printf("%d \n", array_s2[k]);
}
printf("Size of second array: %d", (two_s[1] - two_s[0]));
printf("\n");
check_sort(array_m, a_size);
if (s_type == 'I') { //Insertion sort
insertion_sort(array_s1, two_s[0]);
insertion_sort(array_s2, two_s[0]);
printf("Sorted first half \n");
for (i = 0; i < two_s[0]; i++) {
printf("%d \n", array_s1[i]);
}
printf("Sorted second half \n");
for (i = 0; i < two_s[0]; i++) {
printf("%d \n", array_s2[i]);
}
//combine_array(array_s1, array_s2, array_m, two_s[0], two_s[0]);
printf("\n");
printf("Combined and sorted \n");
for (i = 0; i < a_size; i++) {
printf("%d \n", array_m[i]);
}
check_sort(array_m, a_size);
}
if (s_type == 'Q') { //Quick sort
qsort(array_m, a_size, sizeof(int), cmpfunc);
printf("\n");
for (i = 0; i < a_size; i++) {
printf("%d \n", array_m[i]);
}
}
}
}
In your example, array_s2 is an array with 5 elements. In the following for loop, you're writing to memory outside the bounds of the array:
for (k = two_s[0]; k < two_s[1]; k++) {
array_s2[k] = array_m[k];
printf("%d \n", array_s2[k]);
}
k has an initial value of 5 and a final value of 9, which is outside the bounds of array_s2. Try the following to correctly index the array:
for (k = two_s[0]; k < two_s[1]; k++) {
array_s2[k - two_s[0]] = array_m[k];
printf("%d \n", array_s2[k - two_s[0]]);
}