can anyone pinpoint the error in my recursive function? - c++

this function prints all triplets in an array whose product is a number k
input first line number of elements, second array elements, third target product .. passes parameters to recursive function f along with a vector that stores elements whose product might give k
thought process -> for each element we can include or exclude it to get the product k. If p > 24 or number elements multiplied > 3 we backtrack. once the prod = k, we print all numbers from vector v and pop them out and set number of elements count to 0 and product to 1 and continue
for an input of:
9
1 2 3 12 4 7 5 24 9
24
my output looks something like this :
12
2
1
9
9
9
| ->cursor justs stops here ..no further outputs...
naming scheme used :
count -> number of elements multiplied till now whose product is stored in -> p
n-> number of elements in array
k -> target pdt
i -> index of element in array currently at
code :
#include <iostream>
#include <vector>
using namespace std;
// all triplets whose product is a number k
void f(int i, int count, int p, int k, vector<int>&v, int *a, int n)
{
// success condition
if(count == 3 && p == k)
{
for(int i = 2; i >= 0; --i)
{
cout << v[i] << " " << endl;
v.pop_back();
}
p = 1;
count = 0;
}
if(count>=3 || i > n - 1 || p > k)
{
return;
}
v.push_back(a[i]);
f(i + 1, count + 1, p * a[i], k, v, a, n);
v.pop_back();
f(i + 1, count, p, k, v, a, n);
}
int main()
{
int n;
cin >> n;
int *a=new int[n];
for(int i = 0; i < n; ++i)
{
cin >> a[i];
}
int k;
cin >> k;
//int p = 1;
vector<int>v;
f(0, 0, 1, k, v, a, n);
delete[] a;
return 0;
}

Your “reset” of p and count on success is immediately strange: why does the function need to keep looking when its caller will already try the other possibilities? But that’s just a distraction from the real issue: the balanced push_back and pop_back around the first recursive call establish and rely on an invariant where every call leaves v the same length as when it started. But the success path clears the vector and leaves it shorter, so eventually you pop_back when it’s empty and—
The joys of undefined behavior (which happened to give an infinite loop here) aside, the fix is trivial: just return after printing without modifying v at all. (Then you may find some further simplifications.)

Related

How to solve this?

I'm doing an assignment which command me to count the numbers of future numbers in q elements given. A future number is a number which has all the divisors of it (1 and itself are not include) that are prime numbers. It doesn't print anything at all. Anyone have a suggestion why isn't it working ?!!
Sample input :
9
9 7 10 6 17 4 19 21 13
Sample output :
5
my code :
#include<bits/stdc++.h>
using std::cin;
using std::cout;
int i,j,count1=0,count_divisors;
int a[10005];
int prime_numbers(int n) {
if(n<2) return 0;
if(n==2||n==3) return 1;
for(i=2;i<=sqrt(n);i++)
if(n%i==0) return 0;
return 1;
}
int main() {
int q;
cin>>q;
for(i=0;i<q;i++) cin>>a[i];
for(i=0;i<q;i++) {
count_divisors=0;
for(j=2;j<=sqrt(a[i]);j++) {
if(!(a[i]%j)) {
int the=a[i]/j;
if(prime_numbers(j)==0) break;
if(prime_numbers(the)==0) break;
count_divisors+=2;
}
if(j>sqrt(a[i])&&count_divisors!=0) count1++;
}
}
cout<<count1;
}
I think the assignment is to find all numbers in an array that
a) have at least one divisor (other than 1 or the number itself) and
b) all those divisors are prime numbers.
Some examples:
9 => devisor(s): [3]; 3 is a prime number, so "9" counts.
7 => devisor(s): [none]; so "7" does NOT count.
20 => devisor(s): [2, 5, 10]; 10 is a divisor but not a prime number, so "20" does NOT count.
In the given example 5 of the numbers fulfill the criteria, namely 9, 10, 6, 4 and 21. That's 5 numbers, therefore the answer is "5".
Here is the code that does that for you:
#include <iostream>
bool is_prime_numbers(int n) {
if (n < 2) {
return false;
}
for (int i = 2; i < n; i++)
{
if (n % i == 0) {
return false;
}
}
return true;
}
int main() {
int cnt = 0;
int arr[1000];
int q;
cin >> q;
//q = 9;
for (int i = 0; i < q; i++)
cin >> arr[i];
/*arr[0] = 9;
arr[1] = 7;
arr[2] = 10;
arr[3] = 6;
arr[4] = 17;
arr[5] = 4;
arr[6] = 19;
arr[7] = 21;
arr[8] = 20;*/
for (int i = 0; i < q; i++) {
bool found_divisor_prime = false;
bool found_divisor_other = false;
int val = arr[i];
for (int div = 2; div < val; div++) {
//can "val" be devided by "div"?
if ((val % div) == 0) {
//is "div" a prime number?
if (is_prime_numbers(div))
found_divisor_prime = true;
else
found_divisor_other = true;
}
}
/* we only want to count numbers that:
* a) have a divisor other than 1 or the number itself
* b) all divisors are prime numbers
*/
if (found_divisor_prime && !found_divisor_other)
cnt++;
}
std::cout << cnt;
return 0;
}
The first bug is as AudioDroid stated that the global variable i is being changed by two functions, namely main and prime_numbers. This can be fixed by defining a local variable let's say k and looping through with it:
int k;
for (k = 2; k <= sqrt(n); k++) {
if (n % k == 0) return 0;
}
The second bug is that you wrote
if (j > sqrt(a[i]) && count_divisors != 0) count1++;
inside the inner for loop body and thus it will never be executed. It has to be taken out of there. Fix these two bugs and you will get your 5 as an answer.
However in case you have q as big as let's say 10^6 or more this solution of yours will not be very effective because for every divisor d you are looping through the range [2; sqrt(d)] instead of generating all prime numbers up to a given limit in a lookup object and just checking whether the particular divisor is a prime number or not in O(1) time.
#include <memory>
#include <bitset>
#include <iostream>
#include <vector>
int const lim = 1000000;
bool is_future(int const num, std::unique_ptr<std::bitset<lim + 1>> const& is_prime) {
int div, cnt = 0;
for (div = 2; div * div <= num; ++div) {
if (num % div == 0) {
++cnt;
if (!is_prime->test(div)) {
return false;
}
if (div * div != num) {
++cnt;
if (!is_prime->test(num / div)) {
return false;
}
}
}
}
return cnt != 0;
}
int main() {
auto sieve = std::make_unique<std::bitset<lim + 1>>();
sieve->set();
sieve->set(0, false);
sieve->set(1, false);
int i, j;
for (i = 2; i * i <= lim; ++i) {
if (sieve->test(i)) {
for (j = i * i; j <= lim; j += i) {
sieve->set(j, false);
}
}
}
int q;
std::cin >> q;
std::vector<int> seq;
seq.reserve(q);
int k, num;
for (k = 0; k != q; ++k) {
std::cin >> num;
seq.emplace_back(num);
}
int ans = 0;
for (auto const& elem : seq) {
if (is_future(elem, sieve)) {
++ans;
}
}
std::cout << ans << '\n';
return 0;
}
Set your lim constant to be high enough according to the maximum value of the number in the input. Allocate bitset on the heap via the unique_ptr sieve. Run the sieve of Eratosthenes algorithm on sieve up to lim. Read q. Define the vector seq. Use reserve to allocate memory for q elements and thus avoid preallocation. Grow seq. Initialize the counter ans with 0. Loop through seq and for every element elem call is_future with elem and sieve. is_future uses is_prime (sieve) as a lookup object to check whether the divisor div or (num/div) is prime or not in O(1) time. The counter cnt counts the number of divisors of num in the range [2; sqrt(num)]. Pay attention that I don't use std::sqrt because it is expensive If called thousands of times. If cnt is 0 the number has no divisors in the specified range so it is not future otherwise it is. If is_future returns true increment ans. Output ans.
#Trương Quang Vinh
seq.reserve(q);
Imagine you have a vector seq that is empty. Its initial capacity is 0 which means that it has allocated a block of memory for 0 integers. If you start growing this vector let's say you want to read 10^6 integers and store them in it it has to do the following operations:
allocate a larger block of memory
copy the integers from the old block to the new one
call the destructors of the integers located on the old block
free the memory that the integers located on the old block used and return it back to the system
I made a test with 10^6 integers and under Microsoft's implementation the capacity of the vector seq changes this way:
0 -> 1 -> 2 -> 3 -> 4 -> 6 -> 9 -> 13 -> 19 -> 28 -> 42 -> 63 -> 94 -> 141 -> 211 -> 316 -> 474 -> 711 -> 1066 -> 1599 -> 2398 -> 3597 -> 5395 -> 8092 -> 12138 -> 18207 -> 27310 -> 40965 -> 61447 -> 92170 -> 138255 -> 207382 -> 311073 -> 466609 -> 699913 -> 1049869
At each of these steps where the vector seq changes its capacity the above-mentioned 4 operations will take place which of course take some time. In your case you know that you are going to store q integers in your vector and with the member function reserve you can directly allocate a block of memory that is large enough to keep them and thus avoid the above-mentioned 4 operations.
seq.emplace_back(num);
The member function emplace_back directly constructs an element from the arguments it is given instead of constructing an element from the copy created from the arguments it is given like push_back does and thus is more effective.
is_prime->test(num / div)
is_prime is an unique_ptr that points to an object of type std::bitset<lim + 1> located on the heap. The bitset class mimics the bits of a number. In your case you are going to run the sieve of Eratosthenes algorithm on this object. Let's say you want to generate all the prime numbers in the range [2; 100]. Your bitset object will initially look like that:
11111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111100
The last two bits representing the numbers 0 and 1 are set to 0 because 0 and 1 are not prime numbers. When the algorithm finishes your bitset object will look like that:
00010000000100000100010000010100010000010100000100000100010100010000010100000100010100010100010101100
The function test called via the pointer is_prime with operator-> which is the short form of (*is_prime).test will test whether the bit let's say x is 1 or 0. If it is 1 the number represented by the bit x is prime otherwise it is not.
std::unique_ptr<std::bitset<lim + 1>> const& is_prime
This is the object sieve passed as a reference to const to the function is_future which means that operations done on is_prime are done on sieve with the promise of not changing it because is_prime is a reference to const. If I don't write auto on this line
auto sieve = std::make_unique<std::bitset<lim + 1>>();
I have to write 
std::unique_ptr<std::bitset<lim + 1>> sieve = std::make_unique<std::bitset<lim + 1>>();
which is where the type unique_ptr missing from main is coming from.

Minimum number of jumps to reach end of the array with sequence using recursion

I have a code for "Minimum number of jumps to reach end of the array with its sequence using recursion". But I am not able to print the sequence. ( There is nothing in vector vec to print )
Any help will be appreciated.
Explanation :
I want to reach from 1st element ( i.e. 2) to
last element ( i.e. 4) of the array in minimum Jump.
How Jump will be :
1st element is 2. It means I can make upto 2 jumps in array. If I take 1st jump then I can reach 2nd element ( i.e. 3) or if I take
2nd jump then I can reach 3rd element (i.e. 1)
2nd element is 3 ,so I can make maximum 3 jumps. In 1st jump I can reach to 1 , in 2nd jump I can reach to 0 and in 3rd jump I can
reach to 4
In this way I want to reach from 1st element to last element of the array in minimum number of jumps.
So output will be like , from 1st element 2, I will jump to 3. Then from 3 I will jump to 4 (last element). So 2 Jumps. ( 2 - 3 - 4 )
#include<iostream>
#include<vector>
#include<climits>
using namespace std;
int jump(int arr[], int n, int start, vector<int> &vec)
{
if(start == n-1) // if start is the last element in array
return 0;
if( arr[start] == 0) // if array element is 0
return 0;
vector<int> vec1 = vec;
vector<int> vec2 = vec;
int minimum = INT_MAX;
for( int i = 1 ; i <= arr[start]; i++ )
{
vec1.push_back(start);
int _jump = 1 + jump( arr, n, start+i, vec1); // considering every jump
vec = (_jump < minimum) ? vec1 : vec2;
minimum = min(minimum, _jump);
}
return minimum;
}
int main()
{
int arr[] = { 2, 3, 1, 0, 4 };
int n = sizeof(arr) / sizeof(arr[0]);
vector<int> vec;
cout << "Number of jumps " << jump(arr, n, 0, vec) << endl;
cout<<"Sequence is "<<endl;
for( auto x : vec)
cout << x <<" ";
return 0;
}
output
Number of jumps 2
Sequence is
Expected output
Number of jumps 2
Sequence is 2 3 4
Here is an example that will set a vector where each index stores the correct next step in the sequence after visiting that index. I leave it to you to code following the sequence from the first element to the end, using the result vector. I also corrected this condition if( arr[start] == 0) to return "infinity" since if we visit this element, we cannot complete the sequence.
#include<iostream>
#include<vector>
#include<climits>
using namespace std;
int jump(int arr[], int n, int start, vector<int> &vec)
{
if(start == n-1) // if start is the last element in array
return 0;
if( arr[start] == 0) // if array element is 0
return INT_MAX - n;
int minimum = INT_MAX;
int step;
for( int i = 1 ; i <= arr[start]; i++ )
{
int _jump = 1 + jump( arr, n, start+i, vec); // considering every jump
if (_jump < minimum){
minimum = _jump;
step = start + i;
}
}
vec.at(start) = step;
return minimum;
}
int main()
{
int arr[] = { 2, 3, 1, 0, 4 };
int n = sizeof(arr) / sizeof(arr[0]);
vector<int> vec(n, -1);
cout << "Number of jumps " << jump(arr, n, 0, vec) << endl;
cout<<"Vector: "<<endl;
for( auto x : vec)
cout << x <<" ";
return 0;
}
Essentially, this is the minimal fix so that the sample data would works. I have not check all edge cases. For example, one might want to print something else than the value of INT_MAX is the end is not reachable.
Problem 1
You want to output values (i.e. 2, 3, 4 in your example) and not index (0, 1, 4). Thus you must push values instead of indexes.
vec1.push_back(arr[start]);
Problem 2
if(start == n-1) // if start is the last element in array
return 0;
This will not add the final value when the end is reached. You must add last value with:
vec.push_back(arr[start]);
Problem 3
if( arr[start] == 0) // if array element is 0
return 0;
A sequence that does not reach the end, would be considered to be very good. You should return a large value. Since _jump is 1 + return value of jump, the return value should be INT_MAX - 1 and minimum should also be initialized to that value for same reason.
Alternatively, you could return other values like n too instead.
Problem 4
Finally, the following condition is incorrect:
vec = (_jump < minimum) ? vec1 : vec2;
When the condition is not verified, it is vect2 that need to be copied in vec1 since the loop uses vect1.

how to fix this programme

Given an array A, find the highest unique element in array A. Unique element means that element should present only once in the array.
Input:
First line of input contains N, size of array A. Next line contains N
space separated elements of array A.
Output:
Print highest unique number of array A. If there is no any such
element present in array then print -1.
Constraints:
1 ≤ N ≤ 106 0 ≤ Ai ≤ 109
SAMPLE INPUT
5 9 8 8 9 5
SAMPLE OUTPUT
5
Explanation
In array A: 9 occur two times. 8 occur two times. 5 occur once hence the answer is 5.
Can you explain what is wrong with this code?
#include <iostream>
using namespace std;
int main() {
int n;
cin >> n;
int a[n], i, max = -99;
for (i = 0; i < n; i++) {
cin >> a[i];
}
for (i = 0; i < n; i++) {
if (a[i] > max) {
max = a[i];
cout << max;
}
}
for (i = 0; i < n; i++) {
if (max == a[i]) {
break;
} else {
// cout<<"-1";
}
max =
}
return 0;
}
There's a few problems here (right now it won't even compile at max =). But the algorithmic problem is this: the second for loop finds the maximum before rejecting duplicate entries. The reverse is needed. First reject duplicates (say, by setting them to -99), then find the max of what is left over.

How to find size of largest subset of a sub-sequence equal to a sum

I have this problem from hackerearth
Given an array of N integers, C cards and S sum. Each card can be used
either to increment or decrement an integer in the given array by 1.
Find if there is any subset (after/before using any no.of cards) with
sum S in the given array.
Input Format
First line of input contains an integer T which denotes the no. of
testcases. Each test case has 2 lines of input. First line of each
test case has three integers N(size of the array), S(subset sum) and
C(no. of cards). Second line of each test case has N integers of the
array(a1 to aN) seperated by a space.
Constraints
1<=T<=100 1<=N<=100 1<=S<=10000 0<=C<=100 1<=ai<=100
Output Format
Print TRUE if there exists a subset with given sum else print FALSE.
So this is basically a variation of the subset sum problem, but instead of finding out whether a given subset with a sum S exists, we need to find the largest subset from sequence index to N-1 that has a value of s and compare it's length with our C value to see if it is greater. If it is, then we have enough elements to modify the sum using our C cards, and then we print out our answer. Here is my code for that
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int N, S, C;
int checkSum(int index, int s, vector<int>& a, vector< vector<int> >& dP) {
if (dP[index][s] != -1)
return dP[index][s];
int maxNums = 0; // size of maximum subset array
for (int i = index; i < N; i++) {
int newSum = s - a[i];
int l = 0;
if (newSum == 0) {
l = 1;
} if (newSum > 0) {
if (i < (N-1)) { // only if we can still fill up sum
l = checkSum(i + 1, newSum, a, dP);
if (l > 0) // if it is possible to create this sum
l++; // include l in it
} else {
// l stays at 0 for there is no subset that can create this sum
}
} else {
// there is no way to create this sum, including this number, so skip it;
if (i == (N-1))
break; // don't go to the next level
// and l stays at 0
}
if (l > maxNums) {
maxNums = l;
}
}
dP[index][s] = maxNums;
return maxNums;
}
int main() {
int t;
cin >> t;
while (t--) {
cin >> N >> S >> C;
vector<int> a(N);
for (int i = 0; i < N; i++)
cin >> a[i];
vector< vector<int> > dP(N, vector<int>(S + C + 2, -1));
bool possible = false;
for (int i = 0; i <= C; i++) {
int l = checkSum(0, S-i, a, dP);
int m = checkSum(0, S+i, a, dP);
if ( (l > 0 && l >= i) || (m > 0 && m >= i) ) {
cout << "TRUE" << endl;
possible = true;
break;
}
}
if (!possible)
cout << "FALSE" << endl;
}
return 0;
}
So basically, 0 means it's not possible to create a subset equal to s from elements index to N-1, and -1 means we haven't computed it yet. And any other value indicates the size of the largest subset that sums up to s. This code isn't passing all the test cases. What's wrong?
You miss an else in following line
} if (newSum > 0) {
This make your program has an unexpected early break before updating maxNums by l in some cases.
For example, N=1, S=5, C=0, a={5}
Potential logic problem
You have limited the no. of card to be used to not exceed the subset size while the question never state you cannot apply multiple cards to same integers.
I mean l >= i and m >= i in
if ( (l > 0 && l >= i) || (m > 0 && m >= i) ) {
Seems you have logic flaw.
You need to find the shortest subset (with sum in range S-C..S+C) and compare it's size with C. If subset is shorter, it is possible to make needed sum.

Remove repeated elements and give a Range Sum

I have a question regarding already asked this question:
SPOJ DQUERY : TLE Even With BIT?
What if I would like to not consider the repeated element to count when I make a range query?
following is an example:
Input
Line 1: n (1 ≤ n ≤ 10^6).
Line 2: n numbers a1, a2, ..., an (-10^9 ≤ ai ≤ ).
Line 3: q (1 ≤ q ≤ 10^6), the number of d-queries.
In the next q lines, each line contains 2 numbers i, j
representing a d-query (1 ≤ i ≤ j ≤ n).
Output
For each d-query (i, j), print the number of distinct elements in the
subsequence ai, ai+1, ..., aj in a single line.
Example
Input
9
1 2 3 2 4 1 2 3 4
3
1 9
2 4
5 9
2 7
Output
0 //Explanation: all elements have been repeated.
1 //Explanation: only 3 has not repeated.
3 //Explanation: only 4 is repeated, so count only 1, 2 and 3.
3 //Explanation: only 2 is repeated, so count only 3, 4 and 1.
what could it be the necessary changes which should have done in #kraskevich 's answer(which is an efficient solution for that particular case)? I tried to add 0 in BIT, instead of -1 in above-mentioned solution, which does not help for all types of queries. Can anybody get me an idea?
I finally made it using MOs Algorithm. Following will work as expected.
/** For the given set of queries find the Unique element
* count of an array using MO's Algorithum. */
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <unordered_map>
using namespace std;
struct Query // struct for storing the queries
{
int Left;
int Right;
int Index;
};
inline void Add(const int i, int &ans, vector<int> &Arr, vector<int> &countArray)
{
++countArray[Arr[i]];
if(countArray[Arr[i]] == 1)
ans += countArray[Arr[i]];
if(countArray[Arr[i]] == 2)
ans -= countArray[Arr[i]];
}
inline void Remove(const int i, int &ans, vector<int> &Arr, vector<int> &countArray)
{
--countArray[Arr[i]];
if(countArray[Arr[i]] == 1)
ans += countArray[Arr[i]];
if(countArray[Arr[i]] == 0)
ans -= countArray[Arr[i]];
}
int main()
{
int _size; cin >> _size;
vector<int> Arr; Arr.reserve(_size);
copy_n(istream_iterator<int>(cin), _size, back_inserter(Arr));
//copy(Arr.cbegin(), Arr.cend(), ostream_iterator<int>(cout, "\t"));
int id = -1;
int sqrt_n = sqrt(_size);
int Q; cin >> Q;
vector<Query> qArr(Q);
unordered_map<int, int> Map;
for (int i = 0; i < _size; ++i)
{
if (Map.count(Arr[i]) == 0)
Map[Arr[i]] = ++id;
Arr[i] = Map[Arr[i]];
}
// read queries
for (int i = 0; i < Q; ++i)
{
int L,R;
cin >> L >> R;
qArr[i].Left = L-1;
qArr[i].Right = R-1;
qArr[i].Index = i;
}
// sort the queries according to(MO's Algorithum)
sort(qArr.begin(),qArr.end(),
[&](const Query &lhs, const Query &rhs)->bool
{
return ( (lhs.Left/sqrt_n == rhs.Left/sqrt_n) ?
lhs.Right < rhs.Right: // Qs with same Left case
(lhs.Left / sqrt_n) < (rhs.Left / sqrt_n) ); // Qs with diff values case
});
int currStart = 0;
int currEnd = 0;
int tempAnswer= 0;
vector<int> Answer(Q);
vector<int> countArray(_size);
for (int i = 0; i < Q; ++i)
{
int L = qArr[i].Left;
int R = qArr[i].Right;
/** Remove extra elements of previous range. For
* example if previous range is [0, 3] and current
* range is [2, 5], then a[0] and a[1] are subtracted */
while (currStart < L)
{
Remove(currStart, tempAnswer, Arr, countArray);
++currStart;
}
/** Add Elements of current Range */
while (currStart > L)
{
Add(currStart - 1, tempAnswer, Arr, countArray);
--currStart;
}
while (currEnd <= R)
{
Add(currEnd, tempAnswer, Arr, countArray);
++currEnd;
}
/** Remove elements of previous range. For example
* when previous range is [0, 10] and current range
* is [3, 8], then a[9] and a[10] are subtracted */
while (currEnd > R + 1)
{
Remove(currEnd - 1, tempAnswer, Arr, countArray);
--currEnd;
}
Answer[qArr[i].Index] = tempAnswer;
}
for(const auto &it: Answer) cout<<it<<endl;
return 0;
}