Reach John to top - c++

Problem Statement
John wants to climb up a stair of n steps. He can climb 1 or 2 steps at each move. John wants the number of moves to be a multiple of an integer m.
What is the minimal number of steps making him climb to the top of the stairs that satisfies his condition?
Input
The single line contains two space separated integers n, m (0 < n ≤ 10000, 1 < m ≤ 10).
Output
Print a single integer — the minimal steps being a multiple of m. If there is no way he can climb satisfying condition print  - 1 instead.
Sample test(s)
Input
10 2
Output
6
Input
3 5
Output
-1
Notes:
For the first sample, John could climb in 6 moves with following sequence of steps: {2, 2, 2, 2, 1, 1}.
For the second sample, there are only three valid sequence of steps {2, 1}, {1, 2}, {1, 1, 1} with 2, 2, and 3 steps respectively. All these numbers are not multiples of 5.
My code:
I have been trying to solve this problem ,so i thought of using nearest power of 2 less than the given number but got wrong answer
#include<stdio.h>
#include<math.h>
using namespace std;
int main(){
int n,m;
scanf("%d %d",&n,&m);
int x= pow (2,floor (log2(n)) );
int rem = n-x;
int ans = ((x/2)+rem);
if ( ans % m == 0 )
printf (" %d \n ",ans);
else
printf("-1\n");
return 0;
}

I personally don't see how the powers of two are useful at all.
Let's write a different algorithm in pseudocode first:
N = number of steps
M = desired multiple
# Excluding any idea of the multiple restraint, what is the maximum and minimum
# number of steps that John could take?
If number of steps is even:
minimum = N / 2
maximum = N
If number of steps is odd:
minimum = N / 2 + 1
maximum = N
# Maybe the minimum number of steps is perfect?
If minimum is a multiple of M:
Print minimum
# If it isn't, then we need to increase the number of steps up to a multiple of M.
# We then need to make sure that it didn't surpass the maximum number of steps.
Otherwise:
goal = minimum - (minimum % M) + M
if goal <= maximum:
Print goal
Otherwise:
Print -1
We can then convert this to code:
#include <cstdio>
int main(){
int n,m;
scanf("%d %d", &n, &m);
const int minimum = (n / 2) + (n % 2);
const int maximum = n;
if (minimum % m == 0) {
printf("%d\n", minimum);
return 0;
}
const int guess = minimum - (minimum % m) + m;
if (guess <= maximum) {
printf("%d\n", guess);
return 0;
}
printf("%d\n", -1);
return 0;
}
The key tool that I'm using here is that I know that John can scale the stairs in any combination of steps between (and including) [minimum, maximum]. How can we determine this?
We know the minimum number of steps is using 2 at a time as much as possible.
We know the maximum number of steps is using 1 at a time.
We know that if the current number of steps is not the maximum, then we can replace one of the steps (that must be using 2 at a time) and replace it with taking each step one at a time. That would increase the total number of steps by 1.

Related

Find the maximum score in a given array which can be found by either multiplying or adding

You are given an array A of K integers where Ai denotes page number of a book. To compute the score, you can either add or multiply the last digit of the page numbers.
You have to find the maximum score you can get. Since the score can be quite large, output the score modulo 1000000007
Note: The book contains N pages. Also, you need to follow the order in which the page numbers are given in the array. Initially, your score is 0.
Input format :
First line: Two space seperated integers N and K.
Next line: K space seperated integers denoting the page numbers.
Output format :
Output the maximum score you can get. Print it modulo 1000000007
Input Constraints:
1<=N<=10^9
1<=k<=10^9
SAMPLE INPUT:
50 3
2 35 23
SAMPLE OUTPUT:
30
Explanation
Last digit of all page numbers are: 2, 5, and 3.
Initial score = 0
We add 2 to the score which now becomes 2, multiply with 5 making the score 10, finally we multiply with 3 making the score 30 which is the maximum score.
Output 30 % (10^9+7) = 30.
I encountered the same question in an online test I gave recently.
Instead N was the no of books and K is the size of the array.Both were given as inputs.
Here is what I did:
int main() {
long long n, k;
long long m = 1000000007;
cin >> n >> k;
vector<int> arr(k, 0);
for(int i = 0; i < k; i++){
cin >> arr[i];
}
long long prod = 1;
long long sum = 0;
for(int i = 0; i < k; i++){
if(arr[k] < n){
prod = ((prod % m) * (arr[k] % 10)) % m;
sum = ((sum% m) + (arr[k] % 10)) % m;
prod = max(prod, sum);
sum = max(prod, sum);
}
}
cout << prod % m << endl;
return 0;
}
As you can see instead of handling for 1 and 2, I am checking for max value of the product and sum at every iteration and updating both the product and sum with it.
I got two test cases passed and rest gave wrong answer.Why is it so?
Here is the question link, if anyone needs to give it a try.
The Book Game Problem
The problem asks you to add OR multiply the last digit of the page numbers to make the resultant score as large as possible.
In this case, you should add when the digit is 0 or 1, and multiply otherwise.
For example,
Let the last digit sequence be
[1 0 2 5 8 1]
'score' is initialized to be 0.
add 1 (score: 1)
add 0 (score: 1)
multiply by 2 (score: 2)
multiply by 5 (score: 10)
multiply by 8 (score: 80)
add 1 (score: 81)
and before submitting the answer, you need to modulo it by 1000000007.
so,
score %= 1000000007
in your code, you are calculating the prod and the sum separately, which is not what you are asked to do. Also, you are sumbitting only the 'prod' value, while it is not always the maximum value (consider multiplying some number by 0)
And additionally, you are modulo-ing the intermediate values (prod and sum) which can lead to wrong answer. The modulo should not be used to calculate the score, but to truncate the result of the score digits.
So, my answer is,
Calculate the intermediate values and assign it to one variable named 'score' (don't separate the product and the sum), and modulo the value just before printing the output (don't modulo it every time you add or multiply)
Thanks.

Count ways to n'th stair(order does not matter)

There are N stairs, and a person standing at the bottom wants to reach the top. The person can climb either 1 stair or 2 stairs at a time. Count the number of ways, the person can reach the top (order does not matter).
Note: Order does not matter means for n=4 {1 2 1},{2 1 1},{1 1 2} are considered same.
https://practice.geeksforgeeks.org/problems/count-ways-to-nth-stairorder-does-not-matter/0
So I have been trying to solve this question and the problem I am facing is that I don't understand how do we solve questions like these where the order does not matter? I was able to solve the question when order mattered but I am not able to develop the logic to solve this.
This is the code I wrote for when order mattered
long int countWaysToStair(long int N)
{
if(N == 1 || N == 2)
return N;
long int dp[N+1];
dp[0] = 1;
dp[1] = 1;
dp[2] = 2;
for(int i=3;i<=N;i++)
{
dp[i] = dp[i-1] + dp[i-2];
}
return dp[N];
}
Input:
4
Expected Output:
3
My output:
5
Consider that you have N stairs. First of all you have to understand if N is odd or even.
If is even than it will be a multiple of 2: N = 2*S, where S is the number of pair of stairs.
Suppose N = 6 and S = 3. Your first solution is {2,2,2}. than you can change the first 2 stairs with 1 + 1 stairs and you have your second solution {1, 1, 2 ,2}.
Since order doesn't matter let's proceed with the next pair and we have our third solution {1, 1, 1, 1, 2} and then the fourth {1, 1, 1, 1, 1, 1}
Given N = 2*S the number of possible solutions are S + 1.
Now suppose N is odd and N = 2S + 1.
Let N = 7 and S = 3. Our solutions are {2,2,2,1}, {1,1,2,2,1}, {1,1,1,1,2,1} and {1,1,1,1,1,1,1}. Again, the number of solutions is given by S+1
Now your algorithm is pretty simple:
return N/2 + 1
The above answer is correct, but if you want to know how DP is used in this problem, look at this example:
jumps =[1,2]
Lets say that jump =1, so for any stair, the number of ways will always be equal to 1.
Now for jump=2, say for stair 8: no of ways will be (no of ways to reach 8 using 1 only)+(no of ways to reach 6 using both 1 and 2 because you can reach to 8 from 6 by just a jump of 2).
So the code will looks like:
for(int i=1; i<=n;i++)
dp[i]=1;
for(int i=2;i<=n;i++)
dp[i]=dp[i]+dp[i-2];
return dp[n];
Since the order does not matter, ways to reach at the Nth place would be:
1 way:
1,1,1,1,1....... 1
remaining n/2 ways:
1,1,1,1,1.......2
1,1,1,1,1.....2,2
.
.
.
1,2,2,2,2,2,2...2,2,2 or 2,2,2,2,2,2,2....2 (depends whether n is even or odd).
we can safely say that ways to reach at the Nth place would be n/2 +1

C++: What are some general ways to make code more efficient for use with large numbers?

Please when answering this question try to be as general as possible to help the wider community, rather than just specifically helping my issue (although helping my issue would be great too ;) )
I seem to be encountering this problem time and time again with the simple problems on Project Euler. Most commonly are the problems that require a computation of the prime numbers - these without fail always fail to terminate for numbers greater than about 60,000.
My most recent issue is with Problem 12:
The sequence of triangle numbers is generated by adding the natural numbers. So the 7th triangle number would be 1 + 2 + 3 + 4 + 5 + 6 + 7 = 28. The first ten terms would be:
1, 3, 6, 10, 15, 21, 28, 36, 45, 55, ...
Let us list the factors of the first seven triangle numbers:
1: 1
3: 1,3
6: 1,2,3,6
10: 1,2,5,10
15: 1,3,5,15
21: 1,3,7,21
28: 1,2,4,7,14,28
We can see that 28 is the first triangle number to have over five divisors.
What is the value of the first triangle number to have over five hundred divisors?
Here is my code:
#include <iostream>
#include <vector>
#include <cmath>
using namespace std;
int main() {
int numberOfDivisors = 500;
//I begin by looping from 1, with 1 being the 1st triangular number, 2 being the second, and so on.
for (long long int i = 1;; i++) {
long long int triangularNumber = (pow(i, 2) + i)/2
//Once I have the i-th triangular, I loop from 1 to itself, and add 1 to count each time I encounter a divisor, giving the total number of divisors for each triangular.
int count = 0;
for (long long int j = 1; j <= triangularNumber; j++) {
if (triangularNumber%j == 0) {
count++;
}
}
//If the number of divisors is 500, print out the triangular and break the code.
if (count == numberOfDivisors) {
cout << triangularNumber << endl;
break;
}
}
}
This code gives the correct answers for smaller numbers, and then either fails to terminate or takes an age to do so!
So firstly, what can I do with this specific problem to make my code more efficient?
Secondly, what are some general tips both for myself and other new C++ users for making code more efficient? (I.e. applying what we learn here in the future.)
Thanks!
The key problem is that your end condition is bad. You are supposed to stop when count > 500, but you look for an exact match of count == 500, therefore you are likely to blow past the correct answer without detecting it, and keep going ... maybe forever.
If you fix that, you can post it to code review. They might say something like this:
Break it down into separate functions for finding the next triangle number, and counting the factors of some number.
When you find the next triangle number, you execute pow. I perform a single addition.
For counting the number of factors in a number, a google search might help. (e.g. http://www.cut-the-knot.org/blue/NumberOfFactors.shtml ) You can build a list of prime numbers as you go, and use that to quickly find a prime factorization, from which you can compute the number of factors without actually counting them. When the numbers get big, that loop gets big.
Tldr: 76576500.
About your Euler problem, some math:
Preliminary 1:
Let's call the n-th triangle number T(n).
T(n) = 1 + 2 + 3 + ... + n = (n^2 + n)/2 (sometimes attributed to Gauss, sometimes someone else). It's not hard to figure it out:
1+2+3+4+5+6+7+8+9+10 =
(1+10) + (2+9) + (3+8) + (4+7) + (5+6) =
11 + 11 + 11 + 11 + 11 =
55 =
110 / 2 =
(10*10 + 10)/2
Because of its definition, it's trivial that T(n) + n + 1 = T(n+1), and that with a<b, T(a)<T(b) is true too.
Preliminary 2:
Let's call the divisor count D. D(1)=1, D(4)=3 (because 1 2 4).
For a n with c non-repeating prime factors (not just any divisors, but prime factors, eg. n = 42 = 2 * 3 * 7 has c = 3), D(n) is c^2: For each factor, there are two possibilites (use it or not). The 9 possibile divisors for the examples are: 1, 2, 3, 7, 6 (2*3), 14 (2*7), 21 (3*7), 42 (2*3*7).
More generally with repeating, the solution for D(n) is multiplying (Power+1) together. Example 126 = 2^1 * 3^2 * 7^1: Because it has two 3, the question is no "use 3 or not", but "use it 1 time, 2 times or not" (if one time, the "first" or "second" 3 doesn't change the result). With the powers 1 2 1, D(126) is 2*3*2=12.
Preliminary 3:
A number n and n+1 can't have any common prime factor x other than 1 (technically, 1 isn't a prime, but whatever). Because if both n/x and (n+1)/x are natural numbers, (n+1)/x - n/x has to be too, but that is 1/x.
Back to Gauss: If we know the prime factors for a certain n and n+1 (needed to calculate D(n) and D(n+1)), calculating D(T(n)) is easy. T(N) = (n^2 + n) / 2 = n * (n+1) / 2. As n and n+1 don't have common prime factors, just throwing together all factors and removing one 2 because of the "/2" is enough. Example: n is 7, factors 7 = 7^1, and n+1 = 8 = 2^3. Together it's 2^3 * 7^1, removing one 2 is 2^2 * 7^1. Powers are 2 1, D(T(7)) = 3*2 = 6. To check, T(7) = 28 = 2^2 * 7^1, the 6 possible divisors are 1 2 4 7 14 28.
What the program could do now: Loop through all n from 1 to something, always factorize n and n+1, use this to get the divisor count of the n-th triangle number, and check if it is >500.
There's just the tiny problem that there are no efficient algorithms for prime factorization. But for somewhat small numbers, todays computers are still fast enough, and keeping all found factorizations from 1 to n helps too for finding the next one (for n+1). Potential problem 2 are too large numbers for longlong, but again, this is no problem here (as can be found out with trying).
With the described process and the program below, I got
the 12375th triangle number is 76576500 and has 576 divisors
#include <iostream>
#include <vector>
#include <cstdint>
using namespace std;
const int limit = 500;
vector<uint64_t> knownPrimes; //2 3 5 7...
//eg. [14] is 1 0 0 1 ... because 14 = 2^1 * 3^0 * 5^0 * 7^1
vector<vector<uint32_t>> knownFactorizations;
void init()
{
knownPrimes.push_back(2);
knownFactorizations.push_back(vector<uint32_t>(1, 0)); //factors for 0 (dummy)
knownFactorizations.push_back(vector<uint32_t>(1, 0)); //factors for 1 (dummy)
knownFactorizations.push_back(vector<uint32_t>(1, 1)); //factors for 2
}
void addAnotherFactorization()
{
uint64_t number = knownFactorizations.size();
size_t len = knownPrimes.size();
for(size_t i = 0; i < len; i++)
{
if(!(number % knownPrimes[i]))
{
//dividing with a prime gets a already factorized number
knownFactorizations.push_back(knownFactorizations[number / knownPrimes[i]]);
knownFactorizations[number][i]++;
return;
}
}
//if this failed, number is a newly found prime
//because a) it has no known prime factors, so it must have others
//and b) if it is not a prime itself, then it's factors should've been
//found already (because they are smaller than the number itself)
knownPrimes.push_back(number);
len = knownFactorizations.size();
for(size_t s = 0; s < len; s++)
{
knownFactorizations[s].push_back(0);
}
knownFactorizations.push_back(knownFactorizations[0]);
knownFactorizations[number][knownPrimes.size() - 1]++;
}
uint64_t calculateDivisorCountOfN(uint64_t number)
{
//factors for number must be known
uint64_t res = 1;
size_t len = knownFactorizations[number].size();
for(size_t s = 0; s < len; s++)
{
if(knownFactorizations[number][s])
{
res *= (knownFactorizations[number][s] + 1);
}
}
return res;
}
uint64_t calculateDivisorCountOfTN(uint64_t number)
{
//factors for number and number+1 must be known
uint64_t res = 1;
size_t len = knownFactorizations[number].size();
vector<uint32_t> tmp(len, 0);
size_t s;
for(s = 0; s < len; s++)
{
tmp[s] = knownFactorizations[number][s]
+ knownFactorizations[number+1][s];
}
//remove /2
tmp[0]--;
for(s = 0; s < len; s++)
{
if(tmp[s])
{
res *= (tmp[s] + 1);
}
}
return res;
}
int main()
{
init();
uint64_t number = knownFactorizations.size() - 2;
uint64_t DTn = 0;
while(DTn <= limit)
{
number++;
addAnotherFactorization();
DTn = calculateDivisorCountOfTN(number);
}
uint64_t tn;
if(number % 2) tn = ((number+1)/2)*number;
else tn = (number/2)*(number+1);
cout << "the " << number << "th triangle number is "
<< tn << " and has " << DTn << " divisors" << endl;
return 0;
}
About your general question about speed:
1) Algorithms.
How to know them? For (relatively) simple problems, either reading a book/Wikipedia/etc. or figuring it out if you can. For harder stuff, learning more basic things and gaining experience is necessary before it's even possible to understand them, eg. studying CS and/or maths ... number theory helps a lot for your Euler problem. (It will help less to understand how a MP3 file is compressed ... there are many areas, it's not possible to know everything.).
2a) Automated compiler optimizations of frequently used code parts / patterns
2b) Manual timing what program parts are the slowest, and (when not replacing it with another algorithm) changing it in a way that eg. requires less data send to slow devices (HDD, hetwork...), less RAM memory access, less CPU cycles, works better together with OS scheduler and memory management strategies, uses the CPU pipeline/caches better etc.etc. ... this is both education and experience (and a big topic).
And because long variables have a limited size, sometimes it is necessary to use custom types that use eg. a byte array to store a single digit in each byte. That way, it's possible to use the whole RAM for a single number if you want to, but the downside is you/someone has to reimplement stuff like addition and so on for this kind of number storage. (Of course, libs for that exist already, without writing everything from scratch).
Btw., pow is a floating point function and may get you inaccurate results. It's not appropriate to use it in this case.

Given an integer n, return the number of ways it can be represented as a sum of 1s and 2s

For example:
5 = 1+1+1+1+1
5 = 1+1+1+2
5 = 1+1+2+1
5 = 1+2+1+1
5 = 2+1+1+1
5 = 1+2+2
5 = 2+2+1
5 = 2+1+2
Can anyone give a hint for a pseudo code on how this can be done please.
Honestly have no clue how to even start.
Also this looks like an exponential problem can it be done in linear time?
Thank you.
In the example you have provided order of addends is important. (See the last two lines in your example). With this in mind, the answer seems to be related to Fibonacci numbers. Let's F(n) be the ways n can be written as 1s and 2s. Then the last addened is either 1 or 2. So F(n) = F(n-1) + F(n-2). These are the initial values:
F(1) = 1 (1 = 1)
F(2) = 2 (2 = 1 + 1, 2 = 2)
This is actually the (n+1)th Fibonacci number. Here's why:
Let's call f(n) the number of ways to represent n. If you have n, then you can represent it as (n-1)+1 or (n-2)+2. Thus the ways to represent it are the number of ways to represent it is f(n-1) + f(n-2). This is the same recurrence as the Fibonacci numbers. Furthermore, we see if n=1 then we have 1 way, and if n=2 then we have 2 ways. Thus the (n+1)th Fibonacci number is your answer. There are algorithms out there to compute enormous Fibonacci numbers very quickly.
Permutations
If we want to know how many possible orderings there are in some set of size n without repetition (i.e., elements selected are removed from the available pool), the factorial of n (or n!) gives the answer:
double factorial(int n)
{
if (n <= 0)
return 1;
else
return n * factorial(n - 1);
}
Note: This also has an iterative solution and can even be approximated using the gamma function:
std::round(std::tgamma(n + 1)); // where n >= 0
The problem set starts with all 1s. Each time the set changes, two 1s are replaced by one 2. We want to find the number of ways k items (the 2s) can be arranged in a set of size n. We can query the number of possible permutations by computing:
double permutation(int n, int k)
{
return factorial(n) / factorial(n - k);
}
However, this is not quite the result we want. The problem is, permutations consider ordering, e.g., the sequence 2,2,2 would count as six distinct variations.
Combinations
These are essentially permutations which ignore ordering. Since the order no longer matters, many permutations are redundant. Redundancy per permutation can be found by computing k!. Dividing the number of permutations by this value gives the number of combinations:
Note: This is known as the binomial coefficient and should be read as "n choose k."
double combination(int n, int k)
{
return permutation(n, k) / factorial(k);
}
int solve(int n)
{
double result = 0;
if (n > 0) {
for ( int k = 0; k <= n; k += 1, n -= 1 )
result += combination(n, k);
}
return std::round(result);
}
This is a general solution. For example, if the problem were instead to find the number of ways an integer can be represented as a sum of 1s and 3s, we would only need to adjust the decrement of the set size (n-2) at each iteration.
Fibonacci numbers
The reason the solution using Fibonacci numbers works, has to do with their relation to the binomial coefficients. The binomial coefficients can be arranged to form Pascal's triangle, which when stored as a lower-triangular matrix, can be accessed using n and k as row/column indices to locate the element equal to combination(n,k).
The pattern of n and k as they change over the lifetime of solve, plot a diagonal when viewed as coordinates on a 2-D grid. The result of summing values along a diagonal of Pascal's triangle is a Fibonacci number. If the pattern changes (e.g., when finding sums of 1s and 3s), this will no longer be the case and this solution will fail.
Interestingly, Fibonacci numbers can be computed in constant time. Which means we can solve this problem in constant time simply by finding the (n+1)th Fibonacci number.
int fibonacci(int n)
{
constexpr double SQRT_5 = std::sqrt(5.0);
constexpr double GOLDEN_RATIO = (SQRT_5 + 1.0) / 2.0;
return std::round(std::pow(GOLDEN_RATIO, n) / SQRT_5);
}
int solve(int n)
{
if (n > 0)
return fibonacci(n + 1);
return 0;
}
As a final note, the numbers generated by both the factorial and fibonacci functions can be extremely large. Therefore, a large-maths library may be needed if n will be large.
Here is the code using backtracking which solves your problem. At each step, while remembering the numbers used to get the sum so far(using vectors here), first make a copy of them, first subtract 1 from n and add it to the copy then recur with n-1 and the copy of the vector with 1 added to it and print when n==0. then return and repeat the same for 2, which essentially is backtracking.
#include <stdio.h>
#include <vector>
#include <iostream>
using namespace std;
int n;
void print(vector<int> vect){
cout << n <<" = ";
for(int i=0;i<vect.size(); ++i){
if(i>0)
cout <<"+" <<vect[i];
else cout << vect[i];
}
cout << endl;
}
void gen(int n, vector<int> vect){
if(!n)
print(vect);
else{
for(int i=1;i<=2;++i){
if(n-i>=0){
std::vector<int> vect2(vect);
vect2.push_back(i);
gen(n-i,vect2);
}
}
}
}
int main(){
scanf("%d",&n);
vector<int> vect;
gen(n,vect);
}
This problem can be easily visualized as follows:
Consider a frog, that is present in front of a stairway. It needs to reach the n-th stair, but he can only jump 1 or 2 steps on the stairway at a time. Find the number of ways in which he can reach the n-th stair?
Let T(n) denote the number of ways to reach the n-th stair.
So, T(1) = 1 and T(2) = 2(2 one-step jumps or 1 two-step jump, so 2 ways)
In order to reach the n-th stair, we already know the number of ways to reach the (n-1)th stair and the (n-2)th stair.
So, once can simple reach the n-th stair by a 1-step jump from (n-1)th stair or a 2-step jump from (n-2)th step...
Hence, T(n) = T(n-1) + T(n-2)
Hope it helps!!!

Algorithm to determine coin combinations

I was recently faced with a prompt for a programming algorithm that I had no idea what to do for. I've never really written an algorithm before, so I'm kind of a newb at this.
The problem said to write a program to determine all of the possible coin combinations for a cashier to give back as change based on coin values and number of coins. For example, there could be a currency with 4 coins: a 2 cent, 6 cent, 10 cent and 15 cent coins. How many combinations of this that equal 50 cents are there?
The language I'm using is C++, although that doesn't really matter too much.
edit: This is a more specific programming question, but how would I analyze a string in C++ to get the coin values? They were given in a text document like
4 2 6 10 15 50
(where the numbers in this case correspond to the example I gave)
This problem is well known as coin change problem. Please check this and this for details. Also if you Google "coin change" or "dynamic programming coin change" then you will get many other useful resources.
Here's a recursive solution in Java:
// Usage: int[] denoms = new int[] { 1, 2, 5, 10, 20, 50, 100, 200 };
// System.out.println(ways(denoms, denoms.length, 200));
public static int ways(int denoms[], int index, int capacity) {
if (capacity == 0) return 1;
if (capacity < 0 || index <= 0 ) return 0;
int withoutItem = ways(denoms, index - 1, capacity);
int withItem = ways(denoms, index, capacity - denoms[index - 1]);
return withoutItem + withItem;
}
This seems somewhat like a Partition, except that you don't use all integers in 1:50. It also seems similar to bin packing problem with slight differences:
Wikipedia: Partition (Number Theory)
Wikipedia: Bin packing problem
Wolfram Mathworld: Partiton
Actually, after thinking about it, it's an ILP, and thus NP-hard.
I'd suggest some dynamic programming appyroach. Basically, you'd define a value "remainder" and set it to whatever your goal was (say, 50). Then, at every step, you'd do the following:
Figure out what the largest coin that can fit within the remainder
Consider what would happen if you (A) included that coin or (B) did not include that coin.
For each scenario, recurse.
So if remainder was 50 and the largest coins were worth 25 and 10, you'd branch into two scenarios:
1. Remainder = 25, Coinset = 1x25
2. Remainder = 50, Coinset = 0x25
The next step (for each branch) might look like:
1-1. Remainder = 0, Coinset = 2x25 <-- Note: Remainder=0 => Logged
1-2. Remainder = 25, Coinset = 1x25
2-1. Remainder = 40, Coinset = 0x25, 1x10
2-2. Remainder = 50, Coinset = 0x25, 0x10
Each branch would split into two branches unless:
the remainder was 0 (in which case you would log it)
the remainder was less than the smallest coin (in which case you would discard it)
there were no more coins left (in which case you would discard it since remainder != 0)
If you have 15, 10, 6 and 2 cents coins and you need to find how many distinct ways are there to arrive to 50 you can
count how many distinct ways you have to reach 50 using only 10, 6 and 2
count how many distinct ways you have to reach 50-15 using only 10, 6 and 2
count how many distinct ways you have to reach 50-15*2 using only 10, 6 and 2
count how many distinct ways you have to reach 50-15*3 using only 10, 6 and 2
Sum up all these results that are of course distinct (in the first I used no 15c coins, in the second I used one, in the third two and in the fourth three).
So you basically can split the problem in smaller problems (possibly smaller amount and fewer coins). When you have just one coin type the answer is of course trivial (either you cannot reach the prescribed amount exactly or you can in the only possible way).
Moreover you can also avoid repeating the same computation by using memoization, for example the number of ways of reach 20 using only [6, 2] doesn't depend if the already paid 30 have been reached using 15+15 or 10+10+10, so the result of the smaller problem (20, [6, 2]) can
be stored and reused.
In Python the implementation of this idea is the following
cache = {}
def howmany(amount, coins):
prob = tuple([amount] + coins) # Problem signature
if prob in cache:
return cache[prob] # We computed this before
if amount == 0:
return 1 # It's always possible to give an exact change of 0 cents
if len(coins) == 1:
if amount % coins[0] == 0:
return 1 # We can match prescribed amount with this coin
else:
return 0 # It's impossible
total = 0
n = 0
while n * coins[0] <= amount:
total += howmany(amount - n * coins[0], coins[1:])
n += 1
cache[prob] = total # Store in cache to avoid repeating this computation
return total
print howmany(50, [15, 10, 6, 2])
As for the second part of your question, suppose you have that string in the file coins.txt:
#include <fstream>
#include <vector>
#include <algorithm>
#include <iterator>
int main() {
std::ifstream coins_file("coins.txt");
std::vector<int> coins;
std::copy(std::istream_iterator<int>(coins_file),
std::istream_iterator<int>(),
std::back_inserter(coins));
}
Now the vector coins will contain the possible coin values.
For such a small number of coins you can write a simple brute force solution.
Something like this:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> v;
int solve(int total, int * coins, int lastI)
{
if (total == 50)
{
for (int i = 0; i < v.size(); i++)
{
cout << v.at(i) << ' ';
}
cout << "\n";
return 1;
}
if (total > 50) return 0;
int sum = 0;
for (int i = lastI; i < 6; i++)
{
v.push_back(coins[i]);
sum += solve(total + coins[i], coins, i);
v.pop_back();
}
return sum;
}
int main()
{
int coins[6] = {2, 4, 6, 10, 15, 50};
cout << solve(0, coins, 0) << endl;
}
A very dirty brute force solution that prints all possible combinations.
This is a very famous problem, so try reading about better solutions others have provided.
One rather dumb approach is the following. You build a mapping "coin with value X is used Y times" and then enumerate all possible combinations and only select those which total the desired sum. Obviously for each value X you have to check Y ranging from 0 up to the desired sum. This will be rather slow, but will solve your task.
It's very similar to the knapsack problem
You basically have to solve the following equation: 50 = a*4 + b*6 + c*10 + d*15, where the unknowns are a,b,c,d. You can compute for instance d = (50 - a*4 - b*6 - c*10)/15 and so on for each variable. Then, you start giving d all the possible values (you should start with the one that has the least possible values, here d): 0,1,2,3,4 and than start giving c all the possible values depending on the current value of d and so on.
Sort the List backwards: [15 10 6 4 2]
Now a solution for 50 ct can contain 15 ct or not.
So the number of solutions is the number of solutions for 50 ct using [10 6 4 2] (no longer considering 15 ct coins) plus the number of solutions for 35 ct (=50ct - 15ct) using [15 10 6 4 2]. Repeat the process for both sub-problems.
An algorithm is a procedure for solving a problem, it doesn't have to be in any particular language.
First work out the inputs:
typedef int CoinValue;
set<CoinValue> coinTypes;
int value;
and the outputs:
set< map<CoinValue, int> > results;
Solve for the simplest case you can think of first:
coinTypes = { 1 }; // only one type of coin worth 1 cent
value = 51;
the result should be:
results = { [1 : 51] }; // only one solution, 51 - 1 cent coins
How would you solve the above?
How about this:
coinTypes = { 2 };
value = 51;
results = { }; // there is no solution
what about this?
coinTypes = { 1, 2 };
value = { 4 };
results = { [2: 2], [2: 1, 1: 2], [1: 4] }; // the order I put the solutions in is a hint to how to do the algorithm.
Recursive solution based on algorithmist.com resource in Scala:
def countChange(money: Int, coins: List[Int]): Int = {
if (money < 0 || coins.isEmpty) 0
else if (money == 0) 1
else countChange(money, coins.tail) + countChange(money - coins.head, coins)
}
Another Python version:
def change(coins, money):
return (
change(coins[:-1], money) +
change(coins, money - coins[-1])
if money > 0 and coins
else money == 0
)