McDonald's sells Chicken McNuggets only in packages of 6, 9 or 20. What is the largest number of McNuggets that cannot be bought exactly? - iteration

Question is from MIT OCW Course Number 6.00, As Taught in Fall 2008:
Here is a theorem below:
If it is possible to buy x, x+1,…, x+5 sets of McNuggets, for some x, then it is possible to buy any number of McNuggets >= x, given that McNuggets come in 6, 9 and 20 packs.
Using the theorem above, write an exhaustive search to find the largest number of McNuggets that cannot be bought in exact quantity, i.e. write an iterative program that finds the largest number of McNuggets that cannot be bought in exact quantity. Format of search should follow the outline below:
Hypothesise possible instances of numbers of McNuggets that cannot be purchased exactly, starting with 1.
For each possible instance, called n, test if there exists non-negative integers a, b, and c, such that 6a+9b+20c = n.
If n McNuggets cannot be bought in exact quantity, save n.
When have found 6 consecutive values of n where 6a+9b+20c = n, the last answer that was saved (not the last value of n that had a solution) is the correct answer, since from the theorem, any amount larger than this saved value of n can also be bought in exact quantity
The error is in line 14 of the code below and this is the error:
elif(6*a + 9*b + 20*c < n_saved or 6*a + 9*b + 20*c > n_saved):
^
SyntaxError: invalid syntax
Here is the code:
def largest_not(a, b, c, n, n_saved):
a = 0
b = 0
c = 0
n = 0
n_saved = 0
for a in range (10):
for b in range (10):
for c in range (10):
for n in range (10):
for n_saved in range (10):
if (6*a + 9*b + 20*c == n):
print (n)
elif(6*a + 9*b + 20*c < n_saved or 6*a + 9*b + 20*c > n_saved):
print (n_saved)
if (n - n_saved > 5):
print "Largest number of McNuggets that cannot be bought in exact quantity: " + "<" + n_saved + ">"
else :
print "Have not found the largest number of McNuggets that cannot be bought in exact quantity."
a=6
b=9
c=20
largest_not(a, b, c, n, n_saved)

Here is a way to solve this:
def check(n):
"""check if n nuggets can be bought exactly with packs of 6, 9 and 20"""
for a in range(20):
for b in range(20):
for c in range(20):
if (6*a+9*b+20*c==n):
return True
return False
### look for a serie of 6 successives n
### to apply the theorem
nb_i = 0 ## number of successive good n found
sv_i = 0 ## last good n found
bad_i = 0 ## last bad n found
for i in range(1, 100):
if (check(i)):
nb_i+=1
sv_i=i
else:
bad_i=i
nb_i=0
sv_i=0
if nb_i==6:
print "Solved: the biggest number of nuggets you cannot buy exactly is: " + bad_i
break
result is:
Solved: the biggest number of nuggets you cannot buy exactly is: 43

Your elif needs to be inline with your if. However, your algorithm will also not work.
I got 43 as the largest number not possible: I'm sure this solution could be optimised.
def check(n):
# a in [0..max times 6 goes into n]
for a in range(0, n // 6 + 1):
# b in [0..max times 9 goes into remainder]
for b in range((n - 6*a) // 9 + 1):
# c in [0..max times 20 goes into remainder]
for c in range(0, (n - 6*a - 9*b) // 20 + 1):
if 6*a + 9*b + 20*c == n:
return (a, b, c)
return None
def largest_not():
n = 1
last_n_not_possible = 1
while (n - last_n_not_possible <= 6):
can_purchase = check(n)
if can_purchase is not None:
print("Can purchase ", n, ' = ', can_purchase[0],'*6 + ', can_purchase[1],'*9 + ', can_purchase[2], '*20', sep='')
else:
print("Can't purchase", n)
last_n_not_possible = n
n = n + 1
return last_n_not_possible
print("Answer: ", largest_not())

Related

How are they calculating the Time Complexity for this Problem

Problem 6: Find the complexity of the below program: 
void function(int n)
{
    int i = 1, s =1;
    while (s <= n)
    {
        i++;
        s += i;
        printf("*");
    }
}
Solution: We can define the terms ‘s’ according to relation si = si-1 + i. The value of ‘i’ increases by one for each iteration. The value contained in ‘s’ at the ith iteration is the sum of the first ‘i’ positive integers. If k is total number of iterations taken by the program, then while loop terminates if: 1 + 2 + 3 ….+ k = [k(k+1)/2] > n So k = O(√n).
Time Complexity of the above function O(√n).
FROM: https://www.geeksforgeeks.org/analysis-algorithms-set-5-practice-problems/
Looking it over and over.
Apparently they are saying the Time Complexity is O(√n). I don't understand how they are getting to this result, and i've tried looking at this problem over and over. Can anyone break it down into detail?
At the start of the while-loop, we have s = 1; i = 1, and n is some (big) number. In each step of the loop, the following is done,
Take the current i, and increment it by one;
Add this new value for i to the sum s.
It is not difficult to see that successive updates of i forms the sequence 1, 2, 3, ..., and s the sequence 1, 1 + 2, 1 + 2 + 3, .... By a result attributed to the young Gauss, the sum of the first k natural numbers 1 + 2 + 3 + ... + k is k(k + 1) / 2. You should recognise that the sequence s fits this description, where k indicates the number of iterations!
The while-loop terminates when s > n, which is now equivalent to finding the lowest iteration number k such that (k(k + 1) / 2) > n. Simplifying for the asymptotic case, this gives a result such that k^2 > n, which we can simplify for k as k > sqrt(n). It follows that this algorithm runs in a time proportional to sqrt(n).
It is clear that k is the first integer such that k(k+1)/2 > n (otherwise the loop would have stopped earlier).
Then k-1 cannot have this same property, which means that (k-1)((k-1)+1)/2 <= n or (k-1)k/2 <= n. And we have the following sequence of implications:
(k-1)k/2 <= n → (k-1)k <= 2n
→ (k-1)^2 < 2n ; k-1 < k
→ k <= sqrt(2n) + 1 ; solve for k
<= sqrt(2n) + sqrt(2n) ; 1 < sqrt(2n)
= 2sqrt(2)sqrt(n)
= O(sqrt(n))

How the time complexity of gcd is Θ(logn)?

I was solving a time-complexity question on Interview Bit as given in the below image.
The answer given is Θ(theta)(logn) and I am not able to grasp how the logn term arrive here in the time complexity of this program.
Can someone please explain how the answer is theta of logn?
Theorem given any x, gcd(n, m) where n < fib(x) is recursive called equal or less than x times.
Note: fib(x) is fibonacci(x), where fib(x) = fib(x-1) + fib(x-2)
Prove
Basis
every n <= fib(1), gcd(n, m) is gcd(1,m) only recursive once
Inductive step
assume the theorem is hold for every number less than x, which means:
calls(gcd(n, m)) <= x for every n <= fib(x)
consider n where n <= fib(x+1)
if m > fib(x)
calls(gcd(n, m))
= calls(gcd(m, (n-m))) + 1
= calls(gcd(n-m, m%(n-m))) + 2 because n - m <= fib(x-1)
<= x - 1 + 2
= x + 1
if m <= fib(x)
calls(gcd(n, m))
= calls(gcd(m, (n%m))) + 1 because m <= fib(x)
<= x + 1
So the theorem also holds for x + 1, as mathematical induction, the theorem holds for every x.
Conclusion
gcd(n,m) is Θ(reverse fib) which is Θ(logn)
This algorithm generates a decreasing sequence of integer (m, n) pairs. We can try to prove that such sequence decays fast enough.
Let's say we start with m_1 and n_1, with m_1 < n_1.
At each step we take n_1 % m_1, which is < m_1, and repeat recursively on the pair m_2 = n_1 % m_1 and n_2 = m_1.
Now, let's say n_1 % m_1 = m_1 - p for some p where 0 < p < m_1.
We have max(m_2, n_2) = m_1 - p.
Let's take another step (m_2, n_2) -> (m_3, n_3), we can easily see that max(m_3, n_3) < p, but clearly it is also true that max(m_3, n_3) < m_1 - p as the sequence is strictly decreasing.
So we can write max(m_3, n_3) < min(m_1 - p, p), where min(m_1 - p, p) = m_1 / 2. This result expresses the fact that the sequence decreases geometrically, therefore the algorithm has to terminate in at most log_2(m_1) steps.

Calculating the time complexity

Can somebody help with the time complexity of the following code:
for(i = 0; i <= n; i++)
{
for(j = 0; j <= i; j++)
{
for(k = 2; k <= n; k = k^2)
print("")
}
a/c to me the first loop will run n times,2nd will run for(1+2+3...n) times and third for loglogn times..
but i m not sure about the answer.
We start from the inside and work out. Consider the innermost loop:
for(k = 2; k <= n; k = k^2)
print("")
How many iterations of print("") are executed? First note that n is constant. What sequence of values does k assume?
iter | k
--------
1 | 2
2 | 4
3 | 16
4 | 256
We might find a formula for this in several ways. I used guess and prove to get iter = log(log(k)) + 1. Since the loop won't execute the next iteration if the value is already bigger than n, the total number of iterations executed for n is floor(log(log(n)) + 1). We can check this with a couple of values to make sure we got this right. For n = 2, we get one iteration which is correct. For n = 5, we get two. And so on.
The next level does i + 1 iterations, where i varies from 0 to n. We must therefore compute the sum 1, 2, ..., n + 1 and that will give us the total number of iterations of the outermost and middle loop: this sum is (n + 1)(n + 2) / 2 We must multiply this by the cost of the inner loop to get the answer, (n + 1)(n + 2)(log(log(n)) + 1) / 2 to get the total cost of the snippet. The fastest-growing term in the expansion is n^2 log(log(n)) and so that is what would typically be given as asymptotic complexity.

Rewrite Resurrence Function to the Idea of Dynamic Programming

Can someone help me?
Rewrite the pseudo-code of Count(n) using the idea of Dynamic Programming. And determine the Time Complexity.
Test(n)
If n=1 return 1
Tn=0
For k=1 to n-1
Tn = Tn + Test(k) * Test(n-k)
Return Tn
Add Memoization to get a DP solution from a recursion one:
Python Code:
d = {}
def test(n):
if n == 1:
return 1
if d.get(n) is not None:
return d[n]
ans = 0
for k in range(1, n):
ans += test(k) * test(n - k)
d[n] = ans
return ans
You can check(It's Catalan numbers indeed, learn more about it in OEIS):
for i in range(1, 10):
print str(i) + ' ' + str(test(i))
Output:
1 1
2 1
3 2
4 5
5 14
6 42
7 132
8 429
9 1430
Time Complexity is O(n^2). Because calculate a state is O(n)(for k from 1 to n - 1), and we need calculate n state in total to get test(n).
In fact, we can achieve a O(n) solution since it's Catalan numbers...

Calculate APR (annual percentage rate) Programmatically

I am trying to find a way to programmatically calculate APR based on
Total Loan Amount
Payment Amount
Number of payments
Repayment frequency
There is no need to take any fees into account.
It's ok to assume a fixed interest rate, and any remaining amounts can be rolled into the last payment.
The formula below is based on a credit agreement for a total amount of credit of €6000 repayable in 24 equal monthly instalments of €274.11.
(The APR for the above example is 9.4%)
I am looking for an algorithm in any programming language that I can adapt to C.
I suppose you want to compute X from your equation. This equation can be written as
f(y) = y + y**2 + y**3 + ... + y**N - L/P = 0
where
X = APR
L = Loan (6000)
P = Individual Payment (274.11)
N = Number of payments (24)
F = Frequency (12 per year)
y = 1 / ((1 + X)**(1/F)) (substitution to simplify the equation)
Now, you need to solve the equation f(y) = 0 to get y. This can be done e.g. using the Newton's iteration (pseudo-code):
y = 1 (some plausible initial value)
repeat
dy = - f(y) / f'(y)
y += dy
until abs(dy) < eps
The derivative is:
f'(y) = 1 + 2*y + 3*y**2 + ... + N*y**(N-1)
You would compute f(y) and f'(y) using the Horner rule for polynomials to avoid the exponentiation. The derivative can be likely approximated by some few first terms. After you find y, you get x:
x = y**(-F) - 1
Here is the Objective C code snippet I came up with (which seems to be correct) if anybody is interested:
float x = 1;
do{
fx = initialPaymentAmt+paymentAmt *(pow(x, numPayments+1)-x)/(x-1)+0*pow(x,numPayments)-totalLoanAmt;
dx = paymentAmt *(numPayments * pow( x , numPayments + 1 ) - ( numPayments + 1 )* pow(x,numPayments)+1) / pow(x-1,2)+numPayments * 0 * pow(x,numPayments-1);
z = fx / dx;
x=x-z;
} while (fabs(z)>1e-9 );
apr=100*(pow(1/x,ppa)-1);