I am testing edge cases in my Fibonacci number program. It runs fine if the input value for first variable is 999999 or below. It crashes when the value is anything bigger. I am already using long int somewhere, really no clue what am I doing wrong.
#include <stdio.h>
#include <stdlib.h>
long ft(long num, int m) {
long arr[num];
int i;
int j = 0;
i = 3;
arr[0] = 0;
arr[1] = 1;
arr[2] = 1;
while (i <= num && j != 1) {
arr[i] = 0;
if ((arr[i - 1] + arr[i - 2]) < m) {
arr[i] = arr[i - 1] + arr[i - 2];
} else {
arr[i] = (arr[i - 1] + arr[i - 2]) % m;
}
if (arr[i] == 1 && arr[i - 1] == 1 && arr[i - 2] == 0)
j = 1;
i++;
}
if (i < num)
return arr[num % (i - 3)];
else
return arr[i - 1];
}
int main() {
long n = 0;
int m = 0;
scanf("%ld %d", &n, &m);
printf("%ld", ft(n, m));
return 0;
}
That's too much stack. Please allocate arr with malloc() and please check for allocation failures. Don't forget to free arr.
long *arr = malloc(sizeof(long) * (size_t)(num + 1));
if (!arr) return -1; // Error
//...
long r;
if (i < num) r= arr[num%(i-3)];
else r= arr[i-1];
free(arr);
return r;
Your program computes Fibonacci numbers modulo a given number.
The reason it crashes for values above 999999 is you allocate a variable length array of long with automatic storage (aka on the stack), that exceeds the available space in this segment (4 or 8 MB). Your program has undefined behavior and causes a stack overflow.
You should instead allocate this array from the heap with malloc or calloc and free it before leaving the function.
Note also these other problems:
arr should have a length of num + 1 because you store the result in arr[num].
the result is incorrect for num == 0 and for m == 1.
the function has undefined behavior for m == 0.
negative values of m and num should return an error result such as -1.
the test for cycle detection can be simplified.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
long ft(long num, int m) {
long *arr;
int i;
long res;
if (m < 0 || num < 0 || (arr = calloc(sizeof(*arr), num + 1)) == NULL)
return -1;
if (m == 1)
return 0;
arr[0] = 0;
arr[1] = 1;
arr[2] = 1;
res = arr[num];
for (i = 3; i <= num; i++) {
res = arr[i - 1] + arr[i - 2];
if (res >= m)
res -= m;
arr[i] = res;
if (res == 0 && arr[i - 1] == 1) { // handle cycle
res = arr[num % i];
break;
}
}
free(arr);
return res;
}
int main(int argc, char *argv[]) {
long n, n2;
int m = 0;
char *p;
if (argc > 1) { // command line arguments: start[..end] [mod]
n = n2 = strtol(argv[0], &p, 0);
if (*p == '.' && p[1] == '.')
n2 = strtol(p + 2, NULL, 0);
if (argc > 2)
m = strtol(argv[0], NULL, 0);
} else {
if (scanf("%ld %d", &n, &m) != 2)
return 1;
n2 = n;
}
while (n <= n2)
printf("%ld\n", ft(n++, m));
return 0;
}
Related
This is the task I have got:
I need to write a function (not recursive) which has two parameters.
An array of integers.
An integer representing the size of the array.
The function will move the duplicates to an end of the array.
And will give the size of the different digits.
Example:
5 , 2 , 4 , 5 , 6 , 7 , 2, n = 7
we will get back 5 , 2 , 4 , 6 , 7 , 5 , 2 and 5
We must keep the original sort as it is (which means like in example 5 must)
It does not matter how we sort the duplicates ones but just keep the sort for the original array as it is)
The function has to print the number of different digits (like in example 5)
The the input range of numbers in array [-n,n]
I can only use 1 additional array for help.
It has to be O(n)
I tried it so many times and feel like am missing something. Would appreciate any advice/suggestions.
int moveDup(int* arr, int n)
{
int* C = (int*)calloc(n * 2 + 1, sizeof(int));
assert(C);
/*int* count = C + n;*/
int *D = arr[0];
int value = 0, count = 0;
for (int i = 0; i < n; i++)
{
value = arr[i];
if (C[value + n] == 0)
{
*D = arr[i];
D++;
count++;
}
C[value + n] = C[value + n] + 1;
}
while (1 < C[value + n])
{
*D = i;
D++;
C[value + n]--;
}
free(C);
return count;
}
This algorithm will produce the required results in O(n) arithmetic complexity:
Input is an array A with n elements indexed from A0 to An−1 inclusive. For each Ai, −n ≤ Ai ≤ n.
Create an array C that can be indexed from C−n to C+n, inclusive. Initialize C to all zeros.
Define a pointer D. Initialize D to point to A0.
For 0 ≤ i < n:
If CAi=0, copy Ai to where D points and advance D one element.
Increment CAi.
Set r to the number of elements D has been advanced from A0.
For −n ≤ i ≤ +n:
While 1 < CAi:
Copy i to where D points and advance D one element.
Decrement CAi.
Release C.
Return r. A contains the required values.
A sample implementation is:
#include <stdio.h>
#include <stdlib.h>
#define NumberOf(a) (sizeof (a) / sizeof *(a))
int moveDuplicates(int Array[], int n)
{
int *memory = calloc(2*n+1, sizeof *Array);
if (!memory)
{
fprintf(stderr, "Error, unable to allocate memory.\n");
exit(EXIT_FAILURE);
}
int *count = memory + n;
int *destination = Array;
for (int i = 0; i < n; ++i)
// Count each element. If it is unique, move it to the front.
if (!count[Array[i]]++)
*destination++ = Array[i];
// Record how many unique elements were found.
int result = destination - Array;
// Append duplicates to back.
for (int i = -n; i <= n; ++i)
while (0 < --count[i])
*destination++ = i;
free(memory);
return result;
}
int main(void)
{
int Array[] = { 5, 2, 4, 5, 6, 7, 2 };
printf("There are %d different numbers.\n",
moveDuplicates(Array, NumberOf(Array)));
for (int i = 0; i < NumberOf(Array); ++i)
printf(" %d", Array[i]);
printf("\n");
}
here is the right answer, figured it out by myself.
int moveDup(int* arr, int n)
{
int* seen_before = (int*)calloc(n * 2 + 1, sizeof(int));
assert(seen_before);
int val = 0, count = 0, flag = 1;
int j = 0;
for (int i = 0; i < n; i++)
{
val = arr[i];
if (seen_before[arr[i] + n] == 0)
{
seen_before[arr[i] + n]++;
count++;
continue;
}
else if (flag)
{
j = i + 1;
flag = 0;
}
while (j < n)
{
if (seen_before[arr[j] + n] == 0)
{
count++;
seen_before[arr[j] + n]++;
swap(&arr[i], &arr[j]);
j++;
if (j == n)
{
free(seen_before);
return count;
}
break;
}
/*break;*/
j++;
if (j == n)
{
free(seen_before);
return count;
}
}
}
}
second right answer
int* mem = (int*)calloc(2 * n + 1, sizeof * arr);
assert(mem);
int* count = mem + n;
int* dest = arr;
for (i = 0; i < n; ++i)
{
if (count[arr[i]]++ == 0)
{
*dest = arr[i];
*dest++;
}
}
res = dest - arr;
for (i = -n; i <= n; ++i)
{
while (0 < --count[i])
{
*dest++ = i;
}
}
free(mem);
return res;
In line 10 I cannot find out where my problem is at first. I place int a[100][100]={0} but the cpu speed is stuck.
Then, I try to change it into a[n][n] but no output is shown.
Last, I try to change it again as if it resembles the original ones.
However, nothing works instead of a new question.
#include<stdio.h>
int main() {
int n;
while (scanf("%d", &n)) {
n *= 2;
int x = 0, y = 0, num = 1;
int a[n][n] = {0};
a[x][y] = num++;
while (n * n >= num) //定義陣列
{
while (y + 1 < n && !a[x][y + 1]) //向右
a[x][++y] = num++;
while (x + 1 < n && !a[x + 1][y]) //向下
a[++x][y] = num++;
while (y - 1 >= 0 && !a[x][y - 1]) //向左
a[x][--y] = num++;
while (x - 1 >= 0 && !a[x - 1][y]) //向上
a[--x][y] = num++;
}
for (x = 0; x < n; x++) //print 陣列
{
for (y = 0; y < n; y++) {
if (y != n - 1) {
printf("%d ", a[x][y]);
} else {
printf("%d", a[x][y]);
}
}
printf("\n");
}
break;
}
return 0;
}
At least this problem:
Variable Length Arrays (VLA) cannot be initialized via the C standard.
Alternate, assign via memset() after defining a.
// int a[n][n]={0};
int a[n][n];
memset(a, 0, sizeof a);
I really tried but still don't know what's wrong with my code.
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
int minus, i, judge;
for (minus = 0, judge = 1; judge == 1; minus++, n -= minus) {
for (i = 2; i * i < n; i++) {
if (n % i == 0)
judge = 1;
else judge = 0;
}
if (judge == 1)
continue;
else break;
}
printf("%d\n", n);
return 0;
}
When I input 143, the output is 143 not 139.
However, when I input 11, the output is the correct answer 11.
The loop test is incorrect: for (i = 2; i * i < n; i++)
If n is the square of a prime number, the loop will stop just before finding the factor.
You should either use i * i <= n or i <= n / i.
Furthermore, you do not enumerate all numbers as you decrement n by an increasing value at each iteration.
Note also that the loop would not find the closest prime to n, but the greatest prime smaller than n, which is not exactly the same thing.
Here is a modified version:
#include <limits.h>
#include <stdio.h>
int isPrime(int n) {
if (n <= 2 || n % 2 == 0)
return n == 2;
for (int i = 3; i <= n / i; i += 2) {
if (n % i == 0)
return 0;
}
return 1;
}
int main() {
int n;
if (scanf("%d", &n) != 1)
return 1;
if (n <= 2) {
printf("2\n");
} else {
for (i = 0;; i++) {
if (isPrime(n - i))
printf("%d\n", n - i);
break;
}
if (n <= INT_MAX - i && isPrime(n + i))
printf("%d\n", n + i);
break;
}
}
}
return 0;
}
We are asked to write some code that takes a 4 digit number as input, and does the following:
Take any four-digit number, using at least two different digits.
Arrange the digits in descending and then in ascending order to get two four-digit numbers
Subtract the smaller number from the bigger number.
Go back to step 2 and repeat.
The end result will always freeze at kaprekar's constant 1674 and we must print the algorithm's resulting number each and every time . In the end we also have to print the number of times we had to run the algorithm to get there .
I worked it out as loop , storing the digits in 2 arrays and sorting the first in ascending order and the second in descending order over and over again till i get to 1674 but for some reason the "process" loop won't stop . Any help would be appreciated .
#include <stdio.h>
#include <stdlib.h>
int main()
{
long int pow1(int x, int n)
{
int i, result = 1;
for (i = 0; i < n; i++)
{ // Power Function //
result *= x;
}
return (result);
}
int a, s;
int val[] = {
0,
0,
0,
0};
int value[] = {
0,
0,
0,
0};
int ex = 0;
scanf(" %d", &a);
if (a / 1000 != 0 && a / 1000 < 10)
{
// Extracting the digits and storing them in the arrays .
for (int i = 0; i <= 3; ++i)
{
value[i] = val[i] = (a % pow1(10, i + 1) - a % pow1(10, i)) / pow1(10, i);
if (i > 0)
{
if (val[i] == val[i - 1])
{
ex++;
}
}
}
if (ex == 3)
{
printf("Wrong input");
exit(0);
}
int j = 0, k = a;
// Start of process
while (k != 6174)
{
while (1)
{
s = 0;
for (int i = 0; i <= 3; i++)
{
if (val[i] > val[i + 1])
{
int temp = val[i];
val[i] = val[i + 1];
val[i + 1] = temp;
s = 1;
}
}
if (s == 0)
{
break;
}
}
while (1)
{
s = 0;
for (int i = 0; i <= 3; i++)
{
if (value[i] < value[i + 1])
{
int temp = value[i];
value[i] = value[i + 1];
value[i + 1] = temp;
s = 1;
}
}
if (s == 0)
{
break;
}
}
j++;
printf("max:%d min: %d ", value[0] * 1000 + value[1] * 100 + value[2] * 10 + value[3], val[0] * 1000 + val[1] * 100 + val[2] * 10 + val[3]);
k = value[0] * 1000 + value[1] * 100 + value[2] * 10 + value[3] - (val[0] * 1000 + val[1] * 100 + val[2] * 10 + val[3]);
printf("diff:%d\n", k);
for (int i = 0; i <= 3; ++i)
{
value[i] = val[i] = (k % pow1(10, i + 1) - k % pow1(10, i)) / pow1(10, i);
}
}
printf("Took %d turns", j);
}
else
{
printf("Wrong input");
}
return 0;
}
You have defined val and value as 4 element [0..3], yet in your loops you access and modify both over [0..4] eg: val[i+1] = temp.
I proper sized them (int val[5] = {0}, value[5] = {0}), and your test yielded:
max:2211 min: 112 diff:2099
max:9920 min: 229 diff:9691
max:9961 min: 1699 diff:8262
max:8622 min: 2268 diff:6354
max:6543 min: 3456 diff:3087
max:8730 min: 378 diff:8352
max:8532 min: 2358 diff:6174
Took 7 turns
Because your sort isn't quite right.
If you change your sort to be:
for (int i = 1; i < 4; i++)
{
if (val[i-1] > val[i])
{
int temp = val[i];
val[i] = val[i - 1];
val[i - 1] = temp;
s = 1;
}
}
it will respect its boundaries, and be correct; so you can go back to len 4 vectors. Remember to change the other one as well.
ps: It is more work for me to complain that you didn't put a main wrapper in your example than to put one in. That doesn't excuse not doing the least you can do.
The following program print the number of time to reach to Kaprekars
Constant
I don't understand why it runs on infinite loop when I use normal array
while it works when I use dynamic array as I wrote in comments.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define size 4
void KaprekarsConstant(int num) {
//int *arr;
int j, i, temp, sorted, counter = 0, rev;
while (num != 6174) {
int arr[3] = { 0 };
//arr = (int*)calloc((size - 1), sizeof(int));
for (i = 0; num != 0; i++) {
arr[i] = num % 10;
num /= 10;
}
for (i = 1; i < size; i++) {
for (j = i - 1, temp = arr[i]; (temp < arr[j]) && (j >= 0); j--) {
arr[j + 1] = arr[j];
}
arr[j + 1] = temp;
j++;
}
for (i = 0, sorted = 0; i < size; i++) {
sorted = arr[i] + (sorted * 10);
}
for (i = size - 1, rev = 0; i >= 0; i--) {
rev = arr[i] + (rev * 10);
}
num = abs(rev - sorted);
counter++;
}
//free(arr);
printf("%d\n", counter);
}
int main(void) {
KaprekarsConstant(2111); //print 5
return 0;
}
You code has undefined behavior in both cases because you access and modify arr beyond its boundaries: arr is defined or allocated with a size of 3 but you access and modify arr[3] which is the fourth element.
It is highly error prone to redefine the identifier size as a macro. You should at least use SIZE or NUMBER_SIZE.