Related
I am learning c and encountered maximum cost path question in which
Rules:
matrix is n x n size
Starting from the cell (bottommost leftmost cell), you want to go to the topmost
rightmost cell in a sequence of steps. In each step, you can go either right or up from
your current location.
I tried to solve using dynamic programming and this is the function I have written
computecost(int *utr,int n)//utr is the input matrix
{
int *str;
int i,j;
str=(int *)malloc(n*n*sizeof(int));
for(j=0;j<n;j++)//intialization of bottom row
{
str[n*(n-1)+j]=utr[n*(n-1)+j];
}
for(i=n-2;i>=0;i--)
{
for(j=0;j<n;j++)
{
str[n*i+j]=utr[n*i+j]+max(str[n*(i+1)+j],str[n*(i+1)+(j+1)]);
}
}
printf("%d",str[n*0+0]);
return 0;
}
and this is the input
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&str[n*i+j]);
}
}
but
for the matrix 5 x5
1 4 8 2 9
32 67 18 42 1
4 86 12 7 1
8 4 12 17 44
1 43 11 45 2
the desired output is 272 but I am getting 211.
the output matrix for my case
1 43 11 45 2
51 47 57 62 46
55 143 74 69 47
175 210 92 111 52
211 214 119 113 64
Can anyone help me?
You don't need dynamic programming for this since there are no overlapping sub-problems. Just use a simple recursion.
const int n = 5;
int mat[n][n] = {
{1,4,8,2,9},
{32,67,18,42,1},
{4,86,12,7,1},
{8,4,12,17,44},
{1,43,11,45,2}
}; // input matrix
int f(int x, int y, int sum){
if(x == 0 && y == 4)
return sum;
int p = 0, q = 0;
if(x - 1 >= 0)
p = f(x-1, y, sum + mat[x-1][y]);
if(y + 1 <= 4)
q = f(x, y+1, sum+mat[x][y+1]);
return max(p,q);
}
int main(){
int maxSum = f(4,0, mat[4][0]);
printf("%d\n", maxSum);
}
You were not very far to succeed.
In practice, you did not initialize correctly the bottom row.
Moreover, there was a little mistake in the iteration calculation.
This is the corrected code.
As said in a comment, it could be further simplified, by avoiding the use of a new array, simply updating the input array.
#include <stdio.h>
#include <stdlib.h>
int max (int a, int b) {
return (a > b) ? a : b;
}
int computecost(int *utr,int n) { //utr is the input matrix
int *str;
str = malloc (n*n*sizeof(int));
str[n*n - 1] = utr[n*n - 1];
for (int j = n-2; j >= 0; j--) { //intialization of bottom row {
str[n*(n-1)+j] = utr[n*(n-1)+j] + str[n*(n-1)+j+1]; // corrected
}
for (int i=n-2; i>=0; i--) {
str[n*i+n-1] = utr[n*i+n-1] + str[n*(i+1)+n-1];
for(int j = n-2; j >= 0; j--) {
str[n*i+j] = utr[n*i+j] + max(str[n*(i+1)+j],str[n*i + j+1]); // corrected
}
}
int cost = str[0];
free (str);
return cost;
}
int main() {
int A[25] = {
1,43,11,45,2,
8,4,12,17,44,
4,86,12,7,1,
32,67,18,42,1,
1,4,8,2,9
};
int ans = computecost (A, 5);
printf ("%d\n", ans);
return 0;
}
please help me to solve the below problem in java to rotate the outer ring of matrix in anticlockwise by k element and inner ring in clockwise by k element in java and the middle element remains constant. The sample input is
m=5,n=6,k=1 where m is no of rows,n is no of column and k is the number of required shift and the input matrix is
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
25 26 27 28 29 30
and the expected output is
2 3 4 5 6 12
1 14 8 9 10 18
7 20 15 16 11 24
13 21 22 23 17 30
19 25 26 27 28 29
Can someone tell how to proceed for this problem as we need to do clockwise and anticlockwise both.
My solution copies one ring of matrix cells at a time. The rings are traversed step by step. For every step a case number is calculated by checking row and columns against the borders of the ring:
package ak.matrixTurn;
public class Main {
public static void main(String[] args) {
int rows = 5;
int cols = 6;
int delta = 1;
int[][] matrix = new int[rows][cols];
int[][] turned = new int[rows][cols];
// fill matrix
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
matrix[r][c] = r * cols + c + 1;
}
}
// copy 1:1 (not turned yet)
for (int r = 0; r < rows; r++) {
for (int c = 0; c < cols; c++) {
turned[r][c] = matrix[r][c];
}
}
ringTurn(matrix, turned, 0, delta);
ringTurn(matrix, turned, 1, -delta);
ShowMatrix(matrix);
ShowMatrix(turned);
System.out.println("Ciao!");
}
// helper class represents a row/col pair
static class RowCol {
int row;
int col;
int left;
int top;
int right;
int bottom;
RowCol(int ring, int rows, int cols) {
row = ring;
col = ring;
left = ring;
top = ring;
right = ring + cols - 1;
bottom = ring + rows - 1;
}
// one step anti-clockwise along our ring
void Advance() {
switch(GetCase())
{
case LEFT: // left col
case TOP+LEFT: // top-left corner
row++; break;
case RIGHT: // right col
case BOTTOM+RIGHT: // bottom-right corner
row--; break;
case BOTTOM: // bottom row
case BOTTOM+LEFT: // bottom-left corner
col++; break;
case TOP: // top row
case TOP+RIGHT: // top-right corner
col--; break;
}
}
// cryptic but shorter version of Advance()
void Advance2() {
row += PlusMinus("+- - + ");
col += PlusMinus(" ++ - -");
}
// return -1 for "-", +1 for "+"
// at 1-based string position r
int PlusMinus(String s) {
int r = GetCase();
char c = s.charAt(r - 1);
return "- +".indexOf(c) - 1;
}
// one step back on our ring
void Retract() {
switch(GetCase())
{
case LEFT: // left col
case BOTTOM+LEFT: // bottom-left corner
row--; break;
case RIGHT: // right col
case TOP+RIGHT: // top-right corner
row++; break;
case BOTTOM: // bottom row
case BOTTOM+RIGHT: // bottom-right corner
col--; break;
case TOP: // top row
case TOP+LEFT: // top-left corner
col++; break;
}
}
// cryptic but shorter version of Retract()
void Retract2() {
row += PlusMinus("-+ - +");
col += PlusMinus(" - - ++ ");
}
private int b2x(boolean b, int x) {
return b ? x : 0;
}
static final int LEFT = (1 << 0);
static final int RIGHT = (1 << 1);
static final int BOTTOM = (1 << 2);
static final int TOP = (1 << 3);
// determine where we are on the ring
int GetCase() {
int r = b2x(col == left, LEFT)
+ b2x(col == right, RIGHT)
+ b2x(row == bottom, BOTTOM)
+ b2x(row == top, TOP);
// we have to stay on our ring
assert r != 0;
return r;
}
} // end of class RowCol
// copy all cells in ring from src to dest
// apply delta offset (> 0 if anti-clockwise)
static void ringTurn(int[][] src, int[][] dest, int ring, int delta) {
int cols = src[0].length - 2 * ring;
int rows = src.length - 2 * ring;
// in-place turns are forbidden
assert dest != src;
// matrices have to match in their size
assert dest[0].length == src[0].length;
assert dest.length == src.length;
if ((rows > 1) && (cols > 1)) {
RowCol srcRC = new RowCol(ring, rows, cols);
RowCol destRC = new RowCol(ring, rows, cols);
// position the destination location
for (int i = 0; i < Math.abs(delta); i++) {
if (delta > 0) {
destRC.Advance2();
} else {
destRC.Retract2();
}
}
// perform the copy operation
// by moving both locations along the ring
int steps = 2 * (rows + cols - 2);
for (int step = 0; step < steps; step++) {
dest[destRC.row][destRC.col] = src[srcRC.row][srcRC.col];
destRC.Advance2();
srcRC.Advance2();
}
}
}
static void ShowMatrix(int[][] matrix) {
int cols = matrix[0].length;
System.out.println();
for (int[] ints : matrix) {
StringBuilder s = new StringBuilder();
for (int col = 0; col < cols; col++) {
s.append(String.format("%3d", ints[col]));
}
System.out.println(s);
}
}
}
Output:
1 2 3 4 5 6
7 8 9 10 11 12
13 14 15 16 17 18
19 20 21 22 23 24
25 26 27 28 29 30
2 3 4 5 6 12
1 14 8 9 10 18
7 20 15 16 11 24
13 21 22 23 17 30
19 25 26 27 28 29
I have been trying this popular question, where I have to multiply two very large numbers in C (without using any libraries other than stdio.h). I know my algorithm and code are correct, since it works on dry runs.
However, the ans array here keeps allocating itself garbage value, to which I cannot find any reason whatsoever.
The input format is number1 * number2
Following is my code:
#include <stdio.h>
int main(){
char str[200];
gets(str);
int length = 0;
for (int i = 0; ; i++){
if(str[i]=='\0'){
break;
}
length++;
}
int s1[101], s2[101];
int l1 = 0, l2 = 0, temp = 0;
for(int i = 0; i<length; i++){
l1++;
if(str[i]=='*'){
l1-=2;
temp = i;
break;
}
}
l2 = length-l1;
l2-=3;
for(int i = 0; i<l1; i++){
s1[i] = str[i]-'0';
}
for(int i = l1+3; i<length; i++){
s2[i] = str[i]-'0';
}
int a[100],b[100];
int ans[200];
int i,j,tmp;
for(int k = 0; i<200; i++){
ans[k] = 0;
}
j = l1 - 1;
i = 0;
while (i < j){
tmp = s1[i];
s1[i] = s1[j];
s1[j] = tmp;
i++;
j--;
}
j = l2 - 1;
i = 0;
while (i < j){
tmp = s2[i];
s2[i] = s2[j];
s2[j] = tmp;
i++;
j--;
}
for(i = 0;i < l2;i++){
for(j = 0;j < l1;j++){
ans[i+j] += s2[i]*s1[j];
printf(" %d", ans[i+j]);
}
}
for(i = 0;i < l1+l2;i++)
{
tmp = ans[i]/10;
ans[i] = ans[i]%10;
ans[i+1] = ans[i+1] + tmp;
}
for(i = l1+l2; i>= 0;i--)
{
if(ans[i] > 0)
break;
}
//printf("Product : ");
for(;i >= 0;i--)
{
//printf("%d",ans[i]);
}
return 0;
}
Can anyone help me out with this problem and tell me why this garbage value comes, and how to avoid this error?
Red herring
The original code used int ans[200] = { 0 }; but in the light of some comments, that was changed to:
int ans[200];
for (int k = 0; i < 200; i++){
ans[k] = 0;
}
The loop is clearly erroneous; the index k should be tested and incremented, not i.
However, the original code was correct — it initializes all the elements of the array to 0 as desired. I'm sorry you got a 'bum steer' from some of the commentators.
Diagnosis
I think your main problem is in converting the second number into a string of digits.
for (int i = l1 + 3; i < length; i++){
s2[i] = str[i] - '0';
}
You need to assign to indexes in s2 in the range 0..l2, but you are indexing starting from l1+3, which leaves the start of s2 holding garbage. In the solution below, I took a lazy (but effective) way out: I created int z = 0; before the loop, and used s2[z++] = str[i] - '0';.
(Now I go back and reread kiner_shah's comment, I see that comment also diagnosed this flaw – but I confess I didn't understand what was said until re-reviewing the comments after posting this answer.)
Prescription
I added some assertions to ensure that things behaved as I expected. I added extensive debug printing. I also renamed l1 to len1 and l2 to len2; the 2-character names are just too easily confused with 11 and 12. I created a printing function to show the converted numbers. I could/should have created a function to encapsulate the conversion process.
The main problem was easily spotted when a simple test printed zeros for the second number, even though I'd typed 123 as the number. It was coincidence that it was zeros; the key point is that it wasn't 123 as expected.
Note that the printing has to deal with the special case of 0 as the result. The code that converts the string into a series of decimal digits could spot whether all the digits are zero (simply sum the converted digits; if the result is zero, all the digits are zero) and then special case the calculation (zero times anything is zero).
#include <assert.h>
#include <stdio.h>
/* Print digits - ensure each digit is visible with parentheses */
static void print_number(const char *tag, int len, int data[len])
{
printf("Number %s: [", tag);
for (int i = 0; i < len; i++)
printf("(%d)", data[i]);
printf("]\n");
}
int main(void)
{
char str[200];
if (fgets(str, sizeof(str), stdin) == NULL)
return 1;
int length;
for (length = 0; str[length] != '\0' && str[length] != '\n'; length++)
;
str[length] = '\0'; /* Zap newline */
printf("Calculation: [%s]\n", str); // Debug
int s1[101], s2[101];
int len1 = 0, len2 = 0;
/* This is fragile - it depends on the user getting the format right! */
for (int i = 0; i < length; i++)
{
len1++;
if (str[i] == '*')
{
len1 -= 2;
break;
}
}
assert(str[len1+0] == ' '); // Debug
assert(str[len1+1] == '*'); // Debug
assert(str[len1+2] == ' '); // Debug
len2 = length - len1;
len2 -= 3;
printf("Number 1: [%.*s]\n", len1, str); // Debug
printf("Number 2: [%.*s]\n", len2, &str[len1 + 3]); // Debug
for (int i = 0; i < len1; i++)
{
assert(str[i] >= '0' && str[i] <= '9'); // Debug
s1[i] = str[i] - '0';
}
print_number("1A", len1, s1); // Debug
int z = 0;
for (int i = len1 + 3; i < length; i++)
{
assert(str[i] >= '0' && str[i] <= '9'); // Debug
s2[z++] = str[i] - '0';
}
print_number("2A", len2, s2); // Debug
int ans[200] = { 0 };
int i, j, tmp;
/* Reverse digits of first number */
/* Need a function for this! */
j = len1 - 1;
i = 0;
while (i < j)
{
tmp = s1[i];
s1[i] = s1[j];
s1[j] = tmp;
i++;
j--;
}
/* Reverse digits of second number */
j = len2 - 1;
i = 0;
while (i < j)
{
tmp = s2[i];
s2[i] = s2[j];
s2[j] = tmp;
i++;
j--;
}
/* Raw multiplication - deal with carries later */
for (i = 0; i < len2; i++)
{
for (j = 0; j < len1; j++)
{
ans[i + j] += s2[i] * s1[j];
printf("[%d+%d] = %d\n", i, j, ans[i + j]);
}
}
/* Deal with carries */
for (i = 0; i < len1 + len2; i++)
{
int old1 = ans[i]; // Debug
int old2 = ans[i+1]; // Debug
tmp = ans[i] / 10;
ans[i] = ans[i] % 10;
ans[i + 1] = ans[i + 1] + tmp;
printf("Fixup %d: old (%d)(%d) new (%d)(%d)\n", // Debug
i, old1, old2, ans[i], ans[i+1]); // Debug
}
/* Find most significant digit */
for (i = len1 + len2; i >= 0; i--)
{
if (ans[i] > 0)
break;
}
printf("Significant digits = %d\n", i + 1); // Debug
/* Print digits in reverse order */
j = i; // Save starting point in j // Debug
if (i == -1) // Debug
putchar('0'); // Debug
else // Debug
{ // Debug
printf("Product : "); // Debug
for ( ; i >= 0; i--) // Debug
{ // Debug
printf("(%d)", ans[i]); // Debug
} // Debug
} // Debug
putchar('\n'); // Debug
i = j; // Recover starting point from j // Debug
printf("Product : ");
if (i == -1)
putchar('0');
else
{
for ( ; i >= 0; i--)
{
printf("%d", ans[i]);
}
}
putchar('\n');
return 0;
}
Sample test runs
Calculate 98 x 123
Calculation: [98 * 123]
Number 1: [98]
Number 2: [123]
Number 1A: [(9)(8)]
Number 2A: [(1)(2)(3)]
[0+0] = 24
[0+1] = 27
[1+0] = 43
[1+1] = 18
[2+0] = 26
[2+1] = 9
Fixup 0: old (24)(43) new (4)(45)
Fixup 1: old (45)(26) new (5)(30)
Fixup 2: old (30)(9) new (0)(12)
Fixup 3: old (12)(0) new (2)(1)
Fixup 4: old (1)(0) new (1)(0)
Significant digits = 5
Product : (1)(2)(0)(5)(4)
Product : 12054
Calculate 987654321 x 123456789012
Calculation: [987654321 * 123456789012]
Number 1: [987654321]
Number 2: [123456789012]
Number 1A: [(9)(8)(7)(6)(5)(4)(3)(2)(1)]
Number 2A: [(1)(2)(3)(4)(5)(6)(7)(8)(9)(0)(1)(2)]
[0+0] = 2
[0+1] = 4
[0+2] = 6
[0+3] = 8
[0+4] = 10
[0+5] = 12
[0+6] = 14
[0+7] = 16
[0+8] = 18
[1+0] = 5
[1+1] = 8
[1+2] = 11
[1+3] = 14
[1+4] = 17
[1+5] = 20
[1+6] = 23
[1+7] = 26
[1+8] = 9
[2+0] = 8
[2+1] = 11
[2+2] = 14
[2+3] = 17
[2+4] = 20
[2+5] = 23
[2+6] = 26
[2+7] = 9
[2+8] = 0
[3+0] = 20
[3+1] = 32
[3+2] = 44
[3+3] = 56
[3+4] = 68
[3+5] = 80
[3+6] = 72
[3+7] = 72
[3+8] = 81
[4+0] = 40
[4+1] = 60
[4+2] = 80
[4+3] = 100
[4+4] = 120
[4+5] = 120
[4+6] = 128
[4+7] = 145
[4+8] = 72
[5+0] = 67
[5+1] = 94
[5+2] = 121
[5+3] = 148
[5+4] = 155
[5+5] = 170
[5+6] = 194
[5+7] = 128
[5+8] = 63
[6+0] = 100
[6+1] = 133
[6+2] = 166
[6+3] = 179
[6+4] = 200
[6+5] = 230
[6+6] = 170
[6+7] = 111
[6+8] = 54
[7+0] = 138
[7+1] = 176
[7+2] = 194
[7+3] = 220
[7+4] = 255
[7+5] = 200
[7+6] = 146
[7+7] = 94
[7+8] = 45
[8+0] = 180
[8+1] = 202
[8+2] = 232
[8+3] = 271
[8+4] = 220
[8+5] = 170
[8+6] = 122
[8+7] = 77
[8+8] = 36
[9+0] = 205
[9+1] = 238
[9+2] = 280
[9+3] = 232
[9+4] = 185
[9+5] = 140
[9+6] = 98
[9+7] = 60
[9+8] = 27
[10+0] = 240
[10+1] = 284
[10+2] = 238
[10+3] = 193
[10+4] = 150
[10+5] = 110
[10+6] = 74
[10+7] = 43
[10+8] = 18
[11+0] = 285
[11+1] = 240
[11+2] = 196
[11+3] = 154
[11+4] = 115
[11+5] = 80
[11+6] = 50
[11+7] = 26
[11+8] = 9
Fixup 0: old (2)(5) new (2)(5)
Fixup 1: old (5)(8) new (5)(8)
Fixup 2: old (8)(20) new (8)(20)
Fixup 3: old (20)(40) new (0)(42)
Fixup 4: old (42)(67) new (2)(71)
Fixup 5: old (71)(100) new (1)(107)
Fixup 6: old (107)(138) new (7)(148)
Fixup 7: old (148)(180) new (8)(194)
Fixup 8: old (194)(205) new (4)(224)
Fixup 9: old (224)(240) new (4)(262)
Fixup 10: old (262)(285) new (2)(311)
Fixup 11: old (311)(240) new (1)(271)
Fixup 12: old (271)(196) new (1)(223)
Fixup 13: old (223)(154) new (3)(176)
Fixup 14: old (176)(115) new (6)(132)
Fixup 15: old (132)(80) new (2)(93)
Fixup 16: old (93)(50) new (3)(59)
Fixup 17: old (59)(26) new (9)(31)
Fixup 18: old (31)(9) new (1)(12)
Fixup 19: old (12)(0) new (2)(1)
Fixup 20: old (1)(0) new (1)(0)
Significant digits = 21
Product : (1)(2)(1)(9)(3)(2)(6)(3)(1)(1)(2)(4)(4)(8)(7)(1)(2)(0)(8)(5)(2)
Product : 121932631124487120852
$ bc <<< '987654321 * 123456789012'
121932631124487120852
$
Calculate 000 x 0000
Calculation: [000 * 0000]
Number 1: [000]
Number 2: [0000]
Number 1A: [(0)(0)(0)]
Number 2A: [(0)(0)(0)(0)]
[0+0] = 0
[0+1] = 0
[0+2] = 0
[1+0] = 0
[1+1] = 0
[1+2] = 0
[2+0] = 0
[2+1] = 0
[2+2] = 0
[3+0] = 0
[3+1] = 0
[3+2] = 0
Fixup 0: old (0)(0) new (0)(0)
Fixup 1: old (0)(0) new (0)(0)
Fixup 2: old (0)(0) new (0)(0)
Fixup 3: old (0)(0) new (0)(0)
Fixup 4: old (0)(0) new (0)(0)
Fixup 5: old (0)(0) new (0)(0)
Fixup 6: old (0)(0) new (0)(0)
Significant digits = 0
0
Product : 0
Observations on making debugging easier
This should get you going; there's a lot of refinements that could/should be made. This preserves most of your original code. It also shows you how I added code — assertions and printing operations — to see what was going on. When I saw this as the output from an early version of the code:
Calculation: [98 * 123]
Number 1: [98]
Number 2: [123]
Number 1A: [(9)(8)
Number 2A: [(0)(0)(0)
[0+0] = 0
[0+1] = 0
[1+0] = 0
[1+1] = 0
[2+0] = 0
[2+1] = 0
Fixup 0: old (0)(0) new (0)(0)
Fixup 1: old (0)(0) new (0)(0)
Fixup 2: old (0)(0) new (0)(0)
Fixup 3: old (0)(0) new (0)(0)
Fixup 4: old (0)(0) new (0)(0)
Significant digits = -1
Product :
it was easy to see where there was a problem (the second conversion loop), and from there it was easy to diagnose the main problem. When debugging, print inputs to make sure the program got what you expected. Print intermediate results to check that you get what you expected. Print final results carefully — make sure you are getting what you think you're getting. The use of (%d) illustrates the 'be careful'; when printing a digit string, it would have been easy to spot (19) is wrong whereas just 19 could be right or wrong, depending.
I'll also point you towards C #define macro for debug printing for information on how I'd use conditional compilation to deal with the debug printing if it was going to remain a useful part of a long-term program. You can find the relevant code in my SOQ (Stack Overflow Questions) repository on GitHub as files debug.c and debug.h in the src/libsoq sub-directory.
The code here only gives correct output till the factorial of 21 and after that its correct upto 16 digits from the left then remaining digits are just given as zero. I tried changing the type of variable c from double to long double but it just gives errors or doesn't print the factorials.
#include <stdio.h>
FILE *fp;
long double facto(int i);
int main() {
int n, i;
double c;
printf("enter no. to find factorial till:\n");
scanf("%d", &n);
fp = fopen("output_of_factorial.txt", "w");
fputs("Number |\t Factorial\n\n", fp);
for (i = 1; i <= n; i++) {
c = facto(i);
fprintf(fp, "%d\t|\t %.0Lf\n", i, c);
}
fclose(fp);
return 0;
}
long double facto(int x) {
if (x == 1)
return 1;
else
return x * facto(x - 1);
}
Tye double only has 53 bits of precision, long double probably has 80 bits on your platform. Using floating point arithmetics will give you an approximate result that is correct for the most significant digits. Using integers give you the exact result, but only if it is smaller than the range of the type.
You can use the type long long that is at least 64-bit wide, thus 19 digits, or for one more bit, type unsigned long long that allows for integers twice as large:
LLONG_MAX = 9223372036854775807 // > 9.22e19
ULLONG_MAX = 18446744073709551615 // > 1.84e20
Here is a modified version of the code:
#include <stdio.h>
unsigned long long facto(int i);
int main(void) {
int n, i;
unsigned long long c;
FILE *fp;
printf("enter no. to find factorial till: ");
if (scanf("%d", &n) == 1) {
fp = fopen("output_of_factorial.txt", "w");
if (fp != NULL) {
fputs("Number | Factorial\n\n", fp);
for (i = 1; i <= n; i++) {
c = facto(i);
fprintf(fp, "%6d | %20llu\n", i, c);
}
fclose(fp);
}
}
return 0;
}
unsigned long long facto(int x) {
if (x <= 1)
return 1;
else
return x * facto(x - 1);
}
It works all the way to 20:
Number | Factorial
1 | 1
2 | 2
3 | 6
4 | 24
5 | 120
6 | 720
7 | 5040
8 | 40320
9 | 362880
10 | 3628800
11 | 39916800
12 | 479001600
13 | 6227020800
14 | 87178291200
15 | 1307674368000
16 | 20922789888000
17 | 355687428096000
18 | 6402373705728000
19 | 121645100408832000
20 | 2432902008176640000
But fails for 21 and above because of arithmetic overflow.
To go further, you could use 128-bit integers if they are available on your platform (uint128_t, __uint128 or __uint128_t) but you would need to write your own conversion function to output the decimal representation.
A better approach would be to use multi-precision (aka bignum) packages that can handle extremely large numbers, typically only bound by available memory.
C normally uses the machines word size for integer storage. With factorials you end up running out of bits for storage quite quickly. At some point you will need to store the result in an array and account for carries. Assembly might be some help (since you might find multiplication with carries) or alternatively you can use the top half of your integer as the and write a multiplication algorithm similar to thecway you were taught to multiply in school.
If all this sounds tedious, you can use an arbitrary precision library.
Just so you know
long long is 64 bits on many platforms and gcc supports int_128 on some platforms. There however will give limited milage with factorials.
For illustration purposes, here is a simplistic implementation of bignum I just wrote with a printable internal as an ASCII string:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct bignum {
const char *number; // pointer to the printable representation
char *array; // array of size+1 byte for the digits
size_t size; // maximum number of significant digits
size_t offset; // offset if the first significant digit
char buf[4 * sizeof(size_t)];
} bignum;
void bignum_free(bignum *bp) {
if (bp && bp->array != bp->buf) {
free(bp->array);
bp->array = bp->buf;
}
}
size_t bignum_realloc(bignum *bp) {
size_t extra = bp->size / 2 + bp->size / 8; // use pseudo Fibonacci sequence
char *array, *source = bp->array;
if (bp->array == bp->buf) {
array = malloc(bp->size + extra);
} else {
source = array = realloc(bp->array, bp->size + extra);
}
if (array == NULL)
return 0;
memmove(array + extra, source, bp->size + 1);
bp->array = array;
bp->offset += extra;
bp->size += extra;
return extra;
}
bignum *bignum_normalize(bignum *bp) {
while (bp->offset < bp->size && bp->array[bp->offset] == '0') {
bp->offset++;
}
bp->number = bp->array + bp->offset;
if (bp->offset >= bp->size) {
bp->number = (bp->offset == bp->size) ? "0" : "overflow";
}
return bp;
}
bignum *bignum_set_overflow(bignum *bp) {
bp->offset = bp->size + 1;
return bignum_normalize(bp);
}
bignum *bignum_init(bignum *bp) {
size_t size = sizeof(bp->buf) - 1;
bp->array = bp->buf;
bp->offset = bp->size = size;
bp->array[size] = '\0';
return bignum_normalize(bp);
}
bignum *bignum_set_string(bignum *bp, const char *value) {
bp->offset = bp->size; // default value is 0
if (value) {
while (*value == '0') {
value++;
}
size_t len = strlen(value);
while (len > bp->size && bignum_realloc(bp))
continue;
if (len > bp->size) {
bp->offset = bp->size + 1; // overflow
} else {
bp->offset = bp->size - len;
memcpy(bp->array + bp->offset, value, len);
}
}
return bignum_normalize(bp);
}
bignum *bignum_init_string(bignum *bp, const char *value) {
return bignum_set_string(bignum_init(bp), value);
}
bignum *bignum_add_uint(bignum *bp, unsigned int num) {
unsigned long long carry = num;
if (bp->offset > bp->size || num == 0) {
return bp;
}
for (size_t i = bp->size;;) {
if (carry == 0) {
if (i < bp->offset) {
bp->offset = i;
}
break;
}
if (i == 0) {
bp->offset = 0;
i += bignum_realloc(bp);
if (i == 0) {
bp->offset = bp->size + 1; // overflow
break;
}
}
i--;
if (i >= bp->offset) {
carry += bp->array[i] - '0';
}
bp->array[i] = '0' + carry % 10;
carry /= 10;
}
return bignum_normalize(bp);
}
bignum *bignum_set_value(bignum *bp, unsigned int value) {
bp->offset = bp->size;
return bignum_add_uint(bp, value);
}
bignum *bignum_init_value(bignum *bp, unsigned int value) {
return bignum_add_uint(bignum_init(bp), value);
}
bignum *bignum_mul_uint(bignum *bp, unsigned int num) {
unsigned long long carry = 0;
if (bp->offset > bp->size || num == 1) {
return bp;
}
if (num == 0) {
bp->offset = bp->size; /* special case 0 for speed */
} else {
for (size_t i = bp->size;;) {
if (i == 0) {
bp->offset = 0;
if (carry == 0) {
break;
}
i += bignum_realloc(bp);
if (i == 0) {
bp->offset = bp->size + 1; // overflow
break;
}
}
i--;
if (i >= bp->offset) {
carry += (unsigned long long)num * (bp->array[i] - '0');
} else {
if (carry == 0) {
bp->offset = i + 1;
break;
}
}
bp->array[i] = '0' + carry % 10;
carry /= 10;
}
}
return bignum_normalize(bp);
}
int main(int argc, char *argv[]) {
unsigned int n0 = 1, n1 = 100, max_digits = -1;
bignum c;
if (argc > 1) {
n0 = n1 = strtol(argv[1], NULL, 0);
if (argc > 2) {
n1 = strtol(argv[2], NULL, 0);
if (argc > 3) {
max_digits = strtol(argv[3], NULL, 0);
}
}
if (n1 < n0) {
max_digits = n1;
n1 = n0;
}
}
bignum_init_value(&c, 1);
printf("%6s | %s\n", "Number", "Factorial");
for (unsigned int i = 1; i <= n1; i++) {
bignum_mul_uint(&c, i);
if (i >= n0) {
if (c.size - c.offset > max_digits) {
printf("%6u | %.1s.%.*se%zu\n",
i, c.number, max_digits - 1, c.number + 1,
c.size - c.offset - 1);
} else {
printf("%6u | %s\n", i, c.number);
}
}
}
bignum_free(&c);
return 0;
}
You can pass arguments on the command line:
chqrlie#macbook ~/dev/stackoverflow > ./factomp 1 60
Number | Factorial
1 | 1
2 | 2
3 | 6
4 | 24
5 | 120
6 | 720
7 | 5040
8 | 40320
9 | 362880
10 | 3628800
11 | 39916800
12 | 479001600
13 | 6227020800
14 | 87178291200
15 | 1307674368000
16 | 20922789888000
17 | 355687428096000
18 | 6402373705728000
19 | 121645100408832000
20 | 2432902008176640000
21 | 51090942171709440000
22 | 1124000727777607680000
23 | 25852016738884976640000
24 | 620448401733239439360000
25 | 15511210043330985984000000
26 | 403291461126605635584000000
27 | 10888869450418352160768000000
28 | 304888344611713860501504000000
29 | 8841761993739701954543616000000
30 | 265252859812191058636308480000000
31 | 8222838654177922817725562880000000
32 | 263130836933693530167218012160000000
33 | 8683317618811886495518194401280000000
34 | 295232799039604140847618609643520000000
35 | 10333147966386144929666651337523200000000
36 | 371993326789901217467999448150835200000000
37 | 13763753091226345046315979581580902400000000
38 | 523022617466601111760007224100074291200000000
39 | 20397882081197443358640281739902897356800000000
40 | 815915283247897734345611269596115894272000000000
41 | 33452526613163807108170062053440751665152000000000
42 | 1405006117752879898543142606244511569936384000000000
43 | 60415263063373835637355132068513997507264512000000000
44 | 2658271574788448768043625811014615890319638528000000000
45 | 119622220865480194561963161495657715064383733760000000000
46 | 5502622159812088949850305428800254892961651752960000000000
47 | 258623241511168180642964355153611979969197632389120000000000
48 | 12413915592536072670862289047373375038521486354677760000000000
49 | 608281864034267560872252163321295376887552831379210240000000000
50 | 30414093201713378043612608166064768844377641568960512000000000000
51 | 1551118753287382280224243016469303211063259720016986112000000000000
52 | 80658175170943878571660636856403766975289505440883277824000000000000
53 | 4274883284060025564298013753389399649690343788366813724672000000000000
54 | 230843697339241380472092742683027581083278564571807941132288000000000000
55 | 12696403353658275925965100847566516959580321051449436762275840000000000000
56 | 710998587804863451854045647463724949736497978881168458687447040000000000000
57 | 40526919504877216755680601905432322134980384796226602145184481280000000000000
58 | 2350561331282878571829474910515074683828862318181142924420699914240000000000000
59 | 138683118545689835737939019720389406345902876772687432540821294940160000000000000
60 | 8320987112741390144276341183223364380754172606361245952449277696409600000000000000
The program is only limited by available memory, but it takes 54 seconds to compute factorial(100000), a number with 456574 decimal digits. You can pass a limit to the number of digits:
chqrlie#macbook ~/dev/stackoverflow > ./factomp 100000 60
Number | Factorial
100000 | 2.82422940796034787429342157802453551847749492609122485057891e456573
I was solving this algorithm problem but i am unable to find the reference answer as provided. Any help or tip in solving this problem is appreciated.
The problem statement is as follows
In an area of size NxN each cell contains 1 at time T=0 where 1 represent one user.
Hence, at T= 0 and N = 5 the matrix is as below
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
Each cell is a user.
Now at time T =1,2,3 etc the position of each user changes.
if x(row)+y(col) = even
New x = (x+y)^2%N
New y = (x*y)%N
if x(row)+y(col) = odd
New x = (x+y)%N
New y = |x-y|%N
Find the maximum users at time T = 3
Reference, for N=5 and T= 3 Max users in a cell should be 8.
I have tried solving this problem but I always end up with 11 as my max if I move all the users and 6 if I move just 1 user every time.
Any tips where I might be going wrong in understanding or solving this problem is very much appreciated. Thank you.
Below is my code which I used for solving this problem
Its in C programming language. Thanks in advance.
int abs(int y, int x)
{
int temp = x - y;
return temp > 0 ? temp : -temp;
}
int new_x(int x, int y, int n)
{
if((x+y)%2)
return (((x+y)*(x+y))%n);
else
return (x+y)%n;
}
int new_y(int x, int y, int n)
{
if((x+y)%2)
return (x*y)%n;
else
return ((abs(x,y))%n);
}
void print_matrix(int *p, int n, int time)
{
int i,j;
int sum = 0;
for(i=0;i<n;i++) {
for(j=0;j<n;j++) {
printf("%d\t",*((p+i*n)+j));
sum += *((p+i*n)+j);
}
printf("\n");
}
printf("Sum = %d\t at T=%d\n",sum, time);
}
int main(void)
{
int T = 3;
int N = 5;
int test_case,i,j,x,y,item, sum, val;
int arr_initial[5][5];
//====================================
//For Time T=0 all elements are 1
//====================================
for(i=0;i<N;i++){
for(j=0;j<N;j++) {
arr_initial[i][j] = 1;
}
}
//=====================================
printf("Initial Matrix at T0 time\n");
print_matrix((int*)arr_initial, N, 0);
printf("\n");
//====================================
//Now calculate the new position for Time T1,T2 & T3
//====================================
for(test_case =1; test_case<=T;test_case++)
{
sum = 0;
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{//Get NewX and NewY for movement
x = new_x(i,j,N);
y = new_y(i,j,N);
if(x==i && y==j)
{
//No movement as initial and new position is same
}
else{
//There is a movement
item = arr_initial[i][j];
val = item -1;
if(val<0)
{
//no item to move
}
else
{
arr_initial[x][y] += arr_initial[i][j];
arr_initial[i][j] = 0;
}
}
}
}
//=======================================================
printf("\n");
printf("Matrix at Time T = %d\n",test_case);
print_matrix((int*)arr_initial, N, test_case);
printf("\n");
}
return 0;
}
Your task statement differs from the code - you say (x*y)^2 but implement (x+y)^2. This solution works by building the next generation in a separate array.
#include <stdio.h>
#include <string.h>
#include <math.h>
#define N 5
int main(void) {
char matrix[N][N], next[N][N];
int x, y, t, x2, y2, max;
memset(matrix, 1, sizeof(matrix)); // initialise matrix
for(t=0; t<3; t++) {
memset(next, 0, sizeof(next)); // clear next generation
for (y=0; y<N; y++)
for (x=0; x<N; x++) {
if ((x + y) % 2 == 0) {
x2 = ((x + y) * (x + y)) % N;
y2 = (x * y) % N;
} else {
x2 = (x + y) % N;
y2 = abs(x - y) % N;
}
next[y2][x2] += matrix[y][x];
}
memcpy(matrix, next, sizeof(matrix)); // copy back
}
max = 0;
for (y=0; y<N; y++) { // print matrix
for (x=0; x<N; x++) {
if (max < matrix[y][x])
max = matrix[y][x];
printf("%-3d", matrix[y][x]);
}
printf ("\n");
}
printf ("Max is %d\n", max);
return 0;
}
Program output:
1 0 0 0 0
0 2 0 0 4
0 0 0 0 0
4 8 0 4 0
0 2 0 0 0
Max is 8
1) You calculate if (x+y) is odd wrongly. If (x+y)%2 is true than x+y is odd. Therefore:
int new_x(int x, int y, int n)
{
if((x+y)%2)
return (((x+y)*(x+y))%n);
else
return (x+y)%n;
}
int new_y(int x, int y, int n)
{
if((x+y)%2)
return (x*y)%n;
else
return ((abs(x,y))%n);
}
should be changed to:
int new_x(int x, int y, int n)
{
if((x+y)%2)
return (x+y)%n;
else
return (((x+y)*(x+y))%n);
}
int new_y(int x, int y, int n)
{
if((x+y)%2)
return ((abs(x,y))%n);
else
return (x*y)%n;
}
2) You change fields in array, that were possibly still not processed:
arr_initial[x][y] += arr_initial[i][j];
You need to use another matrix, initialized to 0, to track new values in it and copy changes back to original matrix at the end of each step.
The problem is that you are reading the value from the array and the value might already be modified, which becomes the value for T + 1!
Thus, you need another array to keep track of the value for T. Here is the idea:
for(i = 0; i < N; i ++)
for (j = 0; j < N; j ++)
alter_arr[i][j] = current_arr[i][j];
for(i=0;i<N;i++)
{
for(j=0;j<N;j++)
{//Get NewX and NewY for movement
x = new_x(i,j,N);
y = new_y(i,j,N);
printf("%d, %d moved to %d, %d\n", i, j, x, y);
if(x==i && y==j)
{
// no movement
}
else{
//There is a movement
item = current_arr[i][j];
val = item -1;
if(val<0)
{
//no item to move
}
else
{
alter_arr[x][y] += current_arr[i][j];
alter_arr[i][j] -= current_arr[i][j];
}
}
}
}
int (*tmp)[5] = current_arr;
current_arr = alter_arr;
alter_arr = tmp;
//=======================================================
printf("\n");
printf("Matrix at Time T = %d\n",test_case);
And change the if statement in your new_x and new_y function.
Below is the result, the max is 8 at T = 3:
Initial Matrix at T0 time
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
Sum = 25 at T=0
Matrix at Time T = 1
1 2 0 2 0
2 2 0 4 2
0 2 0 0 0
0 2 0 2 0
2 2 0 0 0
Sum = 25 at T=1
Matrix at Time T = 2
1 0 0 4 0
2 4 0 6 2
0 0 0 0 0
0 2 0 2 0
0 2 0 0 0
Sum = 25 at T=2
Matrix at Time T = 3
1 0 0 4 0
0 2 0 8 2
0 0 0 0 0
0 0 0 4 0
0 4 0 0 0
Sum = 25 at T=3