"Summable Numbers" in C++ - c++

The divisors of n can make the number between 1 to n. This is called a summable number. An example is 12. 1, 2, 3, 4, 6, 12 can be added together in different ways to make the numbers 1 through 12. Now this code gives me all summable numbers from 1 to an user inputed number but it is also giving me some numbers that are not summable such as 14. I am not sure why that is. Where in the code do I have to make a change?
#include <iostream>
#include <vector>
#include <math.h>
using namespace std;
vector <int> divisors;
vector<int> subsetsResult;
vector<int> subset;
bool isSummableNumber(int num)
{
if ((num > 1) && (num % 2 != 0))
{
return false;
}
for (int i=1; i<=num; i++)
{
if (num%i==0)
{
divisors.push_back(i);
int SIZE_OF_DIVISORS_SET = divisors.size();
double COUNTER_LIMIT = pow(2, SIZE_OF_DIVISORS_SET) - 1;
int TOTAL_NUMBER_OF_BITS = 8;
for (int counter = 1; counter <= COUNTER_LIMIT; counter++)
{
int currentValue = counter;
for (int bitIndex = 0; bitIndex < TOTAL_NUMBER_OF_BITS; bitIndex++)
{
if (currentValue & 000001)
{
subset.push_back(divisors[bitIndex]);
}
currentValue = currentValue >> 1;
}
int sum = 0;
for (std::vector<int>::iterator it = subset.begin() ; it != subset.end(); ++it)
sum += *it;
if (sum >= 1 && sum <= num)
{
subsetsResult.push_back(sum);
}
}
subsetsResult;
int counter = 1;
for (std::vector<int>::iterator it = subsetsResult.begin(); it != subsetsResult.end(); ++it)
{
if (counter != *it)
{
return false;
}
counter += 1;
}
return true;
}
}
}
int main()
{
int num;
cout << "Enter a Positive Integer: " ;
cin >> num;
for (int i=1; i<=num; i++)
{
if (isSummableNumber(i))
cout << i << endl;
}
return 0;
}

I'd calculate the set of all numbers from 0 to n that are the sums of divisors that you found so far. std::vector with a size of n + 1 will do fine. Initially, only element 0 is set. Then if you find another divisor d (in pseudo-code)
for (i = n; i >= d; --i)
if (resultset contains i - d)
add i to the result set.
Finally you check whether the set contains all numbers from 0 to n.

This does not do anything: subsetsResult;
Also, don't you get a compiler warning about paths in your function that do not return a value? There is a missing return false; and the end of the function (and maybe and assertion if that return should never be reached).

Right now you're searching divisor combinations before you've even found all the divisors. That's not a good idea, and it likely is hiding your problem.
Either wait until all divisors are found and then iterate the 2**k sums they produce, or else when each new divisor is found, produce sums from the already-known sums and the new divisor, and skip the bit manipulation. For example:
sums = {0}
N=14, i=1, N%i == 0, sums += i + sums => sums = {0, 1+0}
N=14, i=2, N%i == 0, sums += i + sums => sums = {0, 1, 2+0, 2+1}
N=14, i=3, N%i == 2
...
N=14, i=7, N%i == 0, sums += i + sums => sums = {0, 1, 2, 3, 7+0, 7+1, 7+2, 7+3}
Now since 4 < N and 4 is not a member of sums, exclude 14

Related

Denominate the amount with the minimum number of coins with a given face value. Greedy problem

I have the C++ function to do. It works fine, but there are some cases where it works bad - "greedy problem".
My C++ code:
#include <vector>
#include <algorithm>
std::vector<int> ans;
std::vector<int> get_change(const std::vector<int> &denominations, int amount) {
//pure algo
std::vector<int> money = denominations;
std::vector<int> count;
ans.clear();
count.assign(money.size(), 0);
std::sort(money.begin(), money.end());
int summ = amount;
for (int i = count.size()-1; i >= 0; i--) {
count[i] = summ / money[i];
summ = summ % money[i];
if (summ==0)
break;
}
//ans generation
for (int i = 0; i < money.size(); i++)
for (int j = 0; j < count[i]; j++)
ans.push_back(money[i]);
return ans;
}
Greedy problem sample: get_change({ 1, 6, 9 }, 30) will return { 1, 1, 1, 9, 9, 9 }, but not { 6, 6, 9, 9 }.
The task is to improve this algorithm to get the same answer.
One possible approach is backtracking.
Backtracking is a general algorithm for finding all (or some) solutions to some computational problems, notably constraint satisfaction problems, that incrementally builds candidates to the solutions, and abandons a candidate ("backtracks") as soon as it determines that the candidate cannot possibly be completed to a valid solution. (Wikipedia)
Here, we try to determine the number of coins, for each coin.
The candidates are abandonned, as soon as the total number of coins is higher than the current optimal solution. Moreover, here, in a given situation (at step i), we directly calculate the maximum number of coins for coins[i], such that the total sum is not higher than the amount.
Here is a possible implementation:
#include <iostream>
#include <vector>
#include <algorithm>
std::vector<int> get_change(const std::vector<int>& denominations, int amount) {
std::vector<int> coins = denominations;
std::vector<int> n_coins(coins.size(), 0);
std::vector<int> n_coins_opt(coins.size(), 0);
int n = coins.size();
std::sort(coins.begin(), coins.end(), std::greater<int>());
int sum = 0; // current sum
int i = 0; // index of the coin being examined
int n_min_coins = amount / coins[n - 1] + 1;
int n_total_coins = 0;
bool up_down = true;
while (true) { // UP
if (up_down) {
n_coins[i] = (amount - sum) / coins[i]; // max number of coins[i]
sum += n_coins[i] * coins[i];
n_total_coins += n_coins[i];
if (sum == amount) {
if (n_total_coins < n_min_coins) {
n_min_coins = n_total_coins;
n_coins_opt = n_coins;
}
up_down = false;
sum -= n_coins[i] * coins[i];
n_total_coins -= n_coins[i];
n_coins[i] = 0;
i--;
}
else {
if (i == (n - 1) || (n_total_coins >= n_min_coins)) { // premature abandon
sum -= n_coins[i] * coins[i];
n_total_coins -= n_coins[i];
n_coins[i] = 0;
up_down = false;
i--;
}
else {
i++;
}
}
}
else { // DOWN
if (i < 0) break;
if (n_coins[i] == 0) {
if (i == 0) break;
i--;
}
else {
sum -= coins[i];
n_coins[i] --;
n_total_coins--;
i++;
up_down = true;
}
}
}
std::vector<int> ans;
for (int i = 0; i < coins.size(); i++)
for (int j = 0; j < n_coins_opt[i]; j++)
ans.push_back(coins[i]);
return ans;
}
int main() {
std::vector<int> coins = { 1, 6, 9 };
int amount = 30;
auto n_coins = get_change(coins, amount);
for (int i = 0; i < n_coins.size(); i++)
std::cout << n_coins[i] << " ";
std::cout << "\n";
return 1;
}
This is a dynamic programming problem.
import java.util.*;
import java.lang.*;
import java.io.*;
class Solution{
public static void main (String[] args) throws java.lang.Exception{
System.out.println(getChange(new int[]{1,6,9},30));
System.out.println(getChange(new int[]{1},3));
System.out.println(getChange(new int[]{4,20,500},450));
}
private static List<Integer> getChange(int[] denominations,int amount){
Arrays.sort(denominations);
List<Integer> ans = new ArrayList<>();
if(amount <= 0 || denominations[0] > amount) return ans;
int[][] dp = new int[amount + 1][2];
for(int i=0;i<denominations.length;++i){
if(denominations[i] > amount) break;
dp[denominations[i]][0] = 1;
dp[denominations[i]][1] = 0;
for(int j=denominations[i] + 1;j<=amount;++j){
if(dp[j-denominations[i]][0] > 0 && (dp[j][0] == 0 || dp[j-denominations[i]][0] + 1 < dp[j][0])){
dp[j][0] = dp[j-denominations[i]][0] + 1;
dp[j][1] = j-denominations[i];
}
}
}
if(dp[amount][0] > 0){
while(dp[amount][0] != 0){
ans.add(amount - dp[amount][1]);
amount = dp[amount][1];
}
}
return ans;
}
}
Demo: https://ideone.com/2fYg4F
Algorithm:
This is similar to coin change problem.
We first sort the numbers in the array for uniform computation.
Now, we iterate on all array elements and make each array element loop over all possible amounts from that element till final amount.
Now, we can make amount j(which is a sum) only if we have made sum j - denominations[i].
While doing so, we also check for minimum number of coins needed. If amount j with current denominations[i] needs lesser coins than the current value stored in dp[j][0], then we update the answer in dp[j] accordingly.
In the end, we just loop over the exact coins needed and return the answer.
What is dp[][]:
It's just a simple 2D array where the 0th column keeps track of minimum number of coins
needed in it's first index and 2nd index has the previous coin index that give it the
minimal value.
The 2nd index in dp[][] would ease out the calculation to find the exact coin value as we would have to just do amount - dp[amount][1] to get the coin value.
In the end, we just do a check of dp[amount][0] value. If it's value is 0, we don't have a solution, else we compute it.
I am adaptated vivek_23's dynamic solution to required C++ language.
std::vector<int> get_change2(const std::vector<int>& coins, int amount) {
std::vector<int> denominations = coins;
std::sort(denominations.begin(), denominations.end());
std::vector<int> ans;
if (amount <= 0 || denominations[0] > amount)
return ans;
int** dp = new int* [amount + 1];
for (int i = 0; i < amount + 1; i++) {
dp[i] = new int[2];
dp[i][0] = 0;
dp[i][1] = 0;
}
for (int i = 0; i < denominations.size(); i++) {
if (denominations[i] > amount) break;
dp[denominations[i]][0] = 1;
dp[denominations[i]][1] = 0;
for (int j = denominations[i] + 1; j <= amount; ++j) {
if (dp[j - denominations[i]][0] > 0 && (dp[j][0] == 0 || dp[j - denominations[i]][0] + 1 < dp[j][0])) {
dp[j][0] = dp[j - denominations[i]][0] + 1;
dp[j][1] = j - denominations[i];
}
}
}
if (dp[amount][0] > 0) {
while (dp[amount][0] != 0) {
ans.push_back(amount - dp[amount][1]);
amount = dp[amount][1];
}
}
return ans;
}

How to use less memory in Sieve_of_Eratosthenes

I'm coding on a leetcode-like platform. There is a task: counter the number of primes below a given bound.
I used the algorithm: https://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
I copy the code from here: https://www.geeksforgeeks.org/sieve-of-eratosthenes/ , except that I make false represents isPrime to avoid using memset. Here is my code:
void SieveOfEratosthenes(int n)
{
bool *prime = new bool[n+1](); // initialized by false by default
for (int p=2; p*p<=n; p++)
{
if (prime[p] == false)
{
for (int i=p*p; i<=n; i += p)
prime[i] = true;
}
}
for (int p=2; p<=n; p++)
if (prime[p])
cout << p << " ";
}
However, when I execute it, the platform tells me that I used too much memory in the case of 100 000 000 as the enter.
I've checked that sizeof(bool) equals to 1.
Is there some way to use less memory for this piece of code?
A couple of suggestions:
use a bit array representing only odd numbers
break the problem up into segments so the partial sieve uses much less memory
#Kim Walish has a fast C++ version here:
https://github.com/kimwalisch/primesieve/wiki/Segmented-sieve-of-Eratosthenes
You can make it use less memory still by always limiting the segment size to the L1 cache size, and by changing the IsPrime array to also be a bit array of odd numbers.
This is a memory optimized implementation of the sieve of eratosthenes. The basic idea is that, you only need to store the status of the odd numbers. Rest of it is similar to the normal implementation.
#include <iostream>
class Solution {
public:
int countPrimes(int n) {
//if(n <= 1) return 0; // including n
if(n <= 2) return 0; // number of primes less than 0 / 1 / 2 is 0
const int MAXN = 1500000 + 5; // adjust MAXN accordingly
// finding prime from 1 up to N
int status[(MAXN >> 1) + 1]; // we need space for only the odd numbers
// works well up to 1.5 * 10 ^ 6, for numbers larger than that, you need to adjust the second operand accordingly
int prime[115000 + 1000]; // prime number distribution , pi(x) = x/ (ln(x) - 1) , adjust this according to MAXN
// If status[i] = 0 -> i is prime
// If status[i] = 1 -> i is not prime
for(int i = 1 ; i <= (n >> 1) ; ++i) status[i] = 0; // for every i , 2 * i + 1 is the odd number, marking it as prime
int sqrtN = static_cast <int> ((sqrt (static_cast <double> (n))));
// computing sqrt(N) only once because it is costly computing it inside a loop
// only accounting the odd numbers and their multiples
for(int i = 3 ; i <= sqrtN ; i += 2){
if(status[i >> 1] == 0){
// if this is still a prime then discard its multiples
// first multiple that needs to be discarded starts at i * i
// all the previous ones have already been discarded
for(int j = i * i ; j <= n ; j += (i + i)) {
//printf("Marking %d as not prime\n",j);
status[j >> 1] = 1;
}
}
}
int counter = 0;
prime[counter++] = 2;
for(int i = 3 ; i <= n ; i += 2){
if(status[i >> 1] == 0){
prime[counter++] = i;
}
}
if( (n & 1) && !status[n >> 1]) counter--; // if n is prime, discard n
std::cout << "Number of primes less than " << n << " is " << counter << "\n";
for(int i = 0 ; i < counter; ++i){
std::cout << prime[i];
if(i != counter - 1) std::cout << "\n";
}
std::cout << "\n";
return counter;
}
};
int main(int argc, char const *argv[])
{
Solution solution;
int n; std::cin >> n;
solution.countPrimes(n);
return 0;
}

How can I pair all the elements of a vector using backtracking

I have a backtracking homework problem and I can only get 80/100 points, due to my inefficient program. The statement of the problem is the following:
n natural numbers are given (n is even). The n numbers are paired and for each pair, you find the remainder of the division between the two elements of the pair and sum all remainders. Find the minimum value of this sum.
2<=n<=18 and all n natural numbers are <=1000
Example:
n=4 and the 4 numbers are: {6, 5, 3, 4}
The result is 1. Minimum sum of the remainders is 1 because 6 is paired with 3 and 5 is paired with 4. So we have the pairs : {6, 3} and {5, 4}. 6%3 == 0 so the remainder of the first pair is 0. 5%4 == 1 so the remainder of the second pair is 1. 0+1=1 is the smallest possible sum. There is no other pairing of the elements that give a smaller remainder sum.
So what I've tried (since this is a backtracking problem) is to generate all possible pairs, find the remainder sum and choose the smallest one. But my solution is not efficient enough, it only gets 80/100 points. This is the code:
#include <iostream>
#include <climits>
using namespace std;
int n, a[20], v[20], first[20], second[20], suma_min=INT_MAX;
bool solution() {
int i;
for (i=1; i<=n; i++) {
if (a[i] != -1) {
return false;
}
}
return true;
}
void find_sum() {
int i, curr_sum=0;
for (i=1; i<=n/2; i++) {
curr_sum = curr_sum + (first[i] % second[i]);
}
if (curr_sum < suma_min) {
suma_min = curr_sum;
}
}
void backtrack(int k,int stage) {
int i;
for (i=1; i<=n; i++) {
if (a[i] != -1) {
if (stage == 1) {
first[k] = a[i];
a[i] = -1;
if (solution()) {
find_sum();
}
else {
backtrack(k, stage+1);
}
a[i] = v[i];
}
else {
second[k] = a[i];
a[i] = -1;
if (solution()) {
find_sum();
}
else {
backtrack(k+1, stage-1);
}
a[i] = v[i];
}
}
}
}
int main()
{
int i;
cin >> n;
for (i=1; i<=n; i++) {
cin >> v[i];
a[i] = v[i];
}
backtrack(1,1);
cout << suma_min;
return 0;
}
Is there a way to do this faster? Is there an algorithm that pairs all the elements of an array, 2 by 2? Any help is much appreciated.

Factorial function only returning inputted answer in C++?

I have to create a program which calculates the factorial of any number, the problem is if I input any number above 20 it just returns that number. What in my else if statement could be causing this and is there a better way to solve this? ( this function is called in main and works if num <= 20)
void factorial() {
//User input for number
long long num;
std::cout << "Input any positive integer to find its factorial: ";
std::cin >> num;
unsigned long long numFact = 1;
if (num <= 20) {
while (num > 0) {
numFact = numFact * num;
num = num - 1;
}
std::cout << numFact;
}
else if (num > 20) {
std::vector<int> multFactorial;
//stores num as seperate elements in vector multFactorial
while (num > 0) {
int remain = num % 10;
num = num / 10;
multFactorial.insert(multFactorial.begin(), remain);
}
std::vector<int> answer;
std::vector<int> answerFinal;
//Manually multiplies elements in multFactorial
//Then adds new vectors created by multiplying to get final answer
//Repeats until factorial is solved
//Ex: 21 * 20; 0 * 1 and 0 * 2 stored as {0 , 0}
//2*1 and 2*2 stored as {4, 2, 0}
//Vectors will be addes to get {4, 2, 0} and then that will be multiplied
by 19 until num = 1
while (num > 1) {
for (int i = multFactorial.size() - 1; i >= 0; i--) {
int remain1 = ((num - 1) % 10) * multFactorial[i];
answer.insert(answer.begin(), remain1);
int remain2 = (((num - 1) / 10) * multFactorial[i]);
answerFinal.insert(answerFinal.begin(), remain2);
}
answerFinal.insert(answerFinal.begin(), 0);
//Adds vectors to get final value seperate as digits
for (int i = multFactorial.size() - 1; i >= 0; i--) {
multFactorial[i] = answer[i] + answerFinal[i];
}
num = num - 1;
}
//Prints what should be the factorial of the number input
for (size_t i = 0; i < multFactorial.size(); i++) {
std::cout << multFactorial[i];
}
}
}
Factorials of large numbers results in huge numbers. This can be accommodated in languages like C, C++ etc by putting the results into arbitrary length strings.
Here is an algorithm for that - similar to yours.
https://www.geeksforgeeks.org/factorial-large-number/
Best advice is to check your code against this.
Use a debugger if you have one and step through the code line by line.
If not print out intermediate results and compare with expected.
EDIT: As per review comment, the code at above ref is similar to below- just in case link is broken in future.
// C++ program to compute factorial of big numbers
#include<iostream>
using namespace std;
// Maximum number of digits in output
#define MAX 100 // change to whatever value you need
int multiply(int x, int res[], int res_size);
// Calculate factorial of large number
void factorial(int n)
{
int res[MAX];
// Initialize result
res[0] = 1;
int res_size = 1;
// Apply factorial formula
for (int x=2; x<=n; x++)
res_size = multiply(x, res, res_size);
// print out the result
cout << "Factorial is \n";
for (int i=res_size-1; i>=0; i--)
cout << res[i];
}
// Multiplies x with the number represented by res[].
// res_size is size of res[] or number of digits in the
// number represented by res[].
int multiply(int x, int res[], int res_size)
{
int carry = 0; // Initialize carry
// One by one multiply n with individual digits of res[]
for (int i=0; i<res_size; i++)
{
int prod = res[i] * x + carry;
// Store last digit of 'prod' in res[]
res[i] = prod % 10;
// Put rest in carry
carry = prod/10;
}
// Put carry in res and increase result size
while (carry)
{
res[res_size] = carry%10;
carry = carry/10;
res_size++;
}
return res_size;
}
// Main program
int main()
{
//put code here to read a number
factorial(50); // take 50 for example
return 0;
}

Maximum sum from two sorted arrays

You are given two sorted integer arrays, which have some common integers. Any common integer between the two sequences constitute an intersection point.
You can start traversing from any of the array and switch to the other array or continue with the same array at an intersection point.
The objective is to find a path that produces the maximum sum of the data.
Take for example the following two sequences where intersection points are printed in bold:
First = 3 5 7 9 20 25 30 40 55 56 57 60 62
Second = 1 4 7 11 14 25 44 47 55 57 100
In the above example, the largest possible sum is 450 which is the result of adding
3, 5, 7, 9, 20, 25, 44, 47, 55, 56, 57, 60, and 62
I wrote the following code but it is not compiling, please help:
/* M: size of the array a
N: size of the array b
*/
int i,j,sum1,sum2,sum,m_i,n_j = 0;
void printIntersectionElements(int *a,int M, int *b, int N) {
if (M == 0)
return (b);
if (N ==0)
return(a);
while( i < M && j < N ){
sum1 = sum1 +a[i];
sum2 = sum2 + b[j];
if(a[i] == b[j]) { // found a common element.
if(sum1>= sum2){
for(;m_i<= i; m_i++)
cout<< a[m_i];
sum = sum +sum1;
m_i = i+1;
}
else {
for(;n_j<= j; n_j++)
cout<< b[n_j];
sum = sum+sum2;
n_j = j+1;
}
sum1 = sum2 = 0;
}
i++;
j++;
}
}
You are trying to return a result from a function that is declared with a void return type. That's not valid C++, which is why you are getting a compiler error.
There may be other errors, too. Read the error messages: they will tell you exactly what and where the problem is.
This question can be solved in O(m+n).
You can maintain a cumulative sum array for both arrays.
First find the intersection point in O(m+n).
Then check which array has maximum sum between two intersection point.
Add them in a variable.
Here is the code.
#include <iostream>
#include <vector>
#include <cstdio>
using namespace std;
void print(int a[], int x, int y) {
for(int i = x; i <= y; i++) {
printf("%d ", a[i]);
}
}
int main ()
{
int i, j, x, y, n, m;
int a0[100], a1[100], sum1[100], sum0[100];
vector <int> v0, v1;
cout << "Enter the value of n and m:\n";
cin >> n >> m;
scanf("%d", &a0[0]);
sum0[0] = a0[0];
for(i = 1; i < n; i++) {
scanf("%d", &a0[i]);
sum0[i] = a0[i] + sum0[i-1]; //cumulative sum for first array
}
scanf("%d", &a1[0]);
sum1[0] = a1[0];
for(i = 1; i < m; i++) {
scanf("%d", &a1[i]);
sum1[i] += a1[i] + sum1[i-1]; //cumulative sum for second array
}
i = 0;
j = 0;
while(i < n && j < m) { //loop breaks when either one of the array ends
if(a0[i] == a1[j]) { //if there is a intersection
v0.push_back(i); //store index of both the arrays
v1.push_back(j);
i++;
j++;
}
else if(a0[i] > a1[j]) { //else increase the index of array
j++; //containing small number
}
else if(a0[i] < a1[j]) {
i++;
}
}
i = 0;
j = 0;
int sum = 0;
while(i < v0.size()) {
x = v0[i];
y = v1[i];
if(i == 0) {
if(sum0[x] > sum1[y]) { //check which array has greater sum
sum += sum0[x]; //first intersection
print(a0, 0, x);
}
else {
sum += sum1[y];
print(a1, 0, y);
}
i++;
}
else {
if(sum0[x]-sum0[v0[i-1]] > sum1[y]-sum1[v1[i-1]]) {
sum += sum0[x]-sum0[v0[i-1]]; //checks which array has greater sum
print(a0, v0[i-1]+1, x); //between two intersectio
}
else {
sum += sum1[y]-sum1[v1[i-1]];
print(a1, v1[i-1]+1, y);
}
i++;
}
}
if(sum0[n-1]-sum0[x] > sum1[m-1]-sum1[y]) {
sum += sum0[n-1]-sum0[x]; //check which array has greater sum
print(a0, x+1, n-1); //at last intersection
}
else {
sum += sum1[m-1]-sum1[y];
print(a1, y+1, m-1);
}
cout << endl << "sum = " << sum << endl;
return 0;
}
Your code has several problems:
First of it doesn't compile, since your function is declared to return void, but you try to return int*. Change your return statements to return;
However even if you fix that your function doesn't solve the problem you have described.
Your summation stops when you reach the end of the smaller of the two arrays. However from your example you should actually go till the end of both arrays.
Furthermore you only detect intersection points when both arrays contain the same number at the same position, however from your text I would think that you should detect points as intersections, even if they are at different positions in the array (I might be wrong though, depending on the exact formulation of your exercise). To do that the easiest way would be to handle only the smaller value of a[i] and b[j] each iteration (and increase only either i or j (or both if its an intersection).