A number as it's prime number parts - c++

I have to print the number of ways you can represent a given number as it's prime number parts.
Let me clarify: Let's say I have been given this number 7. Now, first of all, I have to find all the prime numbers that are less than 7, which are 2, 3 and 5. Now, in how many ways can I summarize those numbers (I can use one number as many times I want) so that the result equals 7? For example, number 7 has five ways:
2 + 2 + 3
2 + 3 + 2
2 + 5
3 + 2 + 2
5 + 2
I'm totally lost with this task. First I figured I'd make an array of usable elements like so: { 2, 2, 2, 3, 3, 5 } (7/2 = 3, so 2 must appear three times. Same goes with 3, which gets two occurences). After that, loop through the array and choose a 'leader' that determines how far in the array we are. I know the explanation is horrible, so here's the code:
#include <iostream>
#include <vector>
int primes_all[25] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
int main()
{
int number;
std::cin >> number;
std::vector<int> primes_used;
for(int i = 0; i < 25; i++) {
if(primes_all[i] < number && number-primes_all[i] > 1) {
for(int k = 0; k < number/primes_all[i]; k++)
primes_used.push_back(primes_all[i]);
}
else break;
}
int result = 0;
for(size_t i = 0; i < primes_used.size(); i++) {
int j = primes_used.size()-1;
int new_num = number - primes_used[i];
while(new_num > 1 && j > -1)
{
if(j > -1) while(primes_used[j] > new_num && j > 0) j--;
if(j != i && j > -1) {
new_num -= primes_used[j];
std::cout << primes_used[i] << " " << primes_used[j] << " " << new_num << std::endl;
}
j--;
}
if(new_num == 0) result++;
}
std::cout << result << std::endl;
system("pause");
return 0;
}
This simply doesn't work. Simply because the idea behind it is wrong. Here's a little details about the limits:
Time limit: 1 second
Memory limit: 128 MB
Also, the biggest number that can be given is 100. That's why I made the array of prime numbers below 100. The result grows very fast as the given number gets bigger, and will need a BigInteger class later on, but that's not an issue.
A few results known:
Input Result
7 5
20 732
80 10343662267187
SO... Any ideas? Is this a combinatory problem? I don't need code, just an idea. I'm still a newbie to C++ but I'll manage
Keep in mind that 3 + 2 + 2 is different than 2 + 3 + 2.
Also, were the given number to be a prime itself, it won't be counted. For example, if the given number is 7, only these sums are valid:
2 + 2 + 3
2 + 3 + 2
2 + 5
3 + 2 + 2
5 + 2
7 <= excluded

Dynamic programming is your friend here.
Consider the number 27.
If 7 has 5 results, and 20 has 732 results, then you know that 27 has at least (732 * 5) results. You can use a two variable system (1 + 26, 2 + 25 ... etc) using the precomputed values for those as you go. You don't have to recompute 25 or 26 because you already did them.

The concept you are searching for is the "prime partitions" of a number. S partition of a number is a way of adding numbers to reach the target; for instance, 1+1+2+3 is a partition of 7. If all the addends are prime, then the partition is a prime partition.
I think your example is wrong. The number 7 is usually considered to have 3 prime partitions: 2+2+3, 2+5, and 7. The order of the addends doesn't matter. In number theory the function that counts prime partitions is kappa, so we would say kappa(7) = 3.
The usual calculation of kappa is done in two parts. The first part is a function to compute the sum of the prime factors of a number; for instance, 42=2·3·7, so sopf(42)=12. Note that sopf(12)=5 because the sum is over only the distinct factors of a number, so even though 12=2·2·3, only one 2 is included in the calculation of the sum.
Given sopf, there is a lengthy formula to calculate kappa; I'll give it in LaTeX form, since I don't know how to enter it here: \kappa(n) = \frac{1}{n}\left(\mathrm{sopf}(n) + \sum_{j=1}^{n-1} \mathrm{sopf}(j) \cdot \kappa(n-j)\right).
If you actually want a list of the partitions, instead of just the count, there is a dynamic programming solution that #corsiKa pointed out.
I discuss prime partitions in more detail at my blog, including source code to produce both the count and the list.

Here's an efficient implementation which uses dynamic programming like corsiKa suggests, but does not use the algorithm he describes.
Simply: if n is reachable via k distinct paths (including the single-step one, if it exists), and p is prime, then we construct k paths to n+p by appending p to all paths to n. Considering all such n < N will produce an exhaustive list of valid paths to N. So we just sum the number of paths so discovered.
#include <iostream>
int primes_all[] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
const int N_max = 85;
typedef long long ways;
ways ways_to_reach_N[N_max + 1] = { 1 };
int main()
{
// find all paths
for( int i = 0; i <= N_max; ++i ) {
ways ways_to_reach_i = ways_to_reach_N[i];
if (ways_to_reach_i) {
for( int* p = primes_all; *p <= N_max - i && p < (&primes_all)[1]; ++p ) {
ways_to_reach_N[i + *p] += ways_to_reach_i;
}
}
}
// eliminate single-step paths
for( int* p = primes_all; *p <= N_max && p < (&primes_all)[1]; ++p ) {
--ways_to_reach_N[*p];
}
// print results
for( int i = 1; i <= N_max; ++i ) {
ways ways_to_reach_i = ways_to_reach_N[i];
if (ways_to_reach_i) {
std::cout << i << " -- " << ways_to_reach_i << std::endl;
}
}
return 0;
}
Demo: http://ideone.com/xWZT8v
Replacing the typedef ways with a big integer type is left as an exercise to the reader.

Related

Sum of array elements by order until target reached or end of the array reached

Let's say that I have this array:
int A[6] = {1, 7, 2, 4, 3, 9};
And I have the target number at 6. We want to add the numbers until target reached or at least close to the target.
The numbers that comes first have bigger priority, so it would look like this:
Add 1 and 7, which results in 8.
8 is bigger than 6, so ignore this sum and keep 1.
Add 1 and 2.
1 plus 2 results in 3, which is smaller than 6, so we go to the next element after 2,
while holding the successful result.
Right now, result is 3, and the next element is 4, but 3 plus 4 is bigger than 6,
so we don't do anything with our result, and go to the next element.
Result is still 3.
3 plus 3 is 6, so we succesfully reached our target.
We don't need to check the last element (9).
In the end, we added 1, 2 and 3.
Another example:
int B[4] = {5, 4, 3, 2};
Procedure:
Add 5 and 4.
Result is bigger than 6, so ignore the sum and keep 5.
Add 5 and 3. Still bigger than 6, ignore the sum and keep 5.
5 plus 2, 7. Bigger than 6 again.
The final result is 5.
In the end we didn't add anything, and kept 5.
I can't seem to figure the code for this pattern.
EDIT: I've come up with a code that works. Also, it executes until there's no leftovers in the array, dividing the array into parts, redoing the process until theres no element left in the array to be processed. Here it is:
int array[5] = { 500, 1000, 500, 500, 400 };
int arraySize = sizeof(array) / sizeof(array[0]);
int i = 1;
int j = 0;
int sum;
while (j < arraySize)
{
sum = 0;
sum += array[j];
while (i < arraySize)
{
if (sum + array[i] <= 1500)
{
sum += array[i];
array[i] = 0;
i++;
}
else
i++;
}
if (sum != 0)
cout << "Part " << j + 1 << ": " << sum << endl;
j++;
i = j + 1;
}
In this example, we have the target number at 1500, with this array:
int array[5] = { 500, 1000, 500, 500, 400 };
The code returns
Part 1: 1500
Part 2: 1400
it does the same procedure as the other two examples that I gave, but redoing it with all the elements:
Add 500 and 1000, which results in 1500.
1500 is the target number, so doing a sum is not needed anymore,
so it prints the first part that fit in the target,
while maintaining the priority protocol.
Now, add 500 (the 3rd element) plus 500, which results in 1000.
1000 is smaller than 1500, so we keep going.
1000 plus 400 is 1400, which is smaller than 1500, but is the last
element, so we finish here.
Well, the code works, but it was kind of a "trial and error" success. Also, I have a new problem, which is: getting the indexes of the elements that were successful in the sum. It should print something like this:
Part 1: 1500
0, 1
Part 2: 1400
2, 3, 4

Trying to implement the Binary Search algorithm, can't seem to get it to work

I've been trying for the past hour to get this binary search algorithm to work and by using an example of the algorithm as explained on khan academy, I still can't get it to work, it should output a number but nothing happens. The example on khan academy is like this:
Let min = 0 and max = n-1.
If max < min, then stop: target is not present in array. Return -1.
Compute guess as the average of max and min, rounded down (so that it is an integer).
If array[guess] equals target, then stop. You found it! Return guess.
If the guess was too low, that is, array[guess] < target, then set min = guess + 1.
Otherwise, the guess was too high. Set max = guess - 1.
Go back to step 2.
And the code I wrote according to the steps is:
#include <iostream>
int main() {
int arr[] = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97 };
int min = 0;
int max = 24;
int guess;
int targetValue = 73;
while (max > min) {
guess = ((max + min) / 2);
if (arr[guess] == targetValue) {
std::cout << guess;
break;
}
else if (arr[guess] < targetValue) {
min = guess + 1;
}
else {
max = guess - 1;
}
}
return 0;
}
The binary search algorithm states
If L > R, the search terminates as unsuccessful.
In your implementation however, you terminate the search on the condition L >= R. In the case of L == R, the algorithm should do one more iteration, because it did not consider this position in the list yet.
In your case of target value 73, when the algorithm reaches the position of the target, 20, L == R. Your implementation terminates one step too early to recognize the target.
try this:
(max > min) to (max >= min)

All possible combinations of coins

I need to write a program which displays all possible change combinations given an array of denominations [1 , 2, 5, 10, 20, 50, 100, 200] // 1 = 1 cent
Value to make the change from = 300
I'm basing my code on the solution from this site http://www.geeksforgeeks.org/dynamic-programming-set-7-coin-change/
#include<stdio.h>
int count( int S[], int m, int n )
{
int i, j, x, y;
// We need n+1 rows as the table is consturcted in bottom up manner using
// the base case 0 value case (n = 0)
int table[n+1][m];
// Fill the enteries for 0 value case (n = 0)
for (i=0; i<m; i++)
table[0][i] = 1;
// Fill rest of the table enteries in bottom up manner
for (i = 1; i < n+1; i++)
{
for (j = 0; j < m; j++)
{
// Count of solutions including S[j]
x = (i-S[j] >= 0)? table[i - S[j]][j]: 0;
// Count of solutions excluding S[j]
y = (j >= 1)? table[i][j-1]: 0;
// total count
table[i][j] = x + y;
}
}
return table[n][m-1];
}
// Driver program to test above function
int main()
{
int arr[] = {1, 2, 5, 10, 20, 50, 100, 200}; //coins array
int m = sizeof(arr)/sizeof(arr[0]);
int n = 300; //value to make change from
printf(" %d ", count(arr, m, n));
return 0;
}
The program runs fine. It displays the number of all possible combinations, but I need it to be more advanced. The way I need it to work is to display the result in following fashion:
1 cent: n number of possible combinations.
2 cents:
5 cents:
and so on...
How can I modify the code to achieve that ?
Greedy Algorithm Approach
Have this denominations in an int array say, int den[] = [1 , 2, 5, 10, 20, 50, 100, 200]
Iterate over this array
For each iteration do the following
Take the element in the denominations array
Divide the change to be allotted number by the element in denominations array number
If the change allotted number is perfectly divisible by the number in denomination array then you are done with the change for that number.
If the number is not perfectly divisible then check for the remainder and do the same iteration with other number
Exit the inner iteration once you get the value equal to the change number
Do the same for the next denomination available in our denomination array.
Explained with example
den = [1 , 2, 5, 10, 20, 50, 100, 200]
Change to be alloted : 270, let take this as x
and y be the temporary variable
Change map z[coin denomination, count of coins]
int y, z[];
First iteration :
den = 1
x = 270
y = 270/1;
if x is equal to y*den
then z[den, y] // z[1, 270]
Iteration completed
Second Iteration:
den = 2
x = 270
y = 270/2;
if x is equal to y*den
then z[den , y] // [2, 135]
Iteration completed
Lets take a odd number
x = 217 and den = 20
y= 217/20;
now x is not equal to y*den
then update z[den, y] // [20, 10]
find new x = x - den*y = 17
x=17 and identify the next change value by greedy it would be 10
den = 10
y = 17/10
now x is not equal to y*den
then update z[den, y] // [10, 1]
find new x = x - den*y = 7
then do the same and your map would be having following entries
[20, 10]
[10, 1]
[5, 1]
[2, 1]

Searching for specific groups using permutation without repetition and greedy aproach (homework)

I'm student of second year on CS. On my algorithms and data structures course I've been tasked with following problem:
Input:
2<=r<=20
2<=o<=10
0<=di<=100
Output:
number of combinations
or "NO" if there are none
r is number of integers
di are said integers
o is number of groups
I have to find the number of correct combinations. The correct combination is one where every integer is assigned to some group, none of the groups are empty and the sum of integers in every group is the same:
For an instance:
r = 4;
di = {5, 4, 5, 6}
o = 2;
So the sum of integers in every group should add up to 10:
5 + 4 + 5 + 6 = 20
20 / o = 20 / 2 = 10
So we can make following groups:
{5, 5}, {4, 6}
{5, 5}, {6, 4}
{5, 5}, {4, 6}
{5, 5}, {6, 5}
So as we can see, the every combination is essentialy same as first one.( The order of elements in group doesnt matter.)
So actually we have just one correct combination: {5, 5}, {4, 6}. Which means output is equal to one.
Other examples:
r = 4;
di = {10, 2, 8, 6}
o = 2;
10 + 2 + 8 + 6 = 26;
26 / o = 26 / 2 = 13
There is no way to make such a sum of these integers, so the output is "NO".
I had a following idea of getting this thing done:
struct Input { // holds data
int num; // number of integers
int groups; // number of groups
int sumPerGroup; // sum of integers per group
int *integers; // said integers
};
bool f(bool *t, int s) { // generates binary numbers (right to left"
int i = 0;
while (t[i]) i++;
t[i] = 1;
if (i >= s) return true;
if (!t[i + 1])
for (int j = i - 1; j >= 0; j--)
t[j] = 0;
return false;
}
void solve(Input *input, int &result) {
bool bin[input->num]; // holds generated binary numbers
bool used[input->num]; // integers already used
for (int i = 0; i < input->num; i++) {
bin[i] = 0;
used[i] = 0;
}
int solved = 0;
do {
int sum = 0;
for (int i = 0; i < input->num; i++) { // checking if generated combination gets me nice sum
if (sum > input->sumPerGroup) break;
if (bin[i] && !used[i]) sum += input->integers[i]; // if generated combination wasnt used before, start adding up
if (sum == input->sumPerGroup) { // if its add up as it shoul
for (int j = 0; j < input->num; j++) used[j] = bin[j]; // mark integers as used
solved ++; // and mark group as solved
sum = 0;
}
if (udane == input->groups) { // if the number of solved groups is equal to number of groups
result ++; // it means we found another correct combination
solved = 0;
}
}
} while (!f(bin, input->num)); // as long as I can get more combinations
}
So, the main idea is:
1. I generate combination of some numbers as binary number
2. I check if that combination gets me a nice sum
3. If it does, I mark that up
4. Rinse and repeat.
So for input from first example {5, 4, 5, 6} in 2 groups:
5 4 5 6
-------
0 0 0 0
1 0 0 0
...
1 0 1 0 -> this one is fine, becouse 5 + 5 = 10; I mark it as used
1 1 1 0
...
0 1 0 1 -> another one works (4 + 6 = 10); Marked as used
So far i got myself 2 working groups which is equal to 2 groups - job done, it's a correct combination.
The real problem behind my idea is that I have no way of using some integer once I mark it as "used". This way in more complicated examples I would miss quite alot of correct groups. My question is, what is correct approach to this kind of problem? I've tried recursive approach and it didin't work any better (for the same reason)
Another idea I had is to permutate (std:next_permutate(...) for instance) integers from input each time I mark some group as used, but even on paper that looks silly.
I don't ask you to solve that problem for me, but if you could point any flaws in my reasoning that would be terrific.
Also, not a native speaker. So I'd like to apologise in advance if I butchered any sentence (I know i did).

Distinguishing the values of three int's

I have three integer variables, that can take only the values 0, 1 and 2. I want to distinguish what combination of all three numbers I have, ordering doesn't count. Let's say the variables are called x, y and z. Then x=1, y=0, z=0 and x=0, y=1, z=0 and x=0, y=0, z=1 are all the same number in this case, I will refer to this combination as 001.
Now there are a hundred ways how to do this, but I am asking for an elegant solution, be it only for educational purposes.
I thought about bitwise shifting 001 by the amount of the value:
001 << 0 = 1
001 << 1 = 2
001 << 2 = 4
But then the numbers 002 and 111 would both give 6.
The shift idea is good, but you need 2 bits to count to 3. So try shifting by twice the number of bits:
1 << (2*0) = 1
1 << (2*1) = 4
1 << (2*2) = 16
Add these for all 3 numbers, and the first 2 bits will count how many 0 you have, the second 2 bits will count how many 1 and the third 2 bits will count how many 2.
Edit although the result is 6 bit long (2 bits per number option 0,1,2), you only need the lowest 4 bits for a unique identifier - as if you know how many 0 and 1 you have, then the number of 2 is determined also.
So instead of doing
res = 1<<(2*x);
res+= 1<<(2*y);
res+= 1<<(2*z);
you can do
res = x*x;
res+= y*y;
res+= z*z;
because then
0*0 = 0 // doesn't change result. We don't count 0
1*1 = 1 // we count the number of 1 in the 2 lower bits
2*2 = 4 // we count the number of 2 in the 2 higher bits
hence using only 4 bits instead of 6.
When the number of distinct possibilities is small, using a lookup table could be used.
First, number all possible combinations of three digits, like this:
Combinations N Indexes
------------- - ------
000 0 0
001, 010, 100 1 1, 3, 9
002, 020, 200 2 2, 6, 18
011, 101, 110 3 4, 10, 12
012, 021, 102, 120, 201, 210 4 5, 7, 11, 15, 19, 21
022, 202, 220 5 8, 20, 24
111 6 13
112, 121, 211 7 14, 16, 22
122, 212, 221 8 17, 23, 25
222 9 26
The first column shows identical combinations; the second column shows the number of the combination (I assigned them arbitrarily); the third column shows the indexes of each combination, computed as 9*<first digit> + 3*<second digit> + <third digit>.
Next, build a look-up table for each of these ten combinations, using this expression as an index:
9*a + 3*b + c
where a, b, and c are the three numbers that you have. The table would look like this:
int lookup[] = {
0, 1, 2, 1, 3, 4, 2, 4, 5, 1
, 3, 4, 3, 6, 7, 4, 7, 8, 2, 4
, 5, 4, 7, 8, 5, 8, 9
};
This is a rewrite of the first table, with values at the indexes corresponding to the value in the column N. For example, combination number 1 is founds at indexes 1, 3, and 9; combination 2 is at indexes 2, 6, and 18, and so on.
To obtain the number of the combination, simply check
int combNumber = lookup[9*a + 3*b + c];
For such small numbers, it would be easiest to just check them individually, instead of trying to be fancy, eg:
bool hasZero = false;
bool hasOne = false;
bool hasTwo = false;
// given: char* number or char[] number...
for(int i = 0; i < 3; ++i)
{
switch (number[i])
{
case '0': hasZero = true; break;
case '1': hasOne = true; break;
case '2': hasTwo = true; break;
default: /* error! */ break;
}
}
If I understand you correctly, you have some sequence of numbers that can either be 1, 2, or 3, where the permutation of them doesn't matter (just the different combinations).
That being the case:
std::vector<int> v{1, 2, 3};
std::sort(v.begin(), v.end());
That will keep all of the different combinations properly aligned, and you could easily write a loop to test for equality.
Alternatively, you could use a std::array<int, N> (where N is the number of possible values - in this case 3).
std::array<int, 3> a;
Where you would set a[0] equal to the number of 1s you have, a[1] equal to the number of '2's, etc.
// if your string is 111
a[0] = 3;
// if your string is 110 or 011
a[0] = 2;
// if your string is 100 or 010 or 001
a[0] = 1;
// if your string is 120
a[0] = 1;
a[1] = 1;
// if your string is 123
a[0] = 1;
a[1] = 1;
a[2] = 1;
If you are looking to store it in a single 32-bit integer:
unsigned long x = 1; // number of 1's in your string
unsigned long y = 1; // number of 2's in your string
unsigned long z = 1; // number of 3's in your string
unsigned long result = x | y << 8 | z << 16;
To retrieve the number of each, you would do
unsigned long x = result & 0x000000FF;
unsigned long y = (result >> 8) & 0x000000FF;
unsigned long z = (result >> 16) & 0x000000FF;
This is very similar to what happens in the RBG macros.
int n[3]={0,0,0};
++n[x];
++n[y];
++n[z];
Now, in the n array, you have a unique ordered combination of values for each unique unordered combination of x,y,z.
For example, both x=1,y=0,z=0 and x=0,y=0,z=1 will give you n={2,1,0}