SIGSEGV(signal 11) 'segmentation fault' in FCTRL2 codechef - c++

I am facing SIGSEGV error on submitting solution for codechef small factorial problem code FCTRL2 though the code works fine on ideone
coding language C++ 4.3.2
Example
Sample input:
4
1
2
5
3
Sample output:
1
2
120
6
#include <iostream>
using namespace std;
void fact(int n) {
int m = 1, a[200];
for (int j = 0; j < 200; j++) {
a[j] = 0;
}
a[0] = 1;
for (int i = 1; i <= n; i++) {
int temp = 0;
for (int j = 0; j < m; j++) {
a[j] = (a[j] * i) + temp;
temp = a[j] / 10;
a[j] %= 10;
if (temp > 0) {
m++;
}
}
}
if (a[m - 1] == 0) {
m -= 1;
}
for (int l = m - 1; l >= 0; l--) {
cout << a[l];
}
}
int main() {
int i;
cin >> i;
while (i--) {
int n;
cin >> n;
fact(n);
cout << endl;
}
return 0;
}

Caveat I'm not going to just fix up your code for you straight up, but I will highlight where it's going wrong and why you get the seg fault.
Your problem is with your implementation of how you're trying to handle the digit by digit multiplication - specifically with what happens to your m value. Test it out by outputting m each time it's incremented - you'll find it's incrementing more often than you intend. You're right to realise you need to use an approach to get to 158 digits and your basic concept could be made to work.
The first clue is by testing with n = 6 when you get a leading 0 that you shouldn't even though you try to get rid of that problem with the if block that contains m-=1
Try with n = 25 and you will see a lot of leading zeros.
Any value greater than this will fail with a Segmentation error. The Seg fault is because, with this error, you try to set values of the array a beyond the max index (as m gets greater than 200)
N.B. Your assertion that the code works on Ideone.com is only true up to a point - it will fail with n > 25.

(Erased code computing a factorial using int)
The problem in your code is that you increment m each time temp is not 0 for each digit multiplication. You may then get a SIGSEGV when computing big factorials because m becomes too big. You probably saw it because 0 shows up in front of your result. I guess this is why you added the
if (a[m - 1] == 0) {
m -= 1;
}
You should only increment m when the inside loop is finished and term is not null. Once fixed you can get rid of the above code.
void fact(int n) {
int m = 1, a[200];
for (int j = 0; j < 200; j++) {
a[j] = 0;
}
a[0] = 1;
for (int i = 1; i <= n; i++) {
int temp = 0;
for (int j = 0; j < m; j++) {
a[j] = (a[j] * i) + temp;
temp = a[j] / 10;
a[j] %= 10;
}
// if (temp > 0) {
// a[m++] = temp;
// }
while (temp > 0)
{
a[m++] = temp%10;
temp /= 10;
}
}
for (int l = m - 1; l >= 0; l--) {
cout << a[l];
}
}

Related

Leetcode 1588 sum of all ODD length subarrays. C++

I'm practicing myself by doing some leetcode questions, however, I don't know why that's an overflow problem right here. I knew the way I sum the subarray was terrible, any tips for the sum of the subarray?
and the run time for this code would be forever
#include <numeric>
class Solution {
public:
int sumOddLengthSubarrays(vector<int>& arr) {
int size = arr.size();//5
int ans = 0;
int sumAll = 0;
int start = 3;
int tempsum;
for(int i =0; i< size; i++){ //sumitself
sumAll += arr[i];
}
ans = sumAll; //alreayd have the 1 index
if(size%2 == 0){//even number 6
int temp = size-1; //5
if(size == 2)
ans = sumAll;
else{
while(start <= temp){//3 < 5
for(int i = 0; i< size; i++){
for(int k =0; k< start; k++){//3
tempsum += arr[i+k];
if(i+k > temp) //reach 5
break;
}
}
start+=2;
}
}
ans+= tempsum;
}
else{//odd number
if(size == 1)
ans = sumAll;
else{
while(start < size){//3
for(int i = 0; i< size; i++){
for(int k =0; k< start; k++){//3
tempsum += arr[i+k];
if(i+k > size) //reach 5
break;
}
}
start+=2;
}
ans+= tempsum;
ans+= sumAll; //size index
}
}
return ans;
}
};
The problem is with arr[i+k]. The result of i + k can be equal to, or larger, than size. You check it after you have already gone out of bounds.
You should probably modify the inner loop condition so that never happens:
for(int k =0; k < start && (i + k) < size; k++){//3
Now you don't even need the inner check.
You can use prefix sum array technique and then for each index you can calculate the sub-array sum for each odd-length array using prefix sum array. I submitted the below solution in LeetCode and it beats runtime of 100% of submissions and memory usage of 56.95%
class Solution {
public:
int sumOddLengthSubarrays(vector<int>& arr) {
int n = arr.size();
vector<int> prefix(n+1,0);
int sum = 0;
prefix[1] = arr[0];
for(int i=1;i<n;i++)
prefix[i+1]=(arr[i]+prefix[i]);
for(int i=0;i<n;i++)
{
for(int j=i;j<n;j+=2)
sum+=prefix[j+1]-prefix[i];
}
return sum;
}
};
https://leetcode.com/problems/sum-of-all-odd-length-subarrays/discuss/1263893/Java-100-one-pass-O(n)-with-explanation
class Solution {
public int sumOddLengthSubarrays(int[] arr) {
// alt solution: O(n)
//for each i:
// if(n -1 - i) is odd, then arr[i] is counted (n-1-i)/2 + 1 times, each from 0 to i, total ((n-i)/2+1)*(i+1) times
// if(n -1 - i) is even, then arr[i] is counted (n-1-i)/2 + 1 times, if starting subseq index diff with i is even;
// (n-1-i)/2 times, if starting index diff with i s odd, total (n-i)/2 *(i+1) + (i+1)/2
// if i is even i - 1, i - 3, .. 1, total (i -2)/2 + 1 = i / 2 = (i+1) / 2
// if i is odd i-1, i-3, .., 0 total (i-1)/2 + 1 = (i+1) / 2
int total = 0;
int n = arr.length;
for(int i = 0; i < n; i++)
total += (((n - 1 - i) / 2 + 1) * (i + 1) - ((n-i) % 2)*((i+1) / 2)) * arr[i];
return total;
}
}

why my c++ code to find factorials is not working?

#include <iostream>
using namespace std;
int main() {
int n, t;
cin >> n;
int i;
for(i = 0; i < n; i++){
cin >> t;
int arr[200];
arr[0] = 1;
int j;
for(j = 1; j < 200; j++) arr[j] = 0;
int l = 1, k;
for(j = 1; j <= t; j++){
int rem = 0, flag = 0;
for(k = 0; k < l; k++){
int temp = (arr[k]*j) ;
arr[k] = (temp + rem) % 10;
rem = (temp+rem) / 10;
if(k == l-1 && rem != 0){
arr[l] = rem;
flag = 1;
}
}
if(flag) l++;
}
while(l--){
cout << arr[l];
}
if(i != n-1){
cout << "\n";
}
}
return 0;
}
Question statement:
You are asked to calculate the factorials of some small positive integers.
Input:
An integer n, 1<=n<=100, denoting the number of testcases, followed by n lines, each containing a single integer t, 1<=t<=100.
Output:
For each integer n given at input, display a line with the value of t!
This is working fine for t < 35 but starts giving error for t >= 35.
Also tell me how can I improve my coding style. I am new to coding.
CASE 1
sample input:
2
1
35
actual output:
1
-40427027-3-786144929666651337523200000000
expected output:
1
10333147966386144929666651337523200000000
CASE 2
sample input:
3
5
6
7
actual output:
120
720
5040
expected output:
120
720
5040
PS Sorry!, Initial question changed as I ignored floating point errors while calculating 17! from scientific calculator. Now, code is not working for values greater than 34
Error was in part that rem can be a 3 digit number so diving by 10 doesn't work. Need to take care for rem > 100
That part of your code looks wrong since it cycles only up to length of your number
so it may grow only by one digit when there is flag:
for(k = 0; k < l; k++){
int temp = (arr[k]*j) ;
arr[k] = (temp + rem) % 10;
rem = (temp+rem) / 10;
if(k == l-1 && rem != 0){
arr[l] = rem;
flag = 1;
}
}
if(flag) l++;
It should be something shorter like:
for(k = 0; k < l; k++) {
rem += arr[k] * j;
arr[k] = rem % 10;
rem /= 10;
if(k == l-1 && rem != 0) ++l;
}

How to remove zeros before the number?

I have been working on this code for 3 days now and I can't figure out how to remove zeros before the output.
It is a program which calculates factorial of a number. Even if I use if statement as you can see which is commented it removes zeros after and between the numbers. I even tried to take size as the initial value for a but it just takes the global value, but not from the while loop, I even tried to store its value in another variable then also its not working.
#include <bits/stdc++.h>
#include <iostream>
using namespace std;
// Complete the extraLongFactorials function below.
void extraLongFactorials(int n) {
int arr[500] = {0};
int size = 1, i = 0, carry = 0, temp = 0;
arr[0] = 1;
for (int j = 1; j <= n; j++) {
for (int k = 0; k < 500; k++) {
temp = arr[k] * j + carry;
arr[k] = temp % 10;
carry = temp / 10;
}
while (carry) {
size++;
arr[size] = carry % 10;
carry %= 10;
}
}
for (int a = 499; a >= 0; a--) { // if(arr[a]!=0)
cout << arr[a];
}
}
int main() {
int n;
cin >> n;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
extraLongFactorials(n);
return 0;
}
Just skip the leading zeros by finding out the index of the first non-zero value:
i = 499;
// Skip leading zeros.
while (i > 0 && arr[i] == 0) {
--i;
}
while (i >= 0) {
cout << arr[i--];
}
Also, please don't #include <bits/stdc++.h>. This is a private, compiler specific header that you are not supposed to include.

memory issue in using partially initialized array(in 0/1 knapsack)

Given n items with size Ai and value Vi, and a backpack with size m. What's the maximum value can you put into the backpack?
Have you met this question in a real interview? Yes
Example
Given 4 items with size [2, 3, 5, 7] and value [1, 5, 2, 4], and a backpack with size 10. The maximum value is 9.
Note
You cannot divide item into small pieces and the total size of items you choose should smaller or equal to m.
int knapsack(int m, vector<int> A, vector<int> V) {
int dp[m + 1], tmp[m + 1];
for (int n = 1; n <= m; n++) {
//******the problem would disappear if i change n to start with 0
dp[n] = (n < A[0]) ? 0 : V[0] ;
tmp[n] = dp[n];
}
for (int i = 1; i < A.size(); i++) {
for (int n = 1; n <= m; n++) {
tmp[n] = dp[n];
}
for (int j = 1; j <= m; j++) {
if (j >= A[i]) {
dp[j] = max(tmp[j], (V[i] + tmp[j - A[i]]));
}
}
}
return dp[m];
}
I am failing the specific testcase and all other are fine(even larger m values)
m = 10, A = [2,3,5,7], V = [1,5,2,4]
Output: 563858905 (actually random every time) Expected: 9
I know this question is some what trivial but I'm really curious about the memory allocation process in this scenario
I'm guessing that it would be dangerous to use any array that is not initialized at the first memory location, can someone confirm with me?
I tried following code, a simpler version of yours;
#include <iostream>
using namespace std;
int knapsack(int m, int A[], int V[], int size) {
int dp[m+1], tmp[m+1];
for (int n = 1; n <= m; n++) { //*1*
dp[n] = (n < A[0]) ? 0 : V[0] ;
tmp[n] = dp[n];
}
for (int i = 1; i < 4; i++) { //*2*
for (int n = 1; n <= m; n++) { //*3*
tmp[n] = dp[n];
}
for (int j = 1; j <= m; j++) { //*4*
if (j >= A[i]) {
dp[j] = (tmp[j]> (V[i] + tmp[j - A[i]])? //*5*
tmp[j] :
(V[i] + tmp[j - A[i]])
);
}
}
}
cout << "answer:" << dp[m] << endl;
return dp[m];
}
int main(){
int a[] = {2,3,5,7};
int b[] = {1,5,2,4};
knapsack(10, a, b, 4);
return 0;
}
and got 8 as the answer, rather than a random number.
I'm not sure that my code is the correct version of yours, but I luckily noticed that the expression of V[i] + tmp[j-A[i]] at the line marked by "\\*5" accesses tmp[0] when j=2 and i=1, since A[1] == 2 and 2 >= A[1]. Thus it would not be safe without initialization of tmp[0] in this logic.
So, I guess you are right; the uninitialized value of tmp[0] may change the result value, (and in some cases the flow of the logic as well, at the conditional statement of line //*5.)

Sudoku solving matrix, while statement gives an infinite loop

This code should produce a solved sudoku matrix, however the while statement puts it in an infinite loop. Removing the while statement gives me a matrix with some values still 99 or 0. And i can't generate 9 random numbers uniquely one by one.
IF YOU WANT TO RUN AND CHECK THE CODE, REMOVE THE WHILE STATEMENT.
int a[9][9];
int b[9][9];
int inputvalue(int x, int y, int value) //checks horizontally, vertically and 3*3matrix for conflicts
{
int i, j;
for (i = 0; i < 9; i++)
{
if (value == a[x][i] || value == a[i][y])
return 0;
}
for (i = (x / 3) * 3; i <= ((x / 3) * 3) + 2; i++)
{
for (j = (y / 3) * 3; j <= ((y / 3) * 3) + 2; j++)
if (b[i][j] == value)
return 0;
}
return value;
}
int main()
{
int i, j, k;
unsigned int s;
cout << "sudoku\n";
time_t t;
s = (unsigned) time(&t);
srand(s);
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
a[i][j] = 99;
}
for (i = 0; i < 9; i++)
{
for (j = 1; j <= 9; j++)//j is basically the value being given to cells in the matrix while k assigns the column no.
while(a[i][k]==99||a[i][k]==0)
{
k = rand() % 9;
a[i][k] = inputvalue(i, k, j);
}
}
for (i = 0; i < 9; i++)
{
for (j = 0; j < 9; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
return 0;
getch();
}
You are using assignment =, instead of equality == here:
while(a[i][k]=99||a[i][k]=0)
^ ^
this should be:
while(a[i][k]==99||a[i][k]==0)
a[i][k]=99 will always evaluate to true since 99 is non-zero, although your original code does not compile for me under gcc as it is, so I suspect the code you are running either has some parenthesizes or is slightly different.
Also using k in the while loop before it is initialized is undefined behavior and it is unclear that your termination logic makes sense for a k that is constantly changing for each loop iteration.
Another source of the infinite loop is inputvalue which seems to get stuck returning 0 in some instances, so you need to tweak that a bit to prevent infinite loops.
Also, srand(time(NULL)); is a more common way to initialize the pseudo-random number generator