Dynamic programming idiom for combinations - algorithm

Consider the problem in which you have a value of N and you need to calculate how many ways you can sum up to N dollars using [1,2,5,10,20,50,100] Dollar bills.
Consider the classic DP solution:
C = [1,2,5,10,20,50,100]
def comb(p):
if p==0:
return 1
c = 0
for x in C:
if x <= p:
c += comb(p-x)
return c
It does not take into effect the order of the summed parts. For example, comb(4) will yield 5 results: [1,1,1,1],[2,1,1],[1,2,1],[1,1,2],[2,2] whereas there are actually 3 results ([2,1,1],[1,2,1],[1,1,2] are all the same).
What is the DP idiom for calculating this problem? (non-elegant solutions such as generating all possible solutions and removing duplicates are not welcome)

Not sure about any DP idioms, but you could try using Generating Functions.
What we need to find is the coefficient of x^N in
(1 + x + x^2 + ...)(1+x^5 + x^10 + ...)(1+x^10 + x^20 + ...)...(1+x^100 + x^200 + ...)
(number of times 1 appears*1 + number of times 5 appears * 5 + ... )
Which is same as the reciprocal of
(1-x)(1-x^5)(1-x^10)(1-x^20)(1-x^50)(1-x^100).
You can now factorize each in terms of products of roots of unity, split the reciprocal in terms of Partial Fractions (which is a one time step) and find the coefficient of x^N in each (which will be of the form Polynomial/(x-w)) and add them up.
You could do some DP in calculating the roots of unity.

You should not go from begining each time, but at max from were you came from at each depth.
That mean that you have to pass two parameters, start and remaining total.
C = [1,5,10,20,50,100]
def comb(p,start=0):
if p==0:
return 1
c = 0
for i,x in enumerate(C[start:]):
if x <= p:
c += comb(p-x,i+start)
return c
or equivalent (it might be more readable)
C = [1,5,10,20,50,100]
def comb(p,start=0):
if p==0:
return 1
c = 0
for i in range(start,len(C)):
x=C[i]
if x <= p:
c += comb(p-x,i)
return c

Terminology: What you are looking for is the "integer partitions"
into prescibed parts (you should replace "combinations" in the title).
Ignoring the "dynamic programming" part of the question, a routine
for your problem is given in the first section of chapter 16
("Integer partitions", p.339ff) of the fxtbook, online at
http://www.jjj.de/fxt/#fxtbook

Related

Product of consecutive numbers f(n) = n(n-1)(n-2)(n-3)(n- ...) find the value of n

Is there a way to find programmatically the consecutive natural numbers?
On the Internet I found some examples using either factorization or polynomial solving.
Example 1
For n(n−1)(n−2)(n−3) = 840
n = 7, -4, (3+i√111)/2, (3-i√111)/2
Example 2
For n(n−1)(n−2)(n−3) = 1680
n = 8, −5, (3+i√159)/2, (3-i√159)/2
Both of those examples give 4 results (because both are 4th degree equations), but for my use case I'm only interested in the natural value. Also the solution should work for any sequences size of consecutive numbers, in other words, n(n−1)(n−2)(n−3)(n−4)...
The solution can be an algorithm or come from any open math library. The parameters passed to the algorithm will be the product and the degree (sequences size), like for those two examples the product is 840 or 1640 and the degree is 4 for both.
Thank you
If you're interested only in natural "n" solution then this reasoning may help:
Let's say n(n-1)(n-2)(n-3)...(n-k) = A
The solution n=sthen verifies:
remainder of A/s = 0
remainder of A/(s-1) = 0
remainder of A/(s-2) = 0
and so on
Now, we see that s is in the order of t= A^(1/k) : A is similar to s*s*s*s*s... k times. So we can start with v= (t-k) and finish at v= t+1. The solution will be between these two values.
So the algo may be, roughly:
s= 0
t= (int) (A^(1/k)) //this truncation by leave out t= v+1. Fix it in the loop
theLoop:
for (v= t-k to v= t+1, step= +1)
{ i=0
while ( i <= k )
{ if (A % (v - k + i) > 0 ) // % operator to find the reminder
continue at theLoop
i= i+1
}
// All are valid divisors, solution found
s = v
break
}
if (s==0)
not natural solution
Assuming that:
n is an integer, and
n > 0, and
k < n
Then approximately:
n = FLOOR( (product ** (1/(k+1)) + (k+1)/2 )
The only cases I have found where this isn't exactly right is when k is very close to n. You can of course check it by back-calculating the product and see if it matches. If not, it almost certainly is only 1 or 2 in higher than this estimate, so just keep incrementing n until the product matches. (I can write this up in pseudocode if you need it)

find more indipendent seed value for a 64 bit LCG (MMIX (by Knuth))

I'm using a 64 bit LCG (MMIX (by Knuth)). It generate a certain block of random numbers inside my code, which use them to perform some operations. My code works in single core and I would like to parallelize the work to reduce the execution time.
Before start thinking to more advanced methods in this sense I'd like to simply execute more identical codes in parallel (in fact the code repeats the same task over a certain numbers of indipendent simulation, so I can simply split the number of simulation between more identical codes and run them in parallel).
My only problem now is to find a seed for each code; in particular, to avoid the possibility of unwanted non trivial correlation between data generated in different codes, I have to be sure that the random number generated in the various codes don't overlap. To do so, starting from a certain seed in the first code I have to find a way to find a value (the next seed) very distant not in absolute value but in the pseudo-random sequence (so, such that, to go from the first to the second seed, I need a huge number of steps of LCG).
My first attempt was this:
starting from the LCG relation between 2 consecutive numbers generated in the sequence
So, in principle, I could calculate the above relation with, say, n = 2^40 and I_0 equal to the value of the first seed, and obtain a new seed distant 2^40 steps in the random CLG sequence from the first one.
The problem is that, doing so, I necessary go in overflow calculating a^n. In fact for MMIX (by Knuth) a~2^62 and i use unsigned long long int (64 bit). Note that the only problem here is the fraction in the above relation. If there only were sum and multiplication I could ignore the overflow problem due to the following modular properties (in fact I'm using 2^64 as c (64 bit generator)):
So, starting from a certain value (first seed), how can I find a second one distant a huge number of step in the LC pseudo-random sequence?
[EDIT]
r3mainer solution is perfectly suited for python codes. I'm trying now to implement it in c using unsigned __int128 variables. I have only one problem: in principle I should compute:
Say, for simplicity, I want to compute:
with n = 2^40 and c(a-1)~2^126. I proceed with a cycle.Starting with temp = a, in each iteration I compute temp = temp*temp, then I compute temp%c(a-1). The problem is in the second step (temp = temp*temp). temp in fact could be, in principle any number < c(a-1)~2^126. If temp is a big number, say > 2^64, I'll go in overflow, reaching 2^128 - 1, before the next module operation. So is there a way to avoid it? For now the only solution I see is to perform each multiplication with a loop over bit, as suggested here: c code: prevent overflow in modular operation with huge modules (modules near the overflow treshold)
Is there another way to perform module operation during the multiplication?
(note that being c = 2^64, with mod(c) operation I don't have the same problem because the overflow point (for ull int variables) coincides with the module)
Any LCG of the form x[n+1] = (x[n] * a + c) % m can be skipped to an arbitrary position very quickly.
Starting with a seed value of zero, the first few iterations of the LCG will give you this sequence:
x₀ = 0
x₁ = c % m
x₂ = (c(a + 1)) % m
x₃ = (c(a² + a + 1)) % m
x₄ = (c(a³ + a² + a + 1)) % m
It's pretty easy to see that each term is actually the sum of a geometric series, which can be calculated with a simple formula:
x_n = (c(a^{n-1} + a^{n-2} + ... + a + 1)) % m
= (c * (a^n - 1) / (a - 1)) % m
The (a^n - 1) term can be calculated quickly by modular exponentiation, but dividing by (a-1) is a bit tricky because (a-1) and m are both even (i.e., not coprime), so we can't calculate the modular multiplicative inverse of (a-1) mod m directly.
Instead, calculate (a^n-1) mod m*(a-1), then perform a straightforward (non-modular) division of the result by a-1. In Python, the calculation would go something like this:
def lcg_skip(m, a, c, n):
# Calculate nth term of LCG sequence with parameters m (modulus),
# a (multiplier) and c (increment), assuming an initial seed of zero
a1 = a - 1
t = pow(a, n, m * a1) - 1
t = (t * c // a1) % m
return t
def test(nsteps):
m = 2**64
a = 6364136223846793005
c = 1442695040888963407
#
print("Calculating by brute force:")
seed = 0
for i in range(nsteps):
seed = (seed * a + c) % m
print(seed)
#
print("Calculating by fast method:")
# Calculate nth term by modular exponentiation
print(lcg_skip(m, a, c, nsteps))
test(1000000)
So to create LCGs with non-overlapping output sequences, all you would need to do is use initial seed values generated by lcg_skip() with values of n that are far enough apart.
Well, for LCG it is known property to jump forward and backward in O(log2(N)) time where N is the distance between jump points, paper by F. Brown, "Random Number Generation with Arbitrary Stride," Trans. Am. Nucl. Soc. (Nov. 1994).
It means if you have LCG parameters (a, c) satisfying Hull–Dobell Theorem, then whole period would be 264 numbers before repeating themself, and say for Nt number pf threads you make jump distance of 264 / Nt, and all threads start with the same seed and just jump after initializing LCG by (264 / Nt)*threadId, and you would be completely safe from RNG correlations due to sequences overlap.
For simplest case of common 64 unsigned modulo math, as implemented in NumPy, code below should work fine
import numpy as np
class LCG(object):
UZERO: np.uint64 = np.uint64(0)
UONE : np.uint64 = np.uint64(1)
def __init__(self, seed: np.uint64, a: np.uint64, c: np.uint64) -> None:
self._seed: np.uint64 = np.uint64(seed)
self._a : np.uint64 = np.uint64(a)
self._c : np.uint64 = np.uint64(c)
def next(self) -> np.uint64:
self._seed = self._a * self._seed + self._c
return self._seed
def seed(self) -> np.uint64:
return self._seed
def set_seed(self, seed: np.uint64) -> np.uint64:
self._seed = seed
def skip(self, ns: np.int64) -> None:
"""
Signed argument - skip forward as well as backward
The algorithm here to determine the parameters used to skip ahead is
described in the paper F. Brown, "Random Number Generation with Arbitrary Stride,"
Trans. Am. Nucl. Soc. (Nov. 1994). This algorithm is able to skip ahead in
O(log2(N)) operations instead of O(N). It computes parameters
A and C which can then be used to find x_N = A*x_0 + C mod 2^M.
"""
nskip: np.uint64 = np.uint64(ns)
a: np.uint64 = self._a
c: np.uint64 = self._c
a_next: np.uint64 = LCG.UONE
c_next: np.uint64 = LCG.UZERO
while nskip > LCG.UZERO:
if (nskip & LCG.UONE) != LCG.UZERO:
a_next = a_next * a
c_next = c_next * a + c
c = (a + LCG.UONE) * c
a = a * a
nskip = nskip >> LCG.UONE
self._seed = a_next * self._seed + c_next
#%%
np.seterr(over='ignore')
seed = np.uint64(1)
rng64 = LCG(seed, np.uint64(6364136223846793005), np.uint64(1))
print(rng64.next())
print(rng64.next())
print(rng64.next())
#%%
rng64.skip(-3) # back by 3
print(rng64.next())
print(rng64.next())
print(rng64.next())
rng64.skip(-3) # back by 3
rng64.skip(2) # forward by 2
print(rng64.next())
Tested in Python 3.9.1, x64 Win 10

What's an algorithm to get a number closest to a constant that can evenly (within a margin) divide into two other constants?

So let't say I have numbers A=1483 and B = 635. My X=100.0
Let's say my allowed MARGIN is 10.0
What's the best way to get the closest number to X (can be floating point) that can divide into A and B with a remainder that is less that MARGIN?
For an answer K. A % K <= MARGIN, B % K <= MARGIN, with K being as close to X as possible, for example |K - X| < 100
Let's try and write the problem with mathematical notations.
What you have is Euclidean divisions:
A = Q1*X + R1
B = Q2*X + R2
You want to find the minimal |x| such that
A = Q1'*(X+x) + R1' , |R1'| <= M
B = Q2'*(X+x) + R2' , |R2'| <= M
To help you finding such x, you have relations like:
A = Q1*(X+x) + R1-Q1*x
B = Q2*(X+x) + R2-Q2*x
From here, you should first concentrate on how to solve the example you gave, then try and generalize.
1483 = 14*100 + 83 = 15*100 - 17
635 = 6*100 + 35 = 7*100 - 65
Should you can take x > 0 in order to reduce R2 (35) down to 10, or x < 0 to increase R1 (-17) up to -10?
In the first case, x should be in interval [25/6 , 45/6] to bring |R2'| <= M, but at the same time it must be in interval [73/14 , 93/14] to bring |R1'| <= M.
Do these intervals overlap?
if yes you have a solution.
if no, then you have to try further (decrement quotients Q1' and/or Q2')
Just check with any decent interpreter (Squeak/Pharo Smalltalk here)
{25/6 . 45/6. 73/14 . 93/14} sorted
= {(25/6) . (73/14) . (93/14) . (15/2)}
So they overlap, starting at x=73/14.
But maybe you would get a closer x in the other direction?
I have not given an algorithm, just a clue, up to you to continue. But you see that increment does not have to be random (like 0.001).
For now the best way I have found is a brute force method by finding the GCD of A and B and decrease by a small interval (0.001) and find the smallest c(K) where K >= X and c(x) = A % x + B % x
If I had found a way to differentiate c(x) correctly, I would've liked to find its gradient and use gradient descent to find the most optimal value without brute force.

Is this a correct recurrence relationship I've found for the coin change challenge?

I'm trying to solve the "coin change problem" and I think I've come up with a recursive solution but I want to verify.
As a a example, let's suppose we have pennies, nickles and dimes and are trying to make change for 22 cents.
C = { 1 = penny, nickle = 5, dime = 10 }
K = 22
Then the number of ways to make change is
f(C,N) = f({1,5,10},22)
=
(# of ways to make change with 0 dimes)
+ (# of ways to make change with 1 dimes)
+ (# of ways to make change with 2 dimes)
= f(C\{dime},22-0*10) + f(C\{dime},22-1*10) + f(C\{dime},22-2*10)
= f({1,5},22) + f({1,5},12) + f({1,5},2)
and
f({1,5},22)
= f({1,5}\{nickle},22-0*5) + f({1,5}\{nickle},22-1*5) + f({1,5}\{nickle},22-2*5) + f({1,5}\{nickle},22-3*5) + f({1,5}\{nickle},22-4*5)
= f({1},22) + f({1},17) + f({1},12) + f({1},7) + f({1},2)
= 5
and so forth.
In other words, my algorithm is like
let f(C,K) be the number of ways to make change for K cents with coins C
and have the following implementation
if(C is empty or K=0)
return 0
sum = 0
m = C.PopLargest()
A = {0, 1, ..., K / m}
for(i in A)
sum += f(C,K-i*m)
return sum
If there any flaw in that?
Would be linear time, I think.
Rethink about your base cases:
1. What if K < 0 ? Then no solution exists. i.e. No of ways = 0.
2. When K = 0, so there is 1 way to make changes and which is to consider zero elements from array of coin-types.
3. When coin array is empty then No of ways = 0.
Rest of the logic is correct. But your perception that the algorithm is Linear is absolutely wrong.
Lets compute the complexity:
Popping largest element is O(C.length). However this step can be
optimised if you consider sorting the whole array in the beginning.
Your for Loop works O(K/C.max) times in every call and in every iteration it is calling the function recursively.
So if you write the recurrence for it. then it should be something like:
T(N) = O(N) + K*T(N-1)
And this is going to be exponential in terms of N (Size of array).
In case you are looking for improvement, i would suggest you to use Dynamic Programming.

finding pythagorean triples (a,b,c) with a <=200

In my previous post on this subject i have made little progress (not blaming anyone except myself!) so i'll try to approach my problem statement differently.
how do i go about writing the algorithm to generate a list of primitive triples?
all i have to start with is:
a) the basic theorem: a^2 + b^2 = c^2
b) the fact that the small sides of the triple (a and b) need to be smaller than 'n'
(note: 'n' <= 200 for this purpose)
How do i go about building my loops? Do i need 2 or 3 loops?
a professor gave me some hints but alas i am still lost. I don't know where to start with building my loops. Do i need 2 or 3 loops? do i loop through a and b or do i need to introduce the 'n' variable into a loop of its own? This probably looks like obvious hints to experienced programmers but it seems i need more hand holding still...any help will be appreciated!
A Pythagorean triple is group of a,b,c
where a^2 + b^2 = c^2. you need to
find all a,b,c combinations which
satisfy the above rule starting a
0,0,0 up to 200 ,609,641 The first
triple will be [3,4,5] the next will
be [5,12,13] etc.. n is length of the
small side a so if n is 5 you need to
check all triples with
a=1,a=2,a=3,a=4,a=5 and find the two
cases shown above as being
Pythagorean,
EDIT
thanks for all submissions. So this is what i came up with (using python)
import math
for a in range (1,200):
for b in range (a,a*a):
csqrd = a * a + b * b
c = math.sqrt(csqrd)
if math.floor(c) == c:
print (a,b,int(c))
this DOES return the triple (200 ,609,641) where 200 is the upper limit for 'a' but computing the upper limit for 'b' remains tricky. Not sure how i would go about this...suggestions welcome :)
Thanks
Baba
p.s. i'm not looking for a solution but rather help in improving my problem solving skills. (definitely needed :-) )
You only need two loops. Note that n is given, meaning you read it from the keyboard or from a file.
Once you read n, you simply loop a from 1, then in that loop you loop b from a. Then you check if a <= n and if b <= n. If yes, you check if a^2 + b^2 is a square (if it can be writen as c^2 where c is an integer). If yes you output the corresponding triplet. You can stop the first loop once a > n and the second loop once b > n.
To compute the upper limit of b ... certainly we can't go past a^2 + b^2 = (b+1)^2, since the gap between successive squares increases. Now, (b+1)^2 is b^2 + 2b + 1, so we can stop on b when a^2 < 2b + 1. (In fact, for odd a, the biggest triple is when b = (a^2 - 1)/2, and then a^2 + b^2 = (b+1)^2.)
Let's consider even a. Then, we need to consider a^2 + b^2 = (b+2)^2, since 2b+1 is necessarily odd. Now, (b+2)^2 - b^2 = 4b+4, so we're looking at a^2 = 4b+4, or b = (a^2 - 4)/4 as the highest b (and, as before, we know this b works).
Therefore, for given a, you need to check bs up to
(a^2 - 1)/2 (a odd)
(a ^2 - 4)/4 (a even)
Given any a and b, you can compute what c should be. You can also check if the c you get is a whole number. With that in mind, you need to check all the a and b values and find the ones that give you a whole c number.
This should take just two loops (one for a and one for b). Leave comments if you want more help, and let me know what problems you have.
So Pythagorean tripes luckily have two properties that make this not so bad to solve:
First, all the numbers in a triple have to be integers (that means, you can calculate a^2 + b^2 and you have a triple if c^2 is an integer and not a float). Additionally, c is bounded by what a and b are.
So this should inform you how many variables you really have (which will guide your algorithm design - specifically how many for loops you need). The latter piece of information will inform you as to how long of a range you need to iterate over. I've tried to be vague as per your request, but let me know if you'd like anything more specific.
Break the problem into sub problems. The first clue is that you have an upper bound n on the value of c. Let's start with c=1 --- so, let's see how many triplets can be formed with:
a^2 + b^2 = 1
Now, let's set a = 1 to c-1. So that means we have to check if b is an integer such that b^2 = c^2 - a^2 and b^2 = int(b)^2.
leaving the formula and the language alone, you're trying to find every combination of two variables, a and b so...
foreach A
foreach B
foreach C
do something with B and A and eval with c
end foreach C
end foreach B
end foreach A
for ($x = 1; $x <= 200; $x++) {
for ($y = 1; $y <= 200; $y++) {
for ($z = 1; $z <= 200; $z++) {
if ($x < $y) {
if (pow($x, 2) + pow($y, 2) == pow($z, 2)) {
echo "$x, $y , $z<br/>";
}
}
}
}
}
3, 4 , 5
5, 12 , 13
6, 8 , 10
...
81, 108 , 135
84, 112 , 140
84, 135 , 159

Resources