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
I am currently stuck on Project Euler problem 60. The problem goes like this:
The primes 3, 7, 109, and 673, are quite remarkable. By taking any two primes and concatenating them in any order the result will always be prime. For example, taking 7 and 109, both 7109 and 1097 are prime. The sum of these four primes, 792, represents the lowest sum for a set of four primes with this property.
Find the lowest sum for a set of five primes for which any two primes concatenate to produce another prime.
In Python, I used and created the following functions.
def isprime(n):
"""Primality test using 6k+-1 optimization."""
if n <= 3:
return n > 1
elif n % 2 == 0 or n % 3 == 0:
return False
i = 5
while i * i <= n:
if n % i == 0 or n % (i + 2) == 0:
return False
i += 6
return True
def prime_pair_sets(n):
heap = [[3,7]]
x = 11
#Phase 1: Create a list of length n.
while getMaxLength(heap)<n:
if isprime(x):
m = [x]
for lst in heap:
tmplst = [x]
for p in lst:
if primePair(x,p):
tmplst.append(p)
if len(tmplst)>len(m):
m=tmplst
heap.append(m)
x+=2
s = sum(maxList(heap))
#Phase 2: Find the lowest sum.
for li in heap:
y=x
while s>(sum(li)+y) and len(li)<n:
b = True
for k in li:
if not primePair(k,y):
b = False
if b == True:
li.append(y)
y+=2
if len(li)>=n:
s = sum(li)
return s
def getMaxLength(h):
m = 0
for s in h:
if len(s) > m:
m = len(s)
return m
def primePair(x, y):
return isprime(int(str(x)+str(y))) and isprime(int(str(y)+str(x)))
def maxList(h):
result = []
for s in h:
if len(s)> len(result):
result = s
return result
I executed the primePairSets function using the first phase only. After about an hour of waiting I got the sum of 74,617 (33647 + 23003 + 16451 + 1493 + 23). It turns out that it is not the sum we're looking for. I tried the problem again using both phases. After about two hours, I end up with the same wrong result. Obviously, the answer is less than 74,617. Can somebody help me find a more efficient way to solving this problem. Please tell me how to solve it.
Solution found
Primes: 13, 5197, 5701, 6733, 8389
Sum: 26,033
Run time reduced to ~10 seconds vs. 1-2 hours reported by OP solution.
Approach
Backtracking algorithm based upon extending path containing list of primes
A prime can be added to the path if its pairwise prime with all primes already in path
Use Sieve of Eratosthenes to precompute primes up to max we expect to need
For each prime, precompute which other primes it is pairwise prime with
Code
import functools
import time
# Decorator for function timing
def timer(func):
"""Print the runtime of the decorated function"""
#functools.wraps(func)
def wrapper_timer(*args, **kwargs):
start_time = time.perf_counter() # 1
value = func(*args, **kwargs)
end_time = time.perf_counter() # 2
run_time = end_time - start_time # 3
print(f"Finished {func.__name__!r} in {run_time:.4f} secs")
return value
return wrapper_timer
#*************************************************************
# Prime number algorithms
#-------------------------------------------------------------
def _try_composite(a, d, n, s):
if pow(a, d, n) == 1:
return False
for i in range(s):
if pow(a, 2**i * d, n) == n-1:
return False
return True # n is definitely composite
def is_prime(n, _precision_for_huge_n=16, _known_primes = set([2, 3, 5, 7])):
if n in _known_primes:
return True
if n > 6 and not (n % 6) in (1, 5):
# Check of form 6*q +/- 1
return False
if any((n % p) == 0 for p in _known_primes) or n in (0, 1):
return False
d, s = n - 1, 0
while not d % 2:
d, s = d >> 1, s + 1
# Returns exact according to http://primes.utm.edu/prove/prove2_3.html
if n < 1373653:
return not any(_try_composite(a, d, n, s) for a in (2, 3))
if n < 25326001:
return not any(_try_composite(a, d, n, s) for a in (2, 3, 5))
if n < 118670087467:
if n == 3215031751:
return False
return not any(_try_composite(a, d, n, s) for a in (2, 3, 5, 7))
if n < 2152302898747:
return not any(_try_composite(a, d, n, s) for a in (2, 3, 5, 7, 11))
if n < 3474749660383:
return not any(_try_composite(a, d, n, s) for a in (2, 3, 5, 7, 11, 13))
if n < 341550071728321:
return not any(_try_composite(a, d, n, s) for a in (2, 3, 5, 7, 11, 13, 17))
# otherwise
return not any(_try_composite(a, d, n, s)
for a in _known_primes[:_precision_for_huge_n])
def primes235(limit):
' Prime generator using Sieve of Eratosthenes with factorization wheel of 2, 3, 5 '
# Source: https://rosettacode.org/wiki/Sieve_of_Eratosthenes#Python
yield 2; yield 3; yield 5
if limit < 7: return
modPrms = [7,11,13,17,19,23,29,31]
gaps = [4,2,4,2,4,6,2,6,4,2,4,2,4,6,2,6] # 2 loops for overflow
ndxs = [0,0,0,0,1,1,2,2,2,2,3,3,4,4,4,4,5,5,5,5,5,5,6,6,7,7,7,7,7,7]
lmtbf = (limit + 23) // 30 * 8 - 1 # integral number of wheels rounded up
lmtsqrt = (int(limit ** 0.5) - 7)
lmtsqrt = lmtsqrt // 30 * 8 + ndxs[lmtsqrt % 30] # round down on the wheel
buf = [True] * (lmtbf + 1)
for i in range(lmtsqrt + 1):
if buf[i]:
ci = i & 7; p = 30 * (i >> 3) + modPrms[ci]
s = p * p - 7; p8 = p << 3
for j in range(8):
c = s // 30 * 8 + ndxs[s % 30]
buf[c::p8] = [False] * ((lmtbf - c) // p8 + 1)
s += p * gaps[ci]; ci += 1
for i in range(lmtbf - 6 + (ndxs[(limit - 7) % 30])): # adjust for extras
if buf[i]: yield (30 * (i >> 3) + modPrms[i & 7])
def prime_pair(x, y):
' Checks if two primes are prime pair (i.e. concatenation of two in either order is also a prime)'
return is_prime(int(str(x)+str(y))) and is_prime(int(str(y)+str(x)))
def find_pairs(primes):
' Creates dictionary of what primes can go with others as a pair'
prime_pairs = {}
for i, p in enumerate(primes):
pairs = set()
for j in range(i+1, len(primes)):
if prime_pair(p, primes[j]):
pairs.add(primes[j])
prime_pairs[p] = pairs
return prime_pairs
#*************************************************************
# Main functionality
#-------------------------------------------------------------
#timer
def find_groups(max_prime = 9000, n = 5):
'''
Find group smallest sum of primes that are pairwise prime
max_prime - max prime to consider
n - the size of the group
'''
def fully_connected(p, path):
'''
checks if p is connected to all elements of the path
(i.e. group of primes)
'''
return all(p in prime_pairs.get(path_item, set()) for path_item in path)
def backtracking(prime_pairs, n, path = None):
if path is None:
path = []
if len(path) == n:
yield path[:]
else:
if not path:
for p, v in prime_pairs.items():
if v:
yield from backtracking(prime_pairs, n, path + [p])
else:
p = path[-1]
for t in sorted(prime_pairs[p]):
if t > p and fully_connected(t, path):
yield from backtracking(prime_pairs, n, path + [t])
primes = list(primes235(max_prime)) # Sieve for list of primes up to max_pair
set_primes = set(primes) # set of primes (for easy test if number is prime)
prime_pairs = find_pairs(primes) # Table of primes and set of other primes they can pair with
return next(backtracking(prime_pairs, n), None)
Test Runs
for n, max_prime in [(2, 1000), (3, 1000), (4, 1000), (5, 9000)]:
print(find_groups(max_prime = max_prime, n = n))
Run Times
n max_prime Primes Found Run Time (secs)
2 1000 (3, 7) 0.1280
3 1000 (3, 37, 67) 0.1240
4 1000 (3, 7, 109, 673) 0.1233
5 40,000 (13, 5197, 5701, 6733, 8389) 7.1142
Note: Timings above performed on an older Windows desktop computer,
namely:
~7-year-old HP-Pavilion Desktop i7 CPU 920 # 2.67 GHz
I wrote this code based on an sieve of Eratosthenes which only stores the numbers 1 mod 6 and -1 mod 6. It is very fast.
def find_lowest_sum (pmax,num):
n=int(str(pmax)+str(pmax))
sieve5m6 = [True] * (n//6+1)
sieve1m6 = [True] * (n//6+1)
for i in range(1,int((n**0.5+1)/6)+1):
if sieve5m6[i]:
sieve5m6[6*i*i::6*i-1]=[False]*(((n//6+1)-6*i*i-1)//(6*i-1)+1)
sieve1m6[6*i*i-2*i::6*i-1]=[False]*(((n//6+1)-6*i*i+2*i-1)//(6*i-1)+1)
if sieve1m6[i]:
sieve5m6[6*i*i::6*i+1]=[False]*(((n//6+1)-6*i*i-1)//(6*i+1)+1)
sieve1m6[6*i*i+2*i::6*i+1]=[False]*(((n//6+1)-6*i*i-2*i-1)//(6*i+1)+1)
def test_concatenate (p1,p2):
ck=0
p3=int(str(p1)+str(p2))
if sieve1m6[(p3-1)//6] and p3%6==1:
ck=1
elif sieve5m6[(p3+1)//6]and p3%6==5:
ck=1
if ck==1:
p3=int(str(p2)+str(p1))
if sieve1m6[(p3-1)//6] and p3%6==1:
ck=2
elif sieve5m6[(p3+1)//6]and p3%6==5:
ck=2
if ck==2:
return True
else:
return False
kmax=(pmax+1)//6
s1=5*pmax
P1=[]
P2=[]
p=3
kmin=0
while p<s1//5:
if p==3 or(p%6==1 and sieve1m6[(p-1)//6])or(p%6==5 and sieve5m6[(p+1)//6]):
P=[]
if p%6==1:
kmin=p//6
elif p%6==5:
kmin=(p+1)//6
if sieve1m6[kmin]:
if test_concatenate(p,6*kmin+1):
P.append(6*kmin+1)
for k in range(kmin+1,kmax):
if sieve5m6[k]:
if test_concatenate(p,6*k-1):
P.append(6*k-1)
if sieve1m6[k]:
if test_concatenate(p,6*k+1):
P.append(6*k+1)
i1=0
while i1<len(P) and P[i1]<s1:
P1=[p]
s=p
P1.append(P[i1])
s+=P[i1]
for i2 in range(i1+1,len(P)):
for i3 in range(1,len(P1)):
ck=test_concatenate(P[i2],P1[i3])
if ck==False:
break
if len(P1)-1==i3 and ck==True:
P1.append(P[i2])
s+=P[i2]
if len(P1)==num:
if s<s1:
P2=P1
s1=s
break
i1+=1
p+=2
return P2
P=find_lowest_sum(9001,5)
print(P)
s=0
for i in range(0,len(P)):
s+=P[i]
print(s)
I need help for defining the fibanocci 2 function. The fibanocci 2 function is decribed as :
fib2(n) = {0 if n <= 0, 1 if n = 1, 2 if n = 2, ( fib2( n - 1) * fib2( n - 2)) - fib2( n - 3) else}
We need to define this function iterative.
I tried my best but i couldn't write a working code.
def fib2(n: int) -> int:
if n <= 0:
return 0
elif n == 1:
return 1
elif n == 2:
return 2
else:
n = ((n - 1) * (n - 2) - (n - 3)
return n
a = fib2(7)
print (a)
assert (fib2(7) == 37)
the output from this fib2 function is 26 but it should be 37.
Thank you in advance
For the iterative version you have to use a for loop.
And just add the 3 previous numbers to get the next one.
Here is a piece of code:
def fib3(n):
a = 0
b = 1
c = 0
for n in range(n):
newc = a+b+c
a = b
b = c
c = newc
return newc
print(fib3(7))
assert (fib3(7) == 37)
You can not change the value of a parameter.
Please try to return directly :
Return ((fb2(n-1)×fb2(n-2))-fb2(n-3))
So it will work as a recursive function.
def fibo(n):
current = 0
previous_1 = 1
previous_2 = 0
for i in range(1,n):
current = previous_1 + previous_2
previous_2 = previous_1
previous_1 = current
return current
To do it iteratively, the best way is to write it on paper to understand how it works.
Mathematically fibo is Fn = Fn-1 + Fn-2 . Therefore, you can create variables called previous_1 and previous_2 which represents the elements of Fn and you simply update them on each run.
Fn is current
There is a problem we need to solve in my university where we need to print the 10 smallest prime fibonacci numbers in an ascending order.So far i have found this code but it takes about 2 min to print them and was wondering if there was a faster way to print them.
import math
def isSquare(n):
sr = (int)(math.sqrt(n))
return (sr * sr == n)
def printPrimeAndFib(n):
prime = [True] * (n + 1)
p = 2
while (p * p <= n):
if (prime[p] == True):
for i in range(p * 2, n + 1, p):
prime[i] = False
p = p + 1
list=[]
for i in range(2, n + 1):
if (prime[i] and (isSquare(5 * i * i + 4) > 0 or
isSquare(5 * i * i - 4) > 0)):
list.append(i)
print(list)
n = 500000000
printPrimeAndFib(n)
With a Fibonacci generator and a prime filter. Takes about 0.002 seconds.
from itertools import islice
from math import isqrt
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
def is_prime(n):
return n > 1 and all(map(n.__mod__, range(2, isqrt(n) + 1)))
fibonacci_primes = filter(is_prime, fibonacci())
print(list(islice(fibonacci_primes, 10)))
Output:
[2, 3, 5, 13, 89, 233, 1597, 28657, 514229, 433494437]
This approach generates Fibonacci numbers until it finds 10 that are prime; takes approx 0.001-0.002 seconds
from math import sqrt
def isprime(x):
#deal with prime special cases 1 and 2
if x==2:
return True
if x == 1 or x%2==0:
return False
#Fast-ish prime checking - only scan odds numbers up to sqrt(x)
for n in range(3,int(sqrt(x))+1,2):
if x%n==0:
return False
return True
fib_primes = []
current=1
previous=1
while (len(fib_primes)<10):
if isprime(current):
fib_primes.append(current)
next = current+previous
previous = current
current = next
print(fib_primes)
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))