I am trying to create a large pascal triangle that prints up to 70 lines. My code works fine at first but it started to print out the wrong output when it reaches the 65th line. I know the problem to it and I've tried using GMP. Unfortunately the software that i use to code doesn't support GMP. Is there any other ways that i can do this without using GMP?
char str;
int value;
int pascal(int n)
{
for (int i = 1; i < n + 2; i++)
{
unsigned long number = 1;
for (int j = 1; j < i + 1; j++)
{
if(j == i)
{
printf("%lu\n", number);
}
else
{
printf("%lu ", number);
}
number = (number * (i - j) / j);
}
}
return 0;
}
Is there any other ways that i can do this without using GMP?
The integer math needed exceeds basic 64-bit math in forming numbers such as 109069992321755544170, a 67-bit number with more than 64 leading significant bits.
Although the widest integer uintmax_t may meet the more than 64-bit math needs, it is commonly only 64-bit.
long double often has a fair amount of precision (only 64-bit on my platform), but that is not specified to meet OP's need and invokes the usually FP issues of solving an integer problem.
Fortunately the extended math needed is only a multiply and divide. A simple, although not highly efficient, string multiply and divide meets the need.
void string_mult(char *y, unsigned x) {
size_t len = strlen(y);
unsigned acc = 0;
size_t i = len;
while (i > 0) {
i--;
acc += (y[i] - '0') * x;
y[i] = acc % 10 + '0';
acc /= 10;
}
while (acc) {
memmove(&y[1], &y[0], ++len);
y[0] = acc % 10 + '0';
acc /= 10;
}
}
unsigned string_div(char *y, unsigned x) {
size_t len = strlen(y);
unsigned acc = 0;
for (size_t i = 0; i < len; i++) {
acc *= 10;
acc += y[i] - '0';
y[i] = acc / x + '0';
acc %= x;
}
while (y[0] == '0' && len > 1) {
memmove(&y[0], &y[1], len);
len--;
}
return acc;
}
void pascal(unsigned n) {
printf("%u: ", n);
for (unsigned i = 1; i < n + 2; i++) {
char s[100] = "1";
for (unsigned j = 1; j <= i; j++) {
printf("%s ", s);
string_mult(s, i - j);
string_div(s, j);
}
printf("\n");
}
}
int main() {
for (unsigned i = 0; i <= 70; i++)
pascal(i);
}
Output
...
1 70 2415 54740 916895 12103014 131115985 1198774720 9440350920 65033528560 396704524216 2163842859360 10638894058520 47465835030320 193253756909160 721480692460864 2480089880334220 7877932561061640 23196134763125940 63484158299081520 161884603662657876 385439532530137800 858478958817125100 1791608261879217600 3508566179513467800 6455761770304780752 11173433833219812840 18208558839321176480 27963143931814663880 40498346384007444240 55347740058143507128 71416438784701299520 87038784768854708790 100226479430802391940 109069992321755544170 112186277816662845432 109069992321755544170 100226479430802391940 87038784768854708790 71416438784701299520 55347740058143507128 40498346384007444240 27963143931814663880 18208558839321176480 11173433833219812840 6455761770304780752 3508566179513467800 1791608261879217600 858478958817125100 385439532530137800 161884603662657876 63484158299081520 23196134763125940 7877932561061640 2480089880334220 721480692460864 193253756909160 47465835030320 10638894058520 2163842859360 396704524216 65033528560 9440350920 1198774720 131115985 12103014 916895 54740 2415 70 1
On further review, a long double may work, yet my efforts failed at pascal(69).
Related
The problem I am facing:
I need to find a way to deal with very large sets (3 to 10000000) of positive and negative ints, this seemed relatively impossible based off of previous experiments.
However, I received hope when I found a Algorithm on github that is really efficient.
However, I really need to adjust it to work with positive and negative numbers... but I am struggling, I know the unsigned int's should be int. but that's all I've got so far.
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
short* flag;
int N, K, correspond = 0;
unsigned int* check, X = 0;
clock_t t1, t2;
void init() {
int i, j;
printf("N=");
scanf_s("%d", &N);
check = malloc(sizeof(unsigned int) * N);
if (check == NULL) {
perror("Out of memory");
exit(-1);
}
srand((unsigned)time(NULL));
printf("\n///check list///\n");
for (i = 0; i < N; i++) {
check[i] = rand() % 1000000 + 1;
printf("%uyen ", check[i]);
}
printf("\n");
K = rand() % N;
flag = malloc(sizeof(short) * N);
for (i = 0; i < N; i++)flag[i] = 0;
i = 0;
while (i <= K) {
j = rand() % N;
if (flag[j] == 0) {
flag[j] = 1;
X = X + check[j];
i++;
}
}
printf("\nX=%uyen\n", X);
}
void swap(int j, int k) {
unsigned int tmp;
tmp = check[j];
check[j] = check[k];
check[k] = tmp;
}
int partition(int left, int right) {
int j = left, k = right;
unsigned int v;
v = check[(left + right) / 2];
do {
while (check[j] > v) j++;
while (v > check[k]) k--;
swap(j, k);
} while (check[j] != check[k]);
return j;
}
void quicksort(int left, int right) {
int j;
if (left < right) {
j = partition(left, right);
quicksort(left, j - 1);
quicksort(j + 1, right);
}
}
void func(unsigned int sum, int i) {
int j, k, t = 0;
if (sum == X) {
correspond = 1;
t2 = clock();
double record = (double)(t2 - t1) / CLOCKS_PER_SEC;
printf("\nAnswer : ");
for (k = 0; k < N; k++) {
if (flag[k] == 1) {
if (t == 0) t = 1;
else if (t == 1) printf("+");
printf("%u", check[k]);
}
}
printf("\n\nThinking time : %f sec . \n", record);
if (record <= 60) printf("Triumph!\n");
else printf("Failure...\n");
return;
}
else if (sum < X) {
for (j = i + 1; (j <= N) && (correspond == 0); j++) {
flag[j] = 1;
func(sum + check[j], j);
}
}
flag[i] = 0;
return;
}
int main() {
int i;
init();
t1 = clock();
for (i = 0; i < N; i++)flag[i] = 0;
quicksort(0, N);
func(0, 0);
return 0;
}
EDITS:
Thanks for all of your inputs, it does help to get some constructive criticism.
To start off here is the to the Github Repo https://github.com/parthnan/SubsetSum-BacktrackAlgorithm credit goes to Parth Shirish Nandedkar.
The name of this Algorithm is "Amortized O(n) algorithm based on Recursive Backtracking" I am not really sure why it would be called "Amortized" as this would mean it divides the input array into multiple subset and use polynomial-time algorithm on each one.
**I have tried to fix the issues mentioned by ** "chux - Reinstate Monica"... please let me know if I did it incorrectly.
seemed relatively impossible based off of previous experiments.
First fix known problems.
At least these problems:
Out of range access
flag = malloc(sizeof(short) * (N + 1)); allocates such that code can access flag[0] to flag[N].
for (k = 1; k <= N + 1; k++) { if (flag[k] == 1) { attempts to access flag[N+1]. Result undefined behavior (UB).
Mis-matched printf
warning: format '%ld' expects argument of type 'long int', but argument 2 has type 'unsigned int' [-Wformat=]
More undefined behavior (UB).
printf("%ldyen ", check[i]);
printf("\nX=%ldyen\n", X);
Allocation success
Since the goal is "very large sets (3 to 10000000)", code definitely should check allocation success to save debug time.
check = malloc(sizeof(unsigned int) * (N + 1));
if (check == NULL) {
perror("Out of memory");
exit -1;
}
Side issues:
Code uses non-idiomatic array access
Code indexes [1...N]. More common to use [0...N-1].
Heavy use of global variables
More common to local variables, passing data as needed on function arguments.
"deal with ... positive and negative ints"
Fix that before posting - or if not important, no need to mention it here.
I tackled the problem by first figuring out the length of two given numbers and aligning the one with less digits (if one exists) into a new array so that the ones, tens, hundreds etc. align with the bigger number's ones, tens, hundreds, etc.
Then I wanted to save the sum of each two aligned elements (with a mod of 10) into a new array while checking if the sum of digits is greater than 10 - just the basic sum stuff. Now the problem occurs with adding two elements into the aplusb integer and I've tried fixing it with writing
int aplusb = (lengthA[max-i]-'0') +(temp[max-i]-'0');
but it doesn't work. I'm stuck and I don't know what to do. Please help.
The whole code:
#include <stdio.h>
#include <math.h>
int main(){
char a[10000];
char b[10000];
scanf("%s %s", &a, &b);
char sum[10000];
int lengthA = 0;
int lengthB = 0;
int i = 0;
while(a[i]){
i++;
} lengthA = i;
i = 0;
while(b[i]){
i++;
} lengthB = i;
char temp[10000];
int aplusb;
int carry = 0;
int max = lengthA;
int difference = abs(lengthA - lengthB);
if(lengthA>lengthB){
for(i=0; i<lengthA; i++){
temp[i+difference]=b[i];
}
for(i=0; i<=max; i++){
aplusb = lengthA[max-i]+temp[max-i]; //<-- this is the problematic line
if(carry = 1) aplusb++;
if(aplusb>9){
carry = 1;
aplusb%=10;
}
sum[i]=aplusb;
}
}
for(i=0; i<=max; i++){
printf("%c", sum[i]);
}
/*
if(lengthB>lengthA){
max = lengthB;
for(i=0; i<lengthB; i++){
temp[i+difference]=a[i];
}
}*/
return 0;
}
Doing operations and storing on very large numbers is very akin to doing operations and storing polynomials, i.e. with x = 10. a0 + a1.10 + a2.10^2 ... + an.10^n.
There are many polynomial libraries on the Internet, where you could find inspiration. All operations on your very large numbers can be expressed in terms of polynomials. This means that by using base 2^8, or even base 2^63, instead of base 10 to internally store your large numbers you would greatly improve performance.
You must also normalize your coefficients after operations to keep them positive. Operations may result in a negative coefficient, That can easily be fixed, as it is very similar to borrowing after a subtraction, this means coefficients must be larger than your base by 1bit.
To convert back to base 10, you'd need to solve r (your result) for v (your value), such as r(10)=v(2^63). This has only one solution, if you enforce the positive coefficients rule.
[note] After thinking about it some more: the rule on positive coefficients may only be necessary for printing, after all.
Example: adding. no memory error checking
int addPolys(signed char** result, int na, const signed char* a, int nb, const signed char* b)
{
int i, nr, nmin, carry, *r;
nr = max(na, nb) + 1;
nmin = min(na, nb);
r = malloc(sizeof(signed char) * (na + nb + 1));
if (nb < na)
{
nr = nb;
}
for (i = 0; i < nmin; ++i)
{
r[i] = a[i] + b[i];
}
for (; i < na; ++i)
{
r[i] = a[i];
}
for (; i < nb; ++i)
{
r[i] = b[i];
}
r[nr - 1] = 0;
// carry - should really be a proc of its own, unoptimized
carry = 0;
for (i = 0; i < nr; ++i)
{
r[i] += carry;
if (r[i] > 10)
{
carry = r[i] / 10;
r[i] %= 10;
}
else if (r[i] < 0)
{
carry = (r[i] / 10) - 1;
r[i] -= (carry * 10);
}
else
carry = 0;
}
// 'remove' leading zeroes
for (i = nr - 1; i > 0; --i)
{
if (r[i] != 0) break;
}
++i;
*result = r;
if (i != nr)
{
*result = realloc(i * sizeof(signed char));
}
return i; // return number of digits (0 being 1 digit long)
}
That code is working now for any two positive numbers with up to ten thousand digits:
#include <stdio.h>
#include <math.h>
#include <string.h>
int main(){
char chara[10000];
char charb[10000];
scanf("%s %s", &chara, &charb);
int lengthA = strlen(chara);
int lengthB = strlen(charb);
int max = lengthA;
if(lengthB>lengthA) max=lengthB;
int dif = abs(lengthA - lengthB);
//ustvari int tabele
int a[max];
int b[max];
int sum[max+1];
// nastavi nule
int i;
for(i=0; i<max; i++){
a[i] = 0;
b[i] = 0;
sum[i] = 0;
} sum[max] = 0;
//prekopiraj stevila iz char v int tabele &obrni vrstni red
for(i=0; i<lengthA; i++){
a[i] = chara[lengthA-i-1]-'0';
}
for(i=0; i<lengthB; i++){
b[i] = charb[lengthB-i-1]-'0';
}
int vsota;
int prenos = 0;
for(i=0; i<max; i++){
vsota = a[i]+b[i] + prenos;
if(vsota>=10) prenos = 1;
else if (vsota<10) prenos = 0;
sum[i]=vsota%10;
}
if(prenos==1){
sum[max] = 1;
for(i = max; i>=0; i--){
printf("%d", sum[i]);
}
} else {
for(i = max-1; i>=0; i--){
printf("%d", sum[i]);
}
}
return 0;
}
I was trying to solve Project Euler question 16 using c. I did not use bignnum libraries. The question asks 2^1000. I decided to store every digit of that number in an array.
For Example: 45 means arr[0]=4, arr[1]=5;
The problem is definitely i the function int multi.
#include<stdio.h>
#include<conio.h>
int multi(int *base, int k);// does the multiplication of array term by 2
void switcher();//switches every term when the fore mostvalue is >10
int finder();// finds the array address of last value
int arr[1000];
int summer();//sums all values of the array
int main()
{
arr[1000] = { 0 };
arr[0] = 1;
int i, j, sum, k, p;
for (i = 0; i < 1000; i++)
{
j = 0;
k = finder();
p = multi(arr + k, j);
}
sum = summer();
printf("sum of digits of 2^1000 is %d", sum);
_getch();
}
int multi(int *base, int k)
{
int p;
if (base == arr)
{
*base = *base - 1;
*base = *base + k;
if (*base > 10)
{
*base = *base - 10;
switcher();
}
return 0;
}
*base = *base * 2;
*base = *base + k;
if (*base > 10)
{
*base = *base - 10;
p = multi(base - 1, 1);
}
else
{
p = multi(base - 1, 0);
}
}
void switcher()
{
int j;
for (j = 0;; j++)
{
if (arr[j] == 0)
{
break;
}
}
j--;
for (; j > 0; j--)
{
arr[j + 1] = arr[j];
}
arr[0] = 1;
}
int finder()
{
int j;
for (j = 0;; j++)
{
if (arr[j] == 0)
{
break;
}
}
return --j;
}
int summer()
{
int summ, i;
summ = 0;
for (i = 0; i<1000; i++)
{
summ = summ + arr[i];
if (arr[i] == 0)
break;
}
return summ;
}
It compiles but during runtime it shows Access Write Violation, base was ......
Please explain this error and how to resolve it ?
Array is of 100 Bytes but you are looping for 1000. Also in function Finder() , you do not have a limit on variable j so your array size is going beyond 100 bytes.
Also use memset to assign array variables to 0.
As said in the comments, 2^1000 has 302 decimal digits.
You're going far outside your array.
But your code is very complicated because you store the digits with the most significant one first.
Since you're only interested in the digits and not the order in which they would be written, you can store the number "in reverse", with the least significant digit first.
This makes the code much simpler, as you can loop "forwards" and no longer need to shuffle array elements around.
Using -1 as "end of number" marker, it might look like this:
void twice(int* digits)
{
int i = 0;
int carry = 0;
while (digits[i] >= 0)
{
digits[i] *= 2;
digits[i] += carry;
if (digits[i] >= 10)
{
carry = 1;
digits[i] -= 10;
}
else
{
carry = 0;
}
i++;
}
if (carry)
{
digits[i] = 1;
digits[i+1] = -1;
}
}
int main()
{
int digits[302] = {1, -1}; /* Start with 1 */
twice(digits); /* digits is now { 2, -1 } */
return 0;
}
I am trying to implement the sieve of eratosthenes in C. The code works for small input values, but once the input goes beyond a certain range, a run- time error is thrown. This is the second problem in the classical section of the SPOJ base. What is the mistake?
#include<stdio.h>
#include<math.h>
int prime(unsigned long int, unsigned long int);
int main()
{
int nitem;
unsigned long int sn,fn;
scanf("%d", &nitem);
while(nitem)
{
scanf("%lu", &fn);
//printf("%d",fn);
scanf("%lu", &sn);
prime(fn, sn);
nitem--;
}
return 0;
}
int prime(unsigned long int fn, unsigned long int sn)
{
unsigned long int prim[100000];
int i,j,k;
for(i = 0; i < 100000; i++)
{
prim[i] = 1;
}
prim[0] = 0;
prim[1] = 0;
//printf("%d", sn);
//printf("%d", k);
//printf("%d", (k <= sn));
for(k = 2; k <= sqrt(sn); k++)
{
// printf("alksnc%5d", k);
if(prim[k] == 1)
{
for(j = 2; (k * j) <= sn; j++)
{
//printf("%d", prim[k]);
prim[k * j] = 0;
}
}
}
for(int i = 0; i <= sn; i++)
{
if(prim[i] !=0 && i >= fn)
{
printf("%lu\n", i);
}
}
printf("\n");
return;
}
Input:
1
100000 100345
output:
run time error
Input:
1
3 5
output:
3
5
We can make more efficient use of memory (2x) by only sieving odd numbers as all the even numbers you're processing waste time and space. It's trickier to work out but gives us something like:
#include <math.h>
#include <libc.h>
#define MAX_ODD_PRIMES 1048576
void prime(unsigned long fn, unsigned long sn)
{
unsigned char primes[MAX_ODD_PRIMES];
for (unsigned long i = 0; i < MAX_ODD_PRIMES; i++)
{
primes[i] = TRUE;
}
primes[0] = 0; // preset first odd, '1'
for (unsigned long k = 3; k <= sqrt(sn) + 1; k += 2)
{
if (primes[k / 2])
{
for (unsigned long j = 3; (k * j) <= sn; j += 2)
{
primes[k * j / 2] = FALSE;
}
}
}
if (fn <= 2)
{
printf("2\n");
fn = 3;
}
for (unsigned long i = fn / 2; i * 2 + 1 <= sn; i++)
{
if (primes[i])
{
printf("%lu\n", i * 2 + 1);
}
}
}
EXAMPLE
> ./a.out
1 1999900 2000000
1999957
1999969
1999979
1999993
>
1) Array range error.
By changing code
for (j = 2; (k * j) <= sn; j++) {
if (k * j >= 100000) {
printf("Out of range %d %d\n", k, j);
exit(1);
}
prim[k * j] = 0;
}
}
With input 2, 100000
Output
Out of range 2 50000
By using an array (VLA) sized to the task, this is avoided. Many other optimizations available. Consider also a malloc() array.
void prime(unsigned long int fn, unsigned long int sn) {
unsigned long int prim[sn + 1];
2) int prime() eventually performs return; where return something; is expected. Suggest changing function to void prime()
int prime(unsigned long int fn, unsigned long int sn) {
unsigned long int prim[100000];
...
printf("\n");
return;
}
I tried to convert a negative decimal number into a binary number and this code perfectly works on my computer, but the code doesn't work another computer.
I didn't get how it is possible. What is wrong in my code?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
void decTobin(int dec, int s)
{
int b[s], i = 0;
while (dec >= 0 && i != s - 1) {
b[i] = dec % 2;
i++;
dec /= 2;
}
int j = i;
printf("%d", dec);
for (j = i - 1; j >= 0; j--) {
if (b[j] == NULL)
b[j] = 0;
printf("%d",b[j]);
}
}
void ndecTobin(int dec, int s)
{
int b[s], i = 0, a[s], decimal, decimalvalue = 0, g;
while (dec >= 0 && i != s-1) {
b[i] = dec % 2;
i++;
dec /= 2;
}
int j = i;
printf("%d",dec);
for (j = i - 1; j >= 0; j--) {
if (b[j] == NULL)
b[j] = 0;
printf("%d",b[j]);
}
printf("\n");
a[s - 1] = dec;
for (j = s - 2; j >= 0; j--) {
a[j] = b[j];
}
for (j = s - 1; j >= 0; j--) {
if (a[j] == 0)
a[j] = 1;
else
a[j] = 0;
printf("%d",a[j]);
}
for (g = 0; g < s; g++) {
decimalvalue = pow(2, g) * a[g];
decimal += decimalvalue;
}
decimal = decimal + 1;
printf("\n%d\n", decimal);
decTobin(decimal, s);
}
int main()
{
int a, b;
printf("enter a number: ");
scanf(" %d", &a);
printf("enter the base: ");
scanf("%d", &b);
ndecTobin(a, b);
}
decimal and int b[s] not initialized.
By not initializing decimal to 0, it might have the value of 0 on a machine one day and quite different results otherwise.
void decTobin(int dec, int s) {
// while loop does not set all `b`,but following for loop uses all `b`
// int b[s], i = 0;
int b[s] = { 0 }; // or int b[s]; memset(b, 0, sizeof b);
int i = 0;
}
void ndecTobin(int dec, int s) {
int b[s], i = 0, a[s], decimal, decimalvalue = 0, g;
decimal = 0;
...
decimal += decimalvalue;
}
Minor points:
1) if (b[j] == NULL) b[j] = 0; is strange. NULL is best used as a pointer, yet code is comparing b[j], an int to a pointer. Further, since NULL typically has the arithmetic value of 0, code looks like if (b[j] == 0) b[j] = 0;.
2) decTobin() is challenging to follow. It certainly is only meant for non-negative dec and s. Candidate simplification:
void decTobin(unsigned number, unsigned width) {
int digit[width];
for (unsigned i = width; i-- > 0; ) {
digit[i] = number % 2;
number /= 2;
}
printf("%u ", number); // assume this is for debug
for (unsigned i = 0; i<width; i++) {
printf("%u", digit[i]);
}
}
It looks like you are just printing the number as a binary representation. If so this version would work.
void print_binary(size_t n) {
/* buffer large enough to hold number to print */
unsigned buf[CHAR_BIT * sizeof n] = {0};
unsigned i = 0;
/* handle special case user calls with n = 0 */
if(n == 0) {
puts("0");
return;
}
while(n) {
buf[i++] = n % 2;
n/= 2;
}
/* print buffer backwards for binary representation */
do {
printf("%u", buf[--i]);
} while(i != 0);
}
If you don't like the buffer, you can also do it using recursion like this:
void using_recursion(size_t n)
{
if (n > 1)
using_recursion(n/2);
printf("%u", n % 2);
}
Yet another way is to print evaluating most significant bits first. This however introduces issue of leading zeros which in code below are skipped.
void print_binary2(size_t n) {
/* do not print leading zeros */
int i = (sizeof(n) * 8)-1;
while(i >= 0) {
if((n >> i) & 1)
break;
--i;
}
for(; i >= 0; --i)
printf("%u", (n >> i) & 1);
}
Different OS/processor combinations may result in C compilers that store various kinds of numeric variables in different numbers of bytes. For instance, when I first learned C (Turbo C on a 80368, DOS 5) an int was two bytes, but now, with gcc on 64-bit Linux, my int is apparently four bytes. You need to include some way to account for the actual byte length of the variable type: unary operator sizeof(foo) (where foo is a type, in your case, int) returns an unsigned integer value you can use to ensure you do the right number of bit shifts.