Collatz sequence algorithm not working right - c++

For some reason, this always returns value 1. The point of this is to find the starting number (1-1,000,000) that loops the most amount of times (until j = 1). j will always end up being 1 eventually (collatz theory), I divide j by 2 if it's even, or multiple by 3 and add 1 if it's odd.
#include <iostream>
using namespace std;
int collatz() {
int counter = 0;
int holder = 0;
for (int i = 999999; i > 1; i--){ // loops 999,999 times
for (int j = i; j != 1; counter++) { // loops until j = 1, records amount of loops
if (j % 2 == 0) { // if j is even, divide by 2, +1 to counter
j = j / 2;
} else {
j = (j*3) + 1; // if j is odd, multiply by 3 and add 1, +1 to counter
}
}
if (holder < counter){ // records highest number of loops
holder = counter;
counter = 0;
} else {
counter = 0;
}
}
return holder;
}
int main()
{
cout << collatz << endl;
return 0;
}

You're not calling your function, you're printing out the function pointer (which is converted to the bool value true (i.e. 1)).

First, use unsigned int or unsigned long long as the variable type of j to increase the arithmetic range.
Then, in the loop, check for overflow.
while (j!=1) {
counter++;
if (j % 2 == 0) {
j >>= 1;
} else {
unsigned int j2 = j;
j = (j*3) + 1;
if (j2 > j) {
return -1; // or surround this with try/catch/throw exception
}
}
}
With int i; the counter will overflow at i==113383;
and with unsigned int i; at 159487. If these are not checked, there's a possibility of infinite loop.

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;
}
}

Sequence and Biggest,Smallest with vector

The question says that show the highest and lowest number of that sequence and the number of times that they appear. I now i need to show how many numbers this sequence appears,also they need to be lesser than 2000:
#include <iostream>
int main()
{
int v[11], i, b, l;
for (i = 0; i < 11; i++) {
scanf("%d", &v[i]);
}
b = v[0];
for (i = 0; i < 11; i++) {
if (v[i] > b)
b = v[i];
i++;
}
l = v[0];
for (i = 0; i < 11; i++) {
if (v[i] < l)
l = v[i];
i++;
}
printf("%d\n", b);
printf("%d\n", l);
return 0;
}
And see the input and output how should they appear
Input:
20
40
39
120
2
200
2
360
780
7
2
Output:
biggest:780 Shows 1 time(s)
lowest:2 Shows 3 time(s)
Here is the code for the maximum integer. Use similar method for the minimum integer.
#include <iostream>
int main()
{
int v[11]; // gets the input array
for (i = 0; i < 11; i++) {
scanf("%d", &v[i]);
}
int max = 0;
int count = 0;
for (int i = 0; i < 11; i++)
{
if (v[i] > max)
{
max = v[i];
count = 1;
} else if (v[i] == max)
{
count++;
}
}
}
Explanation
The first for loop gets the input from the user. I haven't changed this part of the code.
The second for loop is where the magic happens. First, we define a maximum variable and a count variable. Both variables are set to zero.
As the for loop iterates through the array, we do some if-statements. First, we check whether the current element is greater than our maximum variable. If this is true, we have found a new maximum variable, so we set max = the current element. We also change the value of count to one, because we have found only one instance so far of the new maximum.
We also check if the current element is equal to the maximum. In this case, we have found another instance of the maximum element so we increment count by 1.
These are the only two cases we have to check. It is simple to apply similar logic for the minimum element.
So here's what i did but still doesn't work what could it be:
#include <iostream>
int main()
{
int v[11],i; // gets the input array
for (i = 0; i < 11; i++) {
scanf("%d", &v[i]);
}
int max = 0;
int count = 0;
for (int i = 0; i < 11; i++)
{
if (v[i] > max)
{
max = v[i];
count = 1;
} else if (v[i] == max)
{
count++;
}
}
int min = 0;
for (int i = 0; i < 11; i++)
{
if (v[i] < min)
{
min = v[i];
count = 1;
} else if (v[i] == min)
{
count++;
}
}
printf("%d\n", max);
printf("%d\n", min);
}

prime seive algorithm giving a runtime error

I am trying to implement the Sieve of Eratosthenes algorithm but it giving a runtime error.
didn't get any output though. after providing the input,
#include<iostream>
using namespace std;
//Sieve Approach - Generate an array containing prime Numbers
void prime_sieve(int *p) {
//first mark all odd number's prime
for (int i = 3; i <= 10000; i += 2) {
p[i] = 1;
}
// Sieve
for (long long int i = 3; i <= 10000; i += 2) {
//if the current number is not marked (it is prime)
if (p[i] == 1) {
//mark all the multiples of i as not prime
for (long long int j = i * i; j <= 10000; j = j + i ) {
p[j] = 0;
}
}
}
//special case
p[2] = 1;
p[1] = p[0] = 0;
}
int main() {
int n;
cin >> n;
int p[10000] = {0};
prime_sieve(p);
//lets print primes upto range n
for (int i = 0; i <= n; i++) {
if (p[i] == 1) {
cout << i << " ";
}
}
return 0;
}
compiler didn't throwing any error also it is not providing the output also
program freezes for some seconds and then terminates
As mentioned in the comments, you are going out of bound.
There is also some confusion about the meaning of p[].
In addition, you are not using the value of n in the function, which leads to unnecessary calculations.
Here is a tested programme (up to n = 10000):
#include <iostream>
#include <vector>
#include <cmath>
//Sieve Approach - Generate an array containing prime Numbers less than n
void prime_sieve(std::vector<int> &p, long long int n) {
//first mark all odd number's prime
for (long long int i = 4; i <= n; i += 2) {
p[i] = 0;
}
// Sieve
for (long long int i = 3; i <= sqrt(n); i += 2) {
//if the current number is not marked (it is prime)
if (p[i] == 1) {
//mark all the multiples of i as not prime
for (long long int j = i * i; j <= n; j = j + i ) {
p[j] = 0;
}
}
}
//special cases
p[1] = p[0] = 0;
}
int main() {
long long int n;
std::cout << "Enter n: ";
std::cin >> n;
std::vector<int> p (n+1, 1);
prime_sieve(p, n);
//lets print primes upto range n
for (long long int i = 0; i <= n; i++) {
if (p[i] == 1) {
std::cout << i << " ";
}
}
return 0;
}

figure out Uneaten Leaves algorithm bug

I faced this problem in an interview challenge
K caterpillars are eating their way through N leaves, each caterpillar
falls from leaf to leaf in a unique sequence, all caterpillars start
at a twig at position 0 and falls onto the leaves at position between
1 and N. Each caterpillar j has an associated jump number Aj. A
caterpillar with jump number j eats leaves at positions that are
multiple of j. It will proceed in the order j, 2j, 3j…. till it
reaches the end of the leaves and it stops and build its cocoon. Given
a set A of K elements , we need to determine the number
of uneaten leaves.
Constraints:
1 <= N <= 109
1 <= K <= 15
1 <= A[i] <= 109
Input format:
N = No of uneaten leaves.
K = No. of caterpillars.
A = Array of integer.
jump numbers Output:
The integer nu. Of uneaten leaves
Sample Input:
10
3
2
4
5
Output:
4
Explanation:
[2, 4, 5] is the 3-member set of jump numbers. All leaves which are multiple of 2, 4, and 5 are eaten. Only 4 leaves which are numbered 1,3,7,9 are left.
the naive approach for solving this question is have a Boolean array of all N numbers, and iterate over every caterpillar and remember the eaten leaves by it.
int uneatenusingNaive(int N, vector<int> A)
{
int eaten = 0;
vector<bool>seen(N+1, false);
for (int i = 0; i < A.size(); i++)
{
long Ai = A[i];
long j = A[i];
while (j <= N && j>0)
{
if (!seen[j])
{
seen[j] = true;
eaten++;
}
j += Ai;
}
}
return N - eaten;
}
this approach passed 8 out of 10 test cases and give wrong answer for 2 cases.
another approach using Inclusion Exclusion principle, explanation for it can be found here and here
below is my code for the second approach
int gcd(int a, int b)
{
if (b == 0)
return a;
return gcd(b, a%b);
}
int lcm(int i, int j)
{
return i*j / gcd(i, j);
}
vector<vector<int>> mixStr(vector<vector<int>> & mix, vector<int>& A, unordered_map<int, int> & maxStart)
{
vector<vector<int>> res;
if (mix.size() == 0)
{
for (int i = 0; i < A.size(); i++)
{
vector<int> tmp;
tmp.push_back(A[i]);
res.push_back(tmp);
}
return res;
}
for (int i = 0; i<mix.size(); i++)
{
int currSlotSize = mix[i].size();
int currSlotMax = mix[i][currSlotSize - 1];
for (int j = maxStart[currSlotMax]; j < A.size(); j++)
{
vector<int> tmp(mix[i]);
tmp.push_back(A[j]);
res.push_back(tmp);
}
}
return res;
}
int uneatenLeavs(int N, int k, vector<int> A)
{
int i = 0;
vector<vector<int>> mix;
bool sign = true;
int res = N;
sort(A.begin(), A.end());
unordered_map<int,int> maxStart;
for (int i = 0; i < A.size(); i++)
{
maxStart[A[i]] = i + 1;
}
int eaten = 0;
while (mix.size() != 1)
{
mix = mixStr(mix, A, maxStart);
for (int j = 0; j < mix.size(); j++)
{
int _lcm = mix[j][0];
for (int s = 1; s < mix[j].size(); s++)
{
_lcm = lcm(mix[j][s], _lcm);
}
if (sign)
{
res -= N / _lcm;
}
else
{
res += N / _lcm;
}
}
sign = !sign;
i++;
}
return res;
}
this approach passed only one 1/10 test case. and for the rest of test cases time limit exceeded and wrong answer.
Question:
What am I missing in first or second approach to be 100% correct.
Using Inclusion-Exclusion theorem is correct approach, however, your implementation seems to be too slow. We can use bitmasking technique to obtain a O(K*2^K) time complexity.
Take a look at this:
long result = 0;
for(int i = 1; i < 1 << K; i++){
long lcm = 1;
for(int j = 0; j < K; j++)
if(((1<<j) & i) != 0) //if bit j is set, compute new LCM after including A[j]
lcm *= A[j]/gcd(lcm, A[j]);
if(number of bit set in i is odd)
result += N/lcm;
else
result -= N/lcm;
}
For your first approach, an O(N*K) time complexity algorithm, with N = 10^9 and K = 15, it will be too slow, and can cause memory limit exceed/time limit exceed.
Notice that lcm can be larger than N, so, additional check is needed.

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