I have a 2d array (matrix) where I am trying to calculate the biggest product of adjacent numbers. It's very similar to Project Euler Problem 11 except the user enters how many adjacent numbers they want in the calculation. I have it all right I think. The problem is if i use integer's to calculate the product of say 5 integers of 99 (e.g. 99*99*99*99*99) it will not display right. The maximum number of adjacent numbers which can be checked is 99. I have tried changing to long doubles (as you can see in the code) but it prints ridiculous numbers, e.g. with 3 adjacent numbers I entered 99 in all matrix positions and should get back 970299 (which I do when the maxProduct is an int), but instead I get:
-497917511184158537131936752181264370659584929560826523880745083032965215342755650440802286656251727430041200624372430370294634536699364412350122489510814753628581807006780156992324264734484592980976635224618682514265787653963930812412392499329499188301075222828863209569131692032
I feel like it's something obvious but I just can't see it.
#include <stdio.h>
#include <stdlib.h>
long double calcProduct(int n, int m, int ** matrix)
{
int i, x, y; //Loop counters
long double maxProduct; //Used to hold the maximum product of numbers found so far
long double temp; //Used to hold the current product of numbers
//Searching left to right
for(y = 0; y < n; y++)
{
for(x = 0; x <= n - m; x++)
{
for(i = 0; i < m; i++)
{
temp *= matrix[x + i][y];
}
if(temp > maxProduct)
{
maxProduct = temp;
}
temp = 1;
}
}
//Searching top down
for(x = 0; x < n; x++)
{
for(y = 0; y <= n - m; y++)
{
for(i = 0; i < m; i++)
{
temp *= matrix[x][y + i];
}
if(temp > maxProduct)
{
maxProduct = temp;
}
temp = 1;
}
}
temp = 1;
//Searching diagonal down right
for(x = 0; x < n - m; x++)
{
for(y = 0; y <= n - m; y++)
{
for(i = 0; i < m; i++)
{
temp *= matrix[x + i][y + i];
}
if(temp > maxProduct)
{
maxProduct = temp;
}
temp = 1;
}
}
temp = 1;
//Searching diagonal up right
for(x = 0; x < n - m; x++)
{
for(y = n - 1; y >= m - 1; y--)
{
for(i = 0; i < m; i++)
{
temp *= matrix[x + i][y - i];
}
if(temp > maxProduct)
{
maxProduct = temp;
}
temp = 1;
}
}
return maxProduct;
}
main()
{
int ** matrix; //2D array to hold the matrix items
int n, m; //Used to hold the size of the matrix (n) and the number of adjacent numbers to include in the calculation (m)
int i, j; //Loop counters
//Taking input of n (for size of grid) and m (number of adjacent numbers to include in calculation)
scanf("%d %d", &n, &m);
//Assign the array 'matrix' with the size of int multiplied by the number of items to hold (n)
matrix = (int **)malloc(sizeof(int*)*n);
//If the matrix is null then exit the program
if (matrix == NULL)
{
exit (0);
}
for(i = 0; i < n; i++)
{
matrix[i] = (int *)malloc(sizeof(int)*n);
if(matrix[i] == NULL) exit (0);
}
//Getting the numbers which are held in the matrix
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
scanf("%d", &matrix[i][j]);
}
}
//Prints the highest product by calling the method calcProduct, giving it n, m and the array matrix
printf("%.0Lf", calcProduct(n, m, matrix));
}
temp is not initialized in calcProduct, and neither is maxProduct. They will contain random, garbage values the first time through the loop, which is corrupting your maxProduct result.
'matrix is of type 'int'-Array, but your scanf() 'doubles' into it
Related
Im trying to sort a matrix by the sum of its row's digits, from highest to lowest. I dont know if i explained that correctly so here's some photos explaining it.
This is what my code outputs. Basically, it asks you for m and n, which are the dimensions of the matrix. In this example it's a 3x4, 3 rows and 4 columns. Then, the matrix should be sorted by rows, by the sum of row's digits. Which means, instead of what's being outputted in the picture above, the correct result should be this:
I have no idea how to sort this from highest to lowest, i have been trying for hours to no avail.
Here's my code:
#include <stdio.h>
#define N 30
void main(){
double a[N][N], s[N], p;
int i, j, m, n, max;
while(1){
printf("\nm, n? ");
scanf("%d%d", &m, &n);
if(m <= 0 || m > N || n <=0 || n > N)
break;
for(i = 0; i < m; i++){
printf("%2d. row? ", i+1);
for(j = 0; j < n; scanf("%lf", &a[i][j++]));
}
for(i = 0; i < m; i++)
for(s[i] = j = 0; j < n; s[i] += a[i][j++]);
for(j = 0; j < n - 1; j++){
for(max = i, j = i+1; j < n; j++)
if(s[j] > s[max])
max = i;
if(max != j){
p = s[j];
s[j] = s[max];
s[max] = p;
for(j = 0; j < m; j++){
p = a[j][i];
a[j][i] = a[j][max];
a[j][max] = p;
}
}
}
printf("New matrix: \n");
for(i = 0; i < m; i++){
for(j = 0; j < n; printf("%8.2lf", a[i][j++]));
printf("\n");
}
for(j = 0; j < m; j++)
printf("-------------");
printf("\n");
for(j = 0; j < m; printf("%8.2f \n", s[j++]));
printf("\n");
}
}
You can sort the rows of the matrix from highest to lowest, using a simple bubble sort algorithm.Your code modified below:
int main() {
double a[N][N], s[N], p;
int i, j, m, n, max;
while (1) {
printf("\nm, n? ");
scanf("%d%d", & m, & n);
if (m <= 0 || m > N || n <= 0 || n > N)
break;
for (i = 0; i < m; i++) {
printf("%2d. row? ", i + 1);
for (j = 0; j < n; scanf("%lf", & a[i][j++]));
}
for (i = 0; i < m; i++)
for (s[i] = j = 0; j < n; s[i] += a[i][j++]);
for (i = 0; i < m - 1; i++) { // modified here
for (j = i + 1; j < m; j++) { // modified here
if (s[j] > s[i]) { // modified here
p = s[i];
s[i] = s[j];
s[j] = p;
for (int k = 0; k < n; k++) {
p = a[i][k];
a[i][k] = a[j][k];
a[j][k] = p;
}
}
}
}
printf("New matrix: \n");
for (i = 0; i < m; i++) {
for (j = 0; j < n; printf("%8.2lf", a[i][j++]));
printf("\n");
}
for (j = 0; j < m; j++)
printf("-------------");
printf("\n");
for (j = 0; j < m; printf("%8.2f \n", s[j++]));
printf("\n");
}
return 0;
}
Here's how i modified your code to achieve that:
Initialize a loop variable i to 0.
In the outer loop, run the inner loop j from i+1 to m-1.
In the inner loop, compare the sum of the row i with the sum of row
j. If the sum of row j is greater than the sum of row i, swap the
rows using a temporary variable.
After the inner loop finishes, increment the value of i by 1. Repeat
the outer loop until i becomes equal to m-1.
Output:
You can just use qsort to let it handle the sorting and item swapping. Then you only need to write the code for comparing two rows with each other.
Given something like this:
int matrix[3][4] =
{
{1,2,3,4},
{5,6,7,8},
{9,1,2,3},
};
You'd call qsort as:
qsort(matrix, 3, sizeof(int[4]), compare);
The only complexity is implementing the comparison callback function. There's two things to consider there:
We've told qsort that we have an array of 3 items, each of type int[4]. So the void pointers it passes along to us will actually be pointers to type int[4]. That is: int(*)[4].
qsort sorts in ascending order by default, where the item considered "less" ends up first. So we need to tweak that to get the largest item first.
Example:
int compare (const void* obj1, const void* obj2)
{
const int (*ptr1)[4] = obj1;
const int (*ptr2)[4] = obj2;
size_t sum1=0;
size_t sum2=0;
for(size_t i=0; i<4; i++)
{
sum1 += (*ptr1)[i];
sum2 += (*ptr2)[i];
}
if(sum1 > sum2) // largest sum considered "less" for qsort
return -1;
else
return 1;
return 0;
}
sum1 < sum2 would have placed the smallest row first.
Full example:
#include <stdio.h>
#include <stdlib.h>
int compare (const void* obj1, const void* obj2)
{
const int (*ptr1)[4] = obj1;
const int (*ptr2)[4] = obj2;
size_t sum1=0;
size_t sum2=0;
for(size_t i=0; i<4; i++)
{
sum1 += (*ptr1)[i];
sum2 += (*ptr2)[i];
}
if(sum1 > sum2) // largest sum considered "less" for qsort
return -1;
else
return 1;
return 0;
}
void print_matrix(size_t col, size_t row, int matrix[col][row])
{
for(size_t i=0; i<col; i++)
{
for(size_t j=0; j<row; j++)
{
printf("%d,", matrix[i][j]);
}
puts("");
}
}
int main (void)
{
int matrix[3][4] =
{
{1,2,3,4},
{5,6,7,8},
{9,1,2,3},
};
print_matrix(3,4,matrix);
puts("");
qsort(matrix, 3, sizeof(int[4]), compare);
print_matrix(3,4,matrix);
}
I have to input array length and its elements as shown down in the code. Array length represents the number of cities and its elements show the distance between them like shown in the picture down below.
So the input should look like this:5 and 2 3 4 1 1
And I have to find the shortest distance between two points of the circle like I-I; I-II; I-III... II-I; II-II... till I fill a matrix which size is array size x array size(in this case 5x5)
and that output needs to look like this:
0 2 5 2 1
2 0 3 4 3
5 3 0 4 5
2 4 4 0 1
1 3 5 1 0
This is my code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int* ptr;
int l,n, i, m, x,y,s,j,t;
int **p;
scanf("%d", &l);
ptr = (int*)malloc(l * sizeof(int));
if (ptr == NULL) {
exit(0);
}
else {
for (i = 0; i < l; ++i)
{
scanf("%d", &ptr[i]);
if(ptr[i]<0)
{
exit(0);
}
}
for (i = 0; i < l; ++i) {
printf("%d ", ptr[i]);
}
}
n=l;
m=l;
while(m>0 && n>0){
p= malloc(m*sizeof(int*));
for (i=0;i<m;i++){
p[i]=malloc(n*sizeof(int));
for(j=0;j<n;j++){
x=0;
y=0;
for (t = 0; t < j; t++) {
x += ptr[t];
}
for (t = n; t >j; t--) {
y += ptr[t];
}
if (x > y) {
s = y;
} else {
s = x;
}
p[i][j]=s;
}
}
}
for(i=0;i<n;i++) {
for(j=0;j<m;j++) {
printf("%d", p[i][j]);
}
putchar('\n');
}
return 0;
}
I think the code for finding distance is good but I can't say that for sure because I don't know how to put it into a matrix. I was also thinking to fill the diagonal of a matrix with zeros and fill the bottom left with numbers and "mirror" it since it is the same, but I'm not quite sure how to do that. So if someone can please give me suggestions or fix the code. Thank you in advance.
Well, for starters, I think your program will just run an endless loop since you have the line
while(m>0 && n>0)
but "m" and "n" do not change inside the loop.
I think this works, at least with your example so take a look:
#include <stdio.h>
#include <stdlib.h>
int main(){
int* ptr;
int l,n, i, m, x,y,s,j,t;
int **p;
scanf("%d", &l);
ptr = (int*)malloc(l * sizeof(int));
if (ptr == NULL) {
exit(0);
}
else {
for (i = 0; i < l; ++i)
{
scanf("%d", &ptr[i]);
if(ptr[i]<0)
{
exit(0);
}
}
for (i = 0; i < l; ++i) {
printf("%d ", ptr[i]);
}
printf("\n");
}
//Everything up to here is the same, now we initialize the "result" matrix
p = (int**) malloc (l * sizeof(int*));
for(i = 0; i < l; i++){
p[i] = (int*) malloc(l * sizeof(int));
p[i][i] = 0;//this will just fill the diagonal with 0's
}
for(i = 0; i < l; i++){//this is the starting point
for(j = i+1; j < l; j++){//this is the end point. Note we are starting at i+1 because we only need to fill one since the other is just mirrored
int l1 = 0, l2 = 0; //2 possible lengths, one going forward for index i -> i+1 ->...-> j and one going backwards i -> i-1 -> i-2 ->...->j
//going forwards
for(m = i; m <j; m++)
l1 += ptr[m];
//going backwards
n = i-1;
if(n == -1)//if we are out of bounds->go back
n = l-1;
while(n != j){
l2 += ptr[n];
n--;
if(n == -1)//if we are out of bounds->go back
n = l-1;
}
l2 += ptr[j];
//we compare to find the minimum
if(l1 < l2)
p[j][i] = l1;
else
p[j][i] = l2;
}
}
//we now mirror the results for the other half
for(i = 0; i < l; i++)
for(j = i+1; j < l; j++)
p[i][j] = p[j][i];
printf("RESULTS: \n");
//and we print
for(i = 0; i < l; i++){
for(j = 0; j < l; j++){
printf("%d ", p[i][j]);
}
printf("\n");
}
return 0;
}
My task is: If we look at any two neighbour values in an array, if the one on the right is two times greater than the one on the left, their average should be inserted between them and the new array consisting of old and new elements should be printed. I have a problem with moving the other elements after average.And using special functions or libraries is not allowed.I am beginner, and I hope you could help.
#include <stdio.h>
int main() {
int n, i, j;
double a[100], average;
printf("Enter the number of elements: ");
scanf("%d", &n);
for (i = 0; i < n; i++) {
scanf("%lf", &a[i]);
}
for (i = 0; i < n; i++) {
if ((a[i + 1] / a[i]) == 2) {
for (i = j = 0; i < n; ++i)
b[j++] = a[i];
if (a[i + 1] / a[i] == 2)
average = (a[i + 1] + a[i]) / 2;
b[j++] =average;
}
}
for (i = 0; i < j; ++i) {
printf("%lf\n", b[i]);
}
}
A simple way to solve your problem is adding double b[199];, and copying everything over:
for (i = j = 0; i < n; ++i) {
b[j++] = a[i];
if (...) b[j++] = ...; /* Append the average to b. */
}
for (i = 0; i < j; ++i) {
printf("%lf\n", b[i]);
}
If you really want to move the elements forward within a itself, then you can do it by adding an inner for loop (and an additional loop variable int k;) which copies the elements one-by-one:
for (k = n++; k > i; --k) {
a[k] = a[k - 1];
}
In order to insert an element in an array, you must copy the elements with higher index from the last one down.
Also avoid dividing by a[i] that can be zero, and properly handle 0,0 that match the criteria for inserting the average, and skip the inserted value to avoid inserting more zeros.
#include <stdio.h>
#include <stdlib.h>
int main() {
int n, i, j;
printf("Enter the number of elements: ");
if (scanf("%d", &n) != 1 || n <= 0)
return 1;
double *a = malloc(sizeof(*a) * (2 * n - 1)); // allocate the array to the maximum size
if (a == NULL)
return 0;
for (i = 0; i < n; i++) {
if (scanf("%lf", &a[i]) != 1)
return 1;
}
for (i = 1; i < n; i++) {
if (a[i] == a[i - 1] * 2) {
for (j = n; j > i; j--)
a[j] = a[j - 1];
a[i] = (a[i - 1] + a[i]) / 2;
n++; // increase number of elements
i++; // skip the new value
}
}
for (i = 0; i < n; ++i) {
printf("%f\n", a[i]);
}
free(a);
return 0;
}
To insert an element in a specific position you would need to move the rest of the array. However doing it many times is expensive and you may prefer to use an array to store the position at which you want to insert the elements and then insert them all at once.
Alternatively you can create a new array where to copy the original plus the new values.
However there's an easier and faster way, that is adding the new values straight away, while you fill the original array. Here's a program that does that.
#include <stdio.h>
#define SIZE 100
int main() {
int i, n, avg = 0;
double a[SIZE];
while( puts("Enter the number of elements:") && (scanf("%d", &n) != 1 || n < 1 || n > SIZE) );
scanf("%lf", &a[0]);
for(i = 1; i < n+avg && i < SIZE-1 && scanf("%lf", &a[i]) == 1; i++) {
if( a[i] == a[i-1] * 2 ) {
a[i+1] = a[i];
a[i] = (a[i] + a[i-1]) / 2;
++avg;
++i;
}
}
for(i = 0; i < n+avg; i++) {
printf("%lf\n", a[i]);
}
return 0;
}
I need a function to find out the Kaprekar numbers inside this 2d array, I searched in web but none of the results worked for 2D array.
This is the array that I made:
int **matrix;
int row, column;
long s, k;
srand(time(NULL));
printf("Number of rows: ");
scanf("%d", &row);
printf("Number of column: ");
scanf("%d", &column);
matrix = (int **) calloc(row, sizeof(int*));
for(i = 0; i < row; i++)
matrix[i] = (int *) calloc(column, sizeof(int));
for(s = 0; s < row; s++)
{
for(k = 0; k < column; k++)
{
matrix[s][k]=(rand()%1000) * (rand()%1000);
}
}
any help or suggestions to convert this code to be able to work for 2D array?
bool iskaprekar(int n)
{
if (n == 1)
return true;
int sq_n = n * n;
int count_digits = 0;
while (sq_n)
{
count_digits++;
sq_n /= 10;
}
sq_n = n*n;
for (int r_digits=1; r_digits<count_digits; r_digits++)
{
int eq_parts = pow(10, r_digits);
if (eq_parts == n)
continue;
int sum = sq_n/eq_parts + sq_n % eq_parts;
if (sum == n)
return true;
}
return false;
}
You have 2D array, you have also the function that verifies the number is Kaprekar or not. The simple way is using the for loop to check all number in 2D array as you did when you initialize the values of array using rand() function.
for(s = 0; s < row; s++) {
for(k = 0; k < column; k++) {
if(iskaprekar(matrix[s][k])) {
printf("%d ", matrix[s][k]);
}
}
}
if you want to store all Kaprekar numbers, you can use pointer then reallocate for it after each time you meet one Kaprekar number. Then remove the duplicated numbers if you want.
int * numbers = 0;
if(!numbers) {return -1;}
int count = 0;
for(s = 0; s < row; s++) {
for(k = 0; k < column; k++) {
if(iskaprekar(matrix[s][k])) {
numbers = realloc(numbers, sizeof(int) (count+1));
if(!numbers) {return -1;}
numbers[count] = matrix[s][k];
count++;
}
}
}
// Remove the duplicated numbers here, if you want
My Gauss Elimination code's results are -nan in visual studio, but not in Linux.
And the Linux results are awful because at func Gauss_Eli how many I increase the variable k at for blocks the func is working... doesn't occur segment error.
What is wrong with my code?
float ** Gauss_Eli(float ** matrix, int n) {
// -----------------------------------------------------
// | |
// | Eliminate elements except (i, i) element |
// | |
// -----------------------------------------------------
// Eliminate elements at lower triangle part
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
for (int k = 0; k < n + 1; k++) {
float e;
e = matrix[i][k] * (matrix[j][i] / matrix[i][i]);
matrix[j][k] -= e;
}
}
}
// Eliminate elements at upper triangle part
for (int i = n - 1; i >= 0; i--) {
for (int j = i - 1; j >= 0; j--) {
for (int k = 0; k < n + 1; k++) {
float e;
e = matrix[i][k] * (matrix[j][i] / matrix[i][i]);
matrix[j][k] -= e;
}
}
}
// Make 1 elements i, i
for (int i = 0; i < n; i++)
for (int j = 0; j < n + 1; j++) matrix[i][j] /= matrix[i][i];
return matrix;
}
int main() {
float ** matrix;
int n;
printf("Matrix Size : ");
scanf("%d", &n);
// Malloc variable matrix for Matrix
matrix = (float**)malloc(sizeof(float) * n);
for (int i = 0; i < n; i++) matrix[i] = (float*)malloc(sizeof(float) * (n + 1));
printf("Input elements : \n");
for (int i = 0; i < n; i++)
for (int j = 0; j < n + 1; j++) scanf("%f", &matrix[i][j]);
matrix = Gauss_Eli(matrix, n);
printf("Output result : \n");
//Print matrix after elimination
for (int i = 0; i < n; i++) {
for (int j = 0; j < n + 1; j++) printf("%.6f ", matrix[i][j]);
printf("\n");
}
return 0;
}
1.) OP allocates memory using the wrong type. This may lead to issues of insufficient memory and all sorts of UB and explain the difference between systems as they could have differing pointer and float sizes.
float ** matrix;
// v--- wrong type
// matrix = (float**)malloc(sizeof(float) * n);
Instead allocate to the size of the referenced variable. Easier to code (and get right), review and maintain.
matrix = malloc(sizeof *matrix * n);
if (matrix == NULL) Handle_Error();
2.) Code should look for division by 0.0
//for (int k = 0; k < n + 1; k++) {
// float e;
// e = matrix[i][k] * (matrix[j][i] / matrix[i][i]);
// matrix[j][k] -= e;
//}
if (matrix[i][i] == 0.0) Handle_Error();
float m = matrix[j][i] / matrix[i][i];
for (int k = 0; k < n + 1; k++) {
matrix[j][k] -= matrix[i][k]*m;
}
3.) General problem solving tips:
Check return values of scanf("%f", &matrix[i][j]);. It is 1?
Enable all warnings.
Especially for debug, print FP using "%e" rather than "%f".
4.) Numerical analysis tip: Insure exact subtraction when i==j
if (i == j) {
for (int k = 0; k < n + 1; k++) {
matrix[j][k] = 0.0;
}
else {
if (matrix[i][i] == 0.0) Handle_Divide_by_0();
float m = matrix[j][i] / matrix[i][i];
for (int k = 0; k < n + 1; k++) {
matrix[j][k] -= matrix[i][k]*m;
}
}