Goldbach Python Output - python

I made a python code for Goldbach conjecture.
The thing is my output looks like this
Enter the lower limit: 8
Enter the Upper limit: 10
8 = 3 + 5
10 = 3 + 7
10 = 5 + 5
What I want my output to look like is
8 = 3 + 5
10 = 3 + 7 = 5 + 5
Is there any way to format it as such?
I am posting only the for loop:
for n in range (lo_limit, up_limit + 1): #lo_limit and up_limit is what you input
if (n % 2 == 0):
for a in range (1, n + 1):
if is_prime(a): #is_prime represent numbers that are prime
for b in range(1, n + 1):
if is_prime(b):
if (a + b == n):
if (a <= b):
print(n, "=", a, "+", b)
main()

Your function can be simplified and sped up a ton with some simple changes:
def goldbach(lo, hi):
# 1. just step by 2 instead of checking for even numbers
for n in range(lo, hi + 1, 2):
# 2. keep a list of found matches instead of building up a string
matches = [str(n)]
# 3. for any 'a', you can just subtract to find 'b' instead of looping
# 4. instead of testing for a <= b, just run the 'a' loop halfway
for a in range(1, n // 2 + 1):
if is_prime(a) and is_prime(n-a):
matches.append('{} + {}'.format(a, n-a))
# 5. join up the matches and print at the end
print(' = '.join(matches))
The entire inner for loop could be expressed as a list-comprehension as well, for more brevity.
You could easily optimize this further by generating a list of primes in your range beforehand, and then just iterating over those and checking membership for the complements, instead of doing repeated primality testing.

Try this:
for n in range (lo_limit, up_limit + 1):
if (int(n) % 2 == 0):
printedstring=str(n)
for a in range (1, n + 1):
if is_prime(a):
for b in range(1, n + 1):
if is_prime(b):
if (a + b == n):
if (a <= b):
printedstring = printedstring + str(" = ", a, " + ", b)
print(printedstring)

Related

Optimising sequence code after Time limit exceeded error

FIND THE SEQUENCE SUM
i = 5
j = 9
K = 6
sum all the values from i to j and back to K: 5 + 6 + 7 + 8 + 9 + 8 + 7 + 6
My answer is:
def sequence_sum(i,j,k):
sum = 0
for i in range(i,j+1):
sum += i
for m in range(j-1,k-1,-1):
sum += m
return sum
However, this solution is correct I received a 9/12 out of the test cases and was given an error message that stated that the time limit was exceeded, I was allowed 10 seconds and the message read " Your code did not execute within the time limits. Please optimise your code."
Can I please get some help with this as I don't understand what I am suppose to do here?
Notice the sum from 5 to 9 is the same as:
(5+0) + (5+1) + (5+2) + (5+3) + (5+4)
If we extract 5, we have: 5*(9-5+1) + (sum from 1 to (9-5)).
To get a general formula:
sum(a,b) = (b-a+1) * a + (b-a)*(b-a+1)/2
The second formula is the sum of all natural numbers up to b-a.
so create the following function:
def my_sum(a,b):
return (b-a+1) * a + (b-a)*(b-a+1)/2
thus the sequence_sum(i,j,k):
def sequence_sum(i,j,k):
return my_sum(i,j) + my_sum(k,j-1)
You can simply use range() function returning an iterable + sum function:
sum's time complexity is O(n) and the range function returns a lazy iterable. That is also O(n) operation.
The return statement returns only the reference of the list so it's time complexity is O(1)
return sum(range(i,j))+sum(range(j,k-1,-1))
the sum from 1, to i is i * (i + 1) / 2 let's call it s(i).
and f(i, j) is the sum from i to j.
f(i, j) = i + (i + 1) + ... + j = 1 + 2 + ... + j - (1 + 2 + ... + (i - 1))
so f(i, j) = s(j) - s(i-1)
the sum from j back to k (but we have to eliminate j because already counted), is the same as the sum from k to j-1 which is f(k, j-1) = s(j-1) - s(k-1)
The total answer is: s(j) - s(i-1) + s(j-1) - s(k-1).
The complexity of sfunction is O(1) so this should pass the test cases
Simpler formula for a range sum, including its derivation:
5 + 6 + 7 + 8
= (write all numbers twice and halve the sum)
(5 + 6 + 7 + 8 +
8 + 7 + 6 + 5) / 2
= (sum each vertical pair)
(13 + 13 + 13 + 13) / 2
=
4 * 13 / 2
=
(8 - 5 + 1) * (5 + 8) / 2
So in general for the sum from i to j: (j - i + 1) * (i + j) / 2
TLE is the case here. So you need to optimize your code.
For that, we can have two approaches.
1st approach: Simple looping
Apply a loop from i to j. And check if the current number is greater than or equal to k. If it is then add 2 times of current number. Else keep adding it once.
for n in range(i,j+1):
if n>=k:
sum+= 2*n
else:
sum+= n
2nd approach: Maths
We know that sum of first n integers is n*(n+1)/2
So what you can do is find sum till j, remove the sum till i (i excluded) from it.
Similarly, for k, find the sum till j and remove the sum till k (k excluded) from it.
Add remaining sums of both minus j as it will get considered twice.
i.e.
sum1 = j*(j+1)/2 - i*i(i-1)/2
sum2 = j*(j+1)/2 - k*(k-1)/2
ans = sum1+sum2 - j;

Efficiency when adding values from two lists

I'm trying to learn algorithms by writing a python application that tests out Fermat's last theorem. It iterates all combinations of a^n + b^n = c^n Where a/b hit a ceiling at 10000 and n hits a ceiling at 100. I realize I won't get any hits, but it's just a bit of fun. Anyway, the specifics don't really matter.
What it boils down to is a + b where a and b iterate all combinations 1 to 10000. But here's the problem: 4 + 5 is exactly the same as 5 + 4. So my program is doing twice the work it needs to do. How can I iterate these combinations while skipping over mirrored inputs?
base_ceiling = 10000 # max values for a and b
n_ceiling = 100 # max value for power of n
powers = []
for i in range(n_ceiling):
jarr = []
for j in range(base_ceiling):
jarr.append(j ** i)
powers.append(jarr)
for k in range(3, n_ceiling):
for i in range(1, base_ceiling):
for j in range(1, base_ceiling):
pow_vals = powers[k]
a = powers[k][i]
b = powers[k][j]
c = a + b
try:
idx = pow_vals.index(c)
if idx > -1:
print k, ": ", i, j, "=", idx, " results in ", a, b, "=", c
except ValueError:
continue
It's as simple as using for j in range(i, base_ceiling). This works because it will start from i instead of 1, so it doesn't repeat anything less than i. You could use i + 1 instead, because i^n + i^n will never be a power of n.

Code optimization - amount of combinations

There is a number C given (C is an integer) and there is given a list of numbers (let's call it N, all the numbers in list N are integers).
My task is to find the amount of possibilities to represent C.
For example:
input:
C = 4
N = [1, 2]
output:
3
Because:
4 = 1 + 1 + 1 + 1 = 1 + 1 + 2 = 2 + 2
My code is working pretty well for small numbers. However I have no idea how can I optimize it so it will work for bigger integers too. Any help will be appreciated!
There is my code:
import numpy
import itertools
def amount(C):
N = numpy.array(input().strip().split(" "),int)
N = list(N)
N = sorted(N)
while C < max(N):
N.remove(max(N))
res = []
for i in range(1, C):
for j in list(itertools.combinations_with_replacement(N, i)):
res.append(sum(list(j)))
m = 0
for z in range (0, len(res)):
if res[z] == C:
m += 1
if N[0] == 1:
return m + 1
else:
return m
Complexity of your algorithm is O(len(a)^ะก). To solve this task more efficiently, use dynamic programming ideas.
Assume dp[i][j] equals to number of partitions of i using terms a[0], a[1], ..., a[j]. Array a shouldn't contain duplicates. This solution runs in O(C * len(a)^2) time.
def amount(c):
a = list(set(map(int, input().split())))
dp = [[0 for _ in range(len(a))] for __ in range(c + 1)]
dp[0][0] = 1
for i in range(c):
for j in range(len(a)):
for k in range(j, len(a)):
if i + a[k] <= c:
dp[i + a[k]][k] += dp[i][j]
return sum(dp[c])
please check this first : https://en.wikipedia.org/wiki/Combinatorics
also this https://en.wikipedia.org/wiki/Number_theory
if i were you , i would divide the c on the n[i] first and check the c is not prim number
from your example : 4/1 = [4] =>integer count 1
4/2 = [2] => integer counter became 2 then do partitioning the [2] to 1+1 if and only if 1 is in the set
what if you have 3 in the set [1,2,3] , 4/3 just subtract 4-3=1 if 1 is in the set , the counter increase and for bigger results i will do some partitioning based on the set

Leaving the for / while loop if certain conditions are met

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.

Sum of even integers from a to b in Python

This is my code:
def sum_even(a, b):
count = 0
for i in range(a, b, 1):
if(i % 2 == 0):
count += [i]
return count
An example I put was print(sum_even(3,7)) and the output is 0. I cannot figure out what is wrong.
Your indentation is off, it should be:
def sum_even(a, b):
count = 0
for i in range(a, b, 1):
if(i % 2 == 0):
count += i
return count
so that return count doesn't get scoped to your for loop (in which case it would return on the 1st iteration, causing it to return 0)
(And change [i] to i)
NOTE: another problem - you should be careful about using range:
>>> range(3,7)
[3, 4, 5, 6]
so if you were to do calls to:
sum_even(3,7)
sum_even(3,8)
right now, they would both output 10, which is incorrect for sum of even integers between 3 and 8, inclusive.
What you really want is probably this instead:
def sum_even(a, b):
return sum(i for i in range(a, b + 1) if i % 2 == 0)
Move the return statement out of the scope of the for loop (otherwise you will return on the first loop iteration).
Change count += [i] to count += i.
Also (not sure if you knew this), range(a, b, 1) will contain all the numbers from a to b - 1 (not b). Moreover, you don't need the 1 argument: range(a,b) will have the same effect. So to contain all the numbers from a to b you should use range(a, b+1).
Probably the quickest way to add all the even numbers from a to b is
sum(i for i in xrange(a, b + 1) if not i % 2)
You can make it far simpler than that, by properly using the step argument to the range function.
def sum_even(a, b):
return sum(range(a + a%2, b + 1, 2))
You don't need the loop; you can use simple algebra:
def sum_even(a, b):
if (a % 2 == 1):
a += 1
if (b % 2 == 1):
b -= 1
return a * (0.5 - 0.25 * a) + b * (0.25 * b + 0.5)
Edit:
As NPE pointed out, my original solution above uses floating-point maths. I wasn't too concerned, since the overhead of floating-point maths is negligible compared with the removal of the looping (e.g. if calling sum_even(10, 10000)). Furthermore, the calculations use (negative) powers of two, so shouldn't be subject by rounding errors.
Anyhow, with the simple trick of multiplying everything by 4 and then dividing again at the end we can use integers throughout, which is preferable.
def sum_even(a, b):
if (a % 2 == 1):
a += 1
if (b % 2 == 1):
b -= 1
return (a * (2 - a) + b * (2 + b)) // 4
I'd like you see how your loops work if b is close to 2^32 ;-)
As Matthew said there is no loop needed but he does not explain why.
The problem is just simple arithmetic sequence wiki. Sum of all items in such sequence is:
(a+b)
Sn = ------- * n
2
where 'a' is a first item, 'b' is last and 'n' is number if items.
If we make 'a' and b' even numbers we can easily solve given problem.
So making 'a' and 'b' even is just:
if ((a & 1)==1):
a = a + 1
if ((b & 1)==1):
b = b - 1
Now think how many items do we have between two even numbers - it is:
b-a
n = --- + 1
2
Put it into equation and you get:
a+b b-a
Sn = ----- * ( ------ + 1)
2 2
so your code looks like:
def sum_even(a,b):
if ((a & 1)==1):
a = a + 1
if ((b & 1)==1):
b = b - 1
return ((a+b)/2) * (1+((b-a)/2))
Of course you may add some code to prevent a be equal or bigger than b etc.
Indentation matters in Python. The code you write returns after the first item processed.
This might be a simple way of doing it using the range function.
the third number in range is a step number, i.e, 0, 2, 4, 6...100
sum = 0
for even_number in range(0,102,2):
sum += even_number
print (sum)
def sum_even(a,b):
count = 0
for i in range(a, b):
if(i % 2 == 0):
count += i
return count
Two mistakes here :
add i instead of [i]
you return the value directly at the first iteration. Move the return count out of the for loop
The sum of all the even numbers between the start and end number (inclusive).
def addEvenNumbers(start,end):
total = 0
if end%2==0:
for x in range(start,end):
if x%2==0:
total+=x
return total+end
else:
for x in range(start,end):
if x%2==0:
total+=x
return total
print addEvenNumbers(4,12)
little bit more fancy with advanced python feature.
def sum(a,b):
return a + b
def evensum(a,b):
a = reduce(sum,[x for x in range(a,b) if x %2 ==0])
return a
SUM of even numbers including min and max numbers:
def sum_evens(minimum, maximum):
sum=0
for i in range(minimum, maximum+1):
if i%2==0:
sum = sum +i
i= i+1
return sum
print(sum_evens(2, 6))
OUTPUT is : 12
sum_evens(2, 6) -> 12 (2 + 4 + 6 = 12)
List based approach,
Use b+1 if you want to include last value.
def sum_even(a, b):
even = [x for x in range (a, b) if x%2 ==0 ]
return sum(even)
print(sum_even(3,6))
4
[Program finished]
This will add up all your even values between 1 and 10 and output the answer which is stored in the variable x
x = 0
for i in range (1,10):
if i %2 == 0:
x = x+1
print(x)

Categories