Then the sum and the last added number and the number of numbers added must be printed.
I am currently stuck, I managed to get the sum part working. The last added number output is printed "23" but should be "21". And lastly, how can I print the number of numbers added?
Output goal: 121, 21, 11
Here is my code:
n = int()
sum = 0
k = 1
while sum <= 100:
if k%2==1:
sum = sum + k
k = k + 2
print('Sum is:', sum)
print("last number:", k)
Edit: Would like to thank everyone for their help and answers!
Note, that (you can prove it by induction)
1 + 3 + 5 + ... + 2 * n - 1 == n**2
<----- n items ----->
So far so good in order to get n all you have to do is to compute square root:
n = sqrt(sum)
in case of 100 we can find n when sum reach 100 as
n = sqrt(100) == 10
So when n == 10 then sum == 100, when n = 11 (last item is 2 * n - 1 == 2 * 11 - 1 == 21) the sum exceeds 100: it will be
n*n == 11 ** 2 == 121
In general case
n = floor(sqrt(sum)) + 1
Code:
def solve(s):
n = round(s ** 0.5 - 0.5) + 1;
print ('Number of numbers added: ', n);
print ('Last number: ', 2 * n - 1)
print ('Sum of numbers: ', n * n)
solve(100)
We have no need in loops here and can have O(1) time and space complexity solution (please, fiddle)
More demos:
test : count : last : sum
-------------------------
99 : 10 : 19 : 100
100 : 11 : 21 : 121
101 : 11 : 21 : 121
Change your while loop so that you test and break before the top:
k=1
acc=0
while True:
if acc+k>100:
break
else:
acc+=k
k+=2
>>> k
21
>>> acc
100
And if you want the accumulator to be 121 just add k before you break:
k=1
acc=0
while True:
if acc+k>100:
acc+=k
break
else:
acc+=k
k+=2
If you have the curiosity to try a few partial sums, you immediately recognize the sequence of perfect squares. Hence, there are 11 terms and the last number is 21.
print(121, 21, 11)
More seriously:
i, s= 1, 1
while s <= 100:
i+= 2
s+= i
print(s, i, (i + 1) // 2)
Instead of
k = k + 2
say
if (sum <= 100):
k = k +2
...because that is, after all, the circumstance under which you want to add 2.
To also count the numbers, have another counter, perhasp howManyNumbers, which starts and 0 and you add 1 every time you add a number.
Just Simply Change you code to,
n = int()
sum = 0
k = 1
cnt = 0
while sum <= 100:
if k%2==1:
sum = sum + k
k = k + 2
cnt+=1
print('Sum is:', sum)
print("last number:", k-2)
print('Number of Numbers Added:', cnt)
Here, is the reason,
the counter should be starting from 0 and the answer of the last printed number should be k-2 because when the sum exceeds 100 it'll also increment the value of k by 2 and after that the loop will be falls in false condition.
You can even solve it for the general case:
def sum_n(n, k=3, s =1):
if s + k > n:
print('Sum is', s + k)
print('Last number', k)
return
sum_n(n, k + 2, s + k)
sum_n(int(input()))
You can do the following:
from itertools import count
total = 0
for i, num in enumerate(count(1, step=2)):
total += num
if total > 100:
break
print('Sum is:', total)
print("last number:", 2*i + 1)
To avoid the update on k, you can also use the follwoing idiom
while True:
total += k # do not shadow built-in sum
if total > 100:
break
Or in Python >= 3.8:
while (total := total + k) <= 100:
k += 2
Based on your code, this would achieve your goal:
n = 0
summed = 0
k = 1
while summed <= 100:
n += 1
summed = summed + k
if summed <= 100:
k = k + 2
print(f"Sum is: {summed}")
print(f"Last number: {k}")
print(f"Loop count: {n}")
This will solve your problem without changing your code too much:
n = int()
counter_sum = 0
counter = 0
k = 1
while counter_sum <= 100:
k+= 2
counter_sum =counter_sum+ k
counter+=1
print('Sum is:', counter_sum)
print("last number:", k)
print("number of numbers added:", counter)
You don't need a loop for this. The sum of 1...n with step size k is given by
s = ((n - 1) / k + 1) * (n + 1) / k
You can simplify this into a standard quadratic
s = (n**2 - k * n + k - 1) / k**2
To find integer solution for s >= x, solve s = x and take the ceiling of the result. Apply the quadratic formula to
n**2 - k * n + k - 1 = k**2 * x
The result is
n = 0.5 * (k + sqrt(k**2 - 4 * (k - k**2 * x - 1)))
For k = 2, x = 100 you get:
>>> from math import ceil, sqrt
>>> k = 2
>>> x = 100
>>> n = 0.5 * (k + sqrt(k**2 - 4 * (k - k**2 * x - 1)))
>>> ceil(n)
21
The only complication arises when you get n == ceil(n), since you actually want s > x. In that case, you can test:
c = ceil(n)
if n == c:
c += 1
Related
I have integer input: 0 < a, K, N < 10^9
I need to find all b numbers that satisfy:
a + b <= N
(a + b) % K = 0
For example: 10 6 40 -> [2, 8, 14, 20, 26]
I tried a simple brute force and failed (Time Limit Exceeded). Can anyone suggest answer? Thanks
a, K, N = [int(x) for x in input().split()]
count = 0
b = 1
while (a + b <= N):
if ((a + b) % K) == 0:
count+=1
print(b, end=" ")
b+=1
if (count == 0):
print(-1)
The first condition is trivial in the sense that it just poses an upper limit on b. The second condition can be rephrased using the definition of % as
a + b = P * K
For some arbitrary integer P. From this, is simple to compute the smallest b by finding the smallest P that gives you a positive result for P * K - a. In other words
P * K - a >= 0
P * K >= a
P >= a / K
P = ceil(a / K)
So you have
b0 = ceil(a / K) * K - a
b = range(b0, N + 1, K)
range is a generator, so it won't compute the values up front. You can force that by doing list(b).
At the same time, if you only need the count of elements, range objects will do the math on the limits and step size for you conveniently, all without computing the actual values, so you can just do len(b).
To find the list of bs, you can use some maths. First, we note that (a + b) % K is equivalent to a % K + b % K. Also when n % K is 0, that means that n is a multiple of K. So the smallest value of b is n * K - a for the smallest value of n where this calculation is still positive. Once you find that value, you can simply add K repeatedly to find all other values of b.
b = k - a%k
Example: a=19, k=11, b = 11-19%11 = 11-8 =3
I'm a bit stuck on a python problem.
I'm suppose to write a function that takes a positive integer n and returns the number of different operations that can sum to n (2<n<201) with decreasing and unique elements.
To give an example:
If n = 3 then f(n) = 1 (Because the only possible solution is 2+1).
If n = 5 then f(n) = 2 (because the possible solutions are 4+1 & 3+2).
If n = 10 then f(n) = 9 (Because the possible solutions are (9+1) & (8+2) & (7+3) & (7+2+1) & (6+4) & (6+3+1) & (5+4+1) & (5+3+2) & (4+3+2+1)).
For the code I started like that:
def solution(n):
nb = list(range(1,n))
l = 2
summ = 0
itt = 0
for index in range(len(nb)):
x = nb[-(index+1)]
if x > 3:
for index2 in range(x-1):
y = nb[index2]
#print(str(x) + ' + ' + str(y))
if (x + y) == n:
itt = itt + 1
for index3 in range(y-1):
z = nb[index3]
if (x + y + z) == n:
itt = itt + 1
for index4 in range(z-1):
w = nb[index4]
if (x + y + z + w) == n:
itt = itt + 1
return itt
It works when n is small but when you start to be around n=100, it's super slow and I will need to add more for loop which will worsen the situation...
Do you have an idea on how I could solve this issue? Is there an obvious solution I missed?
This problem is called integer partition into distinct parts. OEIS sequence (values are off by 1 because you don't need n=>n case )
I already have code for partition into k distinct parts, so modified it a bit to calculate number of partitions into any number of parts:
import functools
#functools.lru_cache(20000)
def diffparts(n, k, last):
result = 0
if n == 0 and k == 0:
result = 1
if n == 0 or k == 0:
return result
for i in range(last + 1, n // k + 1):
result += diffparts(n - i, k - 1, i)
return result
def dparts(n):
res = 0
k = 2
while k * (k + 1) <= 2 * n:
res += diffparts(n, k, 0)
k += 1
return res
print(dparts(201))
Was recently trying to solve this coding challenge from a company and I was stumped.
Let T(n) denote the number of different ways that a value of n cents, where n >= 4 and n is even, can be made by using 4-cent and 6-cent coins. For example, if n = 12 then we can use 3 4-cent coins or 2 6-cent coins, so T(12) = 2. Write a recursive algorithm in Python to find T(n) for n >= 4 and n is even.
I nailed down the base cases to be T(n < 4 or n not even) = 0, T(4) = 1 distinct way (1 4-cent coin) and T(6) = 1 distinct way (1 6-cent coin). But I'm not entirely sure how to proceed with a value greater than 6 and is even. Actually, if n > 4 and is even I did think of using modulo (%), so
if(n % 4 == 0): increment count
if(n % 6 == 0): increment count
I guess, I'm stuck on the recursive part because the two if-statements I've computed would count as only a single a way whereas there can be multiple ways to compute N.
Not recursive, but should help you get started.
To determine unique solutions, you are basically asking for partitions of N such that N1 + N2 = N and N1 % 4 == 0 and N2 % 6 == 0. An iterative solution would go something like this:
count = 0
for j in range(0, N + 1, 4):
if (N - j) % 6 == 0:
count += 1
Turning this loop into a recursion is trivial:
def count(N):
def count4(N, n4):
if n4 > N:
return 0
return int((N - n4) % 6 == 0) + count4(N, n4 + 4)
if N < 4 or N % 2:
return 0
return count4(N, 0)
Assuming that ways means "exact order in which coins are laid out", here is a recursive solution.
def T_recurse (n):
if 0 == n:
return 1
elif n < 3:
return 0
else:
return T_recurse(n - 4) + T_recurse(n - 6)
print(T_recurse(100))
And a faster solution
def T_iter(n):
if n < 0:
return 0
else:
answers = [1, 0, 0, 0, 1, 0]
while len(answers) <= n:
answers.append(answers[-4] + answers[-6])
return answers[n]
print(T_iter(100))
(There is also an analytical solution involving the roots of the polynomial x^6 - x^2 - 1, but that is slower to calculate in practice.)
Assuming that ways means "this many of one, that many of the other", then here is a recursive solution:
def S_recurse (n, coins):
if 0 == n:
return 1
elif n < 0:
return 0
elif len(coins) == 0:
return 0
else:
return S_recurse(n - coins[0], coins) + S_recurse(n, coins[1:])
S_recurse(12, [4, 6])
The recursive slowdown is not as bad though still exponential. However but iterative gives you quadratic:
def S_iter (n, coins):
last_row = [0 for i in range(n + 1)]
last_row[0] = 1
for coin in coins:
this_row = []
for i in range(n+1):
if i < coin:
this_row.append(last_row[i])
else:
this_row.append(last_row[i] + this_row[i - coin])
last_row = this_row
return last_row[n]
You can use an optional parameter to keep track of the current sum of 6-cent coins for a given recursive call, and return 1 when the given number is divisible by 4 after deducting the sum of 6's:
def count46(n, sum6=0):
return sum6 <= n and (((n - sum6) % 4) == 0) + count46(n, sum6 + 6)
so that:
for i in range(4, 24, 2):
print(i, count_4_6(i))
outputs:
4 1
6 1
8 1
10 1
12 2
14 1
16 2
18 2
20 2
22 2
Not the most optimized but it returns an array of all distinct solutions
def coins(n, sum=0, current=[], answers=[]):
if sum > n:
return
if sum == n:
answers.append(current)
return
a4 = list(current)
a4.append(4)
coins(n, sum+4, a4, answers)
lastIndex = len(current) - 1
if len(current) == 0 or current[lastIndex] == 6:
a6 = list(current)
a6.append(6)
coins(n, sum+6, a6, answers)
return answers
Try it online!
a matrix consists of N × N blocks .the block number is equal to the sum of the row number and the column number. each block consists of data, and data is equal to difference of sum of even and odd digits of the block number . calculate total data of n*n blocks
i/o format
lets n = 4
so
matrix will be
2 3 4 5
3 4 5 6
4 5 6 7
5 6 7 8
so total data = 2+3+4+5+3+4+5+6+4+5+6+7+5+6+7+8=80
if number of block is 4256 in any case then data in it will be abs(diff(sum(even digits)- sum(odd digits))) which is abs((4+2+6)-(5))= 7
my naive attempt
n = int(raw_input())
sum1=0
sum2=0
for i in range(1,n+1):
for j in range(1,n+1):
sum1 = i+j
diffsum = diff(sum1)
sum2 = sum2+diffsum
print sum2
again optimized attempt
def diff(sum1):
sum1 = str(sum1)
m = sum([int(i) for i in sum1 if int(i) % 2 == 0])
f = sum([int(i) for i in sum1 if int(i) % 2 != 0])
return abs(m - f)
n = int(raw_input())
sum1 = 0
k = 1
# t1 = time.time()
p = 2 * n
for i in range(2, n + 2):
diffsum = diff(i)
diffsum1 = diff(p)
sum1 = sum1 + (diffsum * k)
sum1 = sum1 + (diffsum1 * k)
p = p - 1
k = k + 1
sum1 = sum1 - (diff(n + 1) * n)
print sum1
diff is common function in both case. i need more optmization with the following algorithm
Your optimised approach calculates the digit sum only once for each number, so at first sight, there isn't anything to be gained from memoisation.
You can improve the performance of your diff function by merging the two loops into one and use a dictionary to look up whether you add or subtract a digit:
value = dict(zip("0123456789", (0, -1, 2, -3, 4,-5, 6,-7, 8,-9)))
def diff2(s):
s = str(s)
return abs(sum([value[i] for i in s]))
This will require a conversion to string. You can get a bit faster (but not much) by calculating the digits by hand:
dvalue = [0, -1, 2, -3, 4,-5, 6,-7, 8,-9]
def diff(s):
t = 0
while s:
t += dvalue[s % 10]
s //= 10
return abs(t)
Finally, you can make use of the fact that you calculate all digit sums from 2 up to 2·n sequentially. Store the digits of the current number in an array, then implement an odometer-like counter. When you increment that counter, keep track of the odd and even digit sums. In 9 of 10 cases, you just have to adjust the last digit by removing its value from the respective sum and by adding the next digit to the other sum.
Here's a program that does this. The function next increments the counter and keeps the digit sums of even and odd numbers in sums[0] and sums[1]. The main program is basically the same as yours, except that the loop has been split into two: One where k increases and one where it decreases.
even = set(range(0, 10, 2))
def next(num, sums):
o = num[0]
if o in even:
sums[0] -= o
sums[1] += o + 1
else:
sums[0] += o + 1
sums[1] -= o
num[0] += 1
i = 0
while num[i] == 10:
sums[0] -= 10
num[i] = 0
i += 1
o = num[i]
if o in even:
sums[0] -= o
sums[1] += o + 1
else:
sums[0] += o + 1
sums[1] -= o
num[i] += 1
n = int(raw_input())
total = 0
m = len(str(2 * n + 1))
num = [0] * m
num[0] = 2
sums = [2, 0]
k = 1
for i in range(2, n + 2):
total += abs(sums[0] - sums[1]) * k
k += 1
next(num, sums)
k = n
for i in range(n + 2, 2*n + 1):
k -= 1
total += abs(sums[0] - sums[1]) * k
next(num, sums)
print total
I've said above that memoisation isn't useful for this approach. That's not true. You could store the even and odd digit sums of number i and make use of it when calculating the numbers 10 * i to 10 * i + 9. When you call diff in order of increasing i, you will have access to the stored sums of i // 10.
This isn't significantly faster than the odometer approach, but the implementation is clearer at the cost of additional memory. (Preallocated arrays work better than dictionaries for big n. You don't need to reserve space for numbers above (2*n + 11) / 10.)
def diff(s):
d = s % 10
e = ememo[s / 10]
o = omemo[s / 10]
if d in even:
e += d
else:
o += d
if s < smax:
ememo[s] = e
omemo[s] = o
return e, o
n = int(raw_input())
total = 0
even = set(range(0, 10, 2))
smax = (2*n + 11) / 10
omemo = smax * [0]
ememo = smax * [0]
omemo[1] = 1
k = 1
for i in range(2, n + 2):
e, o = diff(i)
total += abs(e - o) * k
k += 1
k = n
for i in range(n + 2, 2*n + 1):
k -= 1
e, o = diff(i)
total += abs(e - o) * k
print total
This could be made even faster if one could find a closed formula for the digit sums, but I think that the absolute function prevents such a solution.
I wrote a set of codes to calculate a Diophantine equation:
bestSoFar = 0
packages = (6,9,20)
numMc = 0
guess= 0
possibn = []
for n in xrange(1, 150):
for a in xrange(0, (n/ packages[0]) +1):
for b in xrange(0,(n/ packages[1]) +1):
c = (n - packages[0]* a - b * packages[1]) / packages[-1]
numMc = packages[0] *a + packages[1] * b + packages[-1] * c
if numMc == n and n not in possibn:
possibn.append(n)
print possibn
if len(possibn) >6 and possibn [-1] - possibn[-6] == 5:
bestSoFar = n
break
The original problem set is designed by the MIT course. Basically it is to calculate the number of McNuggets that could be bought by arranging the ratio of packages-in-different-size ( McDonald does 6,9,20 McNuggets in a package). Say, 21 McNuggets could be bought by buying two 6-McNuggets and one 9-McNuggets. if the number of McNuggets are possible to be bought in exact quantity of packages, I store them into a list. It is found that if 6 consecutive numbers are also possible to be bought in exact quantity, the remained numbers could also be possible.
From my code the result of bestSoFar=149 while the expected answer is 40. The reason would be that it keeps looping until n reaches 149. I would like to stop right at 40 ( with the break statement). However, it fails and I am seeking the advices for you all. Also, if there is anyway to program the problem faster/easier, I am happy to know and learn it too.
Thank you so much.
Casey
If you are not supposed to use a function, just assign a variable to cause breaks out of the other loops.
bestSoFar = 0
packages = (6,9,20)
numMc = 0
guess= 0
possibn = []
finished = False
for n in xrange(1, 150):
for a in xrange(0, (n/ packages[0]) +1):
for b in xrange(0,(n/ packages[1]) +1):
c = (n - packages[0]* a - b * packages[1]) / packages[-1]
numMc = packages[0] *a + packages[1] * b + packages[-1] * c
if numMc == n and n not in possibn:
possibn.append(n)
# print possibn
if len(possibn) >6 and possibn [-1] - possibn[-6] == 5:
bestSoFar = n
finished = True
break
if finished: break
print bestSoFar
Turn it into a function and return:
from __future__ import print_function
def solve(*packages):
bestSoFar = 0
numMc = 0
guess= 0
possibn = []
for n in xrange(1, 150):
for a in xrange(0, (n / packages[0]) + 1):
for b in xrange(0, (n / packages[1]) + 1):
c = (n - packages[0] * a - b * packages[1]) / packages[-1]
numMc = packages[0] * a + packages[1] * b + packages[-1] * c
if numMc == n and n not in possibn:
possibn.append(n)
print possibn
if len(possibn) > 6 and possibn [-1] - possibn[-6] == 5:
return n
return bestSoFar
x = solve(6, 9, 20)
print(x)
I am not actually clear on what you are expecting. But, what i see is you want to break out of everything. The break which you have given only exits inner loop. Put another break statement outside the inner loop and inside first loop.