How to stop repetition in my code? - python

This code executes primes upto a given number. It works correctly as far as the prime generation is concerned but the output is painfully repetitive.
The code is:
numP = 1
x = 3
y = int(input('Enter number of primes to be found: '))
while numP<=y:
for n in range(2, x):
for b in range(2, n):
if n % b == 0:
break
else:
# loop fell through without finding a factor
print (n)
x += 2
numP += 1
The output is like (e.g. for y=4):
2
2
3
2
3
5
2
3
5
7
I want to avoid repetition and obtain output like:
2
3
5
7
How should the code be modified?

If you store the data in a set, you will avoid repetitions

There's no reason to loop n from 2..x. Get rid of that loop, and replace all references to 'n' with 'x'. I.e.:
def find_primes(y):
x = 3
numP = 0
while True:
for b in range(2, x):
if x % b == 0:
break
else:
# loop fell through without finding a factor
print (x)
numP += 1
if numP >= y:
return
x += 2

Related

Python project euler [duplicate]

This question already has answers here:
How to find the sum of all the multiples of 3 or 5 below 1000 in Python?
(19 answers)
Closed 1 year ago.
I'm just starting to learn python, I tried to solve the first problem of project euler with python but I can't figure out a way to find the sum of my variables.
the question was to find the sum of all the multiples of 3 or 5 below 1000.
I tried this
def f(a):
for x in range(a):
if(x % 3 == 0 or x % 5 == 0):
i = 0
i = sum({x})
print(i)
f(100)
But it doesn't work, it just gives the value 99, and I have no idea why.I want to adapt it to a function like this.
Thank you in advance.
Try this:
def f(a):
foo = []
for x in range(a):
if(x % 3 == 0 or x % 5 == 0):
foo.append(x)
print(sum(foo))
f(100)
Or in one line using list comprehensions:
print(sum([i for i in range(some_value) if (i % 3 == 0 or i % 5 == 0)]))
There are quite a few errors in your code:
First of all, i = 0 is irrelevent to the rest of your code. All it's doing is defining i to be 0 after each iteration of the for loop.
Then, you are just taking the sum of the last number, because the other values are wiped out after each iteration.
So, what's the solution to this?
Creating a list to append to, so you have access to each value in a iterations:
l = []
def f(a):
for i in range(a):
if i % 3 == 0 or i % 5 == 0:
l.append(i)
print(sum(l))
f(100)
Output:
>>> 2318
How about this, it has limit of 1000 and does not use a list.
def is_multiple(x, a):
"""Returns true if x is a multiple of a"""
return x % a == 0
def f(a):
total = 0
for i in range(a+1): # tests from 0 to 100 if a is 100
if i >= 1000:
break # we don't process 1000 and above, get out of loop
if is_multiple(i, 3) or is_multiple(i, 5):
total += i # increment our total variable
return total
# Tests
n = 100
t = f(n)
print(f'num: {n}, total: {t}')
# num: 100, total: 2418
n = 1200
t = f(n)
num = f(n)
print(f'num: {n}, total: {t}')
# num: 1200, total: 233168

Trouble optimising magic square generation

I'm still fairly new to programming and am currently attempting to generate a magic square based on the users input. I have managed to create some sort of abomination that works fine for a 3x3 square. The problem I'm having is that because I randomly generate a square without checking if the combination has been used before, anything bigger than 3x3 takes a huge amount of time to compute. Are there any modifications I can make to speed up the process? Apologies if I haven't formatted correctly.
Thanks in advance!
import random
import math
'''Checks if the diagonals add up to the magic sum (calculated below).'''
def diagonal_check(bList, point):
reversedDiagonalCount = 0
diagonalCount = 0
if point == 0:
for diagonal in range(magicSquareSize):
diagonalCount += bList[diagonal][diagonal]
else:
for reversedDiagonal in range(magicSquareSize):
reversedDiagonalCount += bList[-(reversedDiagonal+1)]
[reversedDiagonal]
if diagonalCount == magicNumber or reversedDiagonalCount == magicNumber:
return True
else:
return False
'''Iterates through column and row number "x" to see if both add up to the
magic sum.'''
def check_magic_sum(aList, x):
columnCount = 0
rowCount = 0
for columnNumber in range(magicSquareSize):
columnCount += aList[columnNumber][x]
if columnCount == magicNumber:
for rowNumber in range(magicSquareSize):
rowCount += aList[x][rowNumber]
print(columnCount, rowCount)
if columnCount == magicNumber and rowCount == magicNumber:
return True
else:
return False
'''Once initiated, created a randomly generated n x n matrix of numbers.'''
def create_square():
for number in range(1, magicSquareSize**2 + 1):
numberList.append(number)
for row in range(magicSquareSize):
currentList = []
magicNumberCount = magicNumber
magicSquareSizeCount = magicSquareSize
while len(currentList) < magicSquareSizeCount:
rowEntry = random.choice(numberList)
numberList.remove(rowEntry)
currentList.append(rowEntry)
magicNumberCount -= rowEntry
magicSquare.append(currentList)
'''User inputs the grid size they would like, a magic number is then
calculated for this value.'''
magicSquareSize = int(input('Please enter a number, "n" to generate an "n x
n" magic square: '))
magicNumber = int((magicSquareSize/2) * (2+(magicSquareSize**2 - 1)))
'''Initiates an empty list to hold the magic square and the numbers used in
it.'''
numberList = []
magicSquare = []
create_square()
'''Checks magic square to see if it is valid, if not, creates another
randomly generated square and checks again.'''
while True:
validSquare = 0
for checkNumber in range(magicSquareSize):
numberCheck = check_magic_sum(magicSquare, checkNumber)
if numberCheck == True:
validSquare += 1
if checkNumber == 0 or checkNumber == magicSquareSize-1:
isDiagonalGood = diagonal_check(magicSquare, checkNumber)
if isDiagonalGood == True:
validSquare += 1
if validSquare == magicSquareSize + 2:
break
else:
magicSquare = []
create_square()
'''Prints each element in the magicSquare list one by one to display a
roughly square shape.'''
for line in range(magicSquareSize):
print(magicSquare[line])
The magic square problem is NP-hard so it will be time-consuming to find a solution for N>=4. The problem can be formulated as a CSP (constraint satisfaction problem) and with constraint package we can try to solve it for a general N like the following, you may try to see if this approach is faster:
N = 4 #5 # number of rows / columns
n = N**2 # number of cells
s = n*(n+1)//6 # sum of each row
from constraint import *
p = Problem()
p.addVariables(range(n), range(1, n+1))
p.addConstraint(AllDifferentConstraint(), range(n))
p.addConstraint(ExactSumConstraint(s), [k*(N+1) for k in range(N)])
p.addConstraint(ExactSumConstraint(s), [(k+1)*(N-1) for k in range(N)])
for row in range(N):
p.addConstraint(ExactSumConstraint(s),
[row*N+i for i in range(N)])
for col in range(N):
p.addConstraint(ExactSumConstraint(s),
[col+N*i for i in range(N)])
sols = p.getSolutions()
for s in sols:
for row in range(N):
for col in range(N):
print s[row*N+col],
print
print
For N=3 it is very fast and immediately prints all possible solutions:
6 7 2
1 5 9
8 3 4
6 1 8
7 5 3
2 9 4
8 1 6
3 5 7
4 9 2
8 3 4
1 5 9
6 7 2
4 3 8
9 5 1
2 7 6
4 9 2
3 5 7
8 1 6
2 7 6
9 5 1
4 3 8
2 9 4
7 5 3
6 1 8

Python prime number generator prints out every number

I made this prime number generator but it just prints every number (1, 2, 3...).
I am aware that there are other questions about this but I don't understand any of them. Here is what I have so far:
x = 1
y = 1
while x >= y:
if x % y == 0:
print(x)
x = x + 1
y = 1
else:
y = y + 1
y = 1
From your question, I think, it would be better try this way :
n = 10
i = 2
while i < n :
prime = 1 # reset the `prime` variable before the inner loop
for a in range(2, i):
if i%a == 0:
prime = 0
break
if prime:
print (i)
i += 1
Output :
2
3
5
7
There's something called a rubber ducky test where you explain your code, step by step, to a rubber duck. It forces you to walk through every step and you'll often find the error. In this case, think about what y is when you do x%y. You'll see that y=1 the first time this is called. So it will iterate through the loop incrementing x by 1 and y will remain set it 1. And x%y when y=1 will always be...

Print the collatz sequence of a positive int, n, one value per line stoping at 1 using python

I've done:
def collatz(n):
seq = n
if n == 1:
n = n
while n > 1:
if n % 2 == 0:
n = n // 2
else:
n = 3 * n + 1
print(seq)
The corrct output for calling this function, while n = 10:
collatz(10)
10
5
16
8
4
2
1
But the only number printed is n itself.
The issue is that you are only printing seq which was set to n at start of the function, after the while loop has executed. Hence you only get the value printed once.
You should print the value inside the while loop as well as at start (for the first 10 print). Example -
def collatz(n):
print(n)
while n > 1:
if n % 2 == 0:
n = n // 2
else:
n = 3 * n + 1
print(n)
Demo -
>>> def collatz(n):
... print(n)
... while n > 1:
... if n % 2 == 0:
... n = n // 2
... else:
... n = 3 * n + 1
... print(n)
...
>>> collatz(10)
10
5
16
8
4
2
1
You need to print once for every step within your loop. Your print statement is outside your while loop hence it only fires once.
Additionally, you want to print the value that is changing n not seq which never chances in this function.
On that note, you don't even need seq as you never use it!
The two lines if n == 1: n = n don't do anything. Even if n==1, setting n to itself doesn't change the value.

How to find the sum of all the multiples of 3 or 5 below 1000 in Python?

Not sure if I should've posted this on math.stackexchange instead, but it includes more programming so I posted it here.
The question seems really simple, but I've sat here for at least one hour now not figuring it out. I've tried different solutions, and read math formulas for it etc but it won't gives me the right answer when coding it! I made two different solutions for it, which both gives me the wrong answer. The first solution gives me 265334 while the second one gives me 232169. The answer is 233168, so the second solution is closer.
I should mention this is a question from Project Euler, the first one to be precise.
Here's my code. Any ideas what's wrong?
nums = [3, 5]
max = 999
result = 0
for num in nums:
for i in range(1,max):
if num*i < max:
result += num*i
print result
result = 0
for i in range(0,max):
if i%3 == 0 or i%5 == 0:
result += i
print result
You are overcomplicating things. You just need a list of numbers that are multiples of 3 or 5 which you can get easily with a list comprehension:
>>> [i for i in range(1000) if i % 3 == 0 or i % 5 == 0]
Then use sum to get the total:
>>> sum([i for i in range(1000) if i % 3 == 0 or i % 5 == 0])
<<< 233168
Or even better use a generator expression instead:
>>> sum(i for i in range(1000) if i % 3 == 0 or i % 5 == 0)
Or even better better (courtesy Exelian):
>>> sum(set(list(range(0, 1000, 3)) + list(range(0, 1000, 5))))
range(k,max) does not include max, so you're really checking up to and including 998 (while 999 is a multiple of 3). Use range(1,1000) instead.
I like this the most:
def divisibles(below, *divisors):
return (n for n in xrange(below) if 0 in (n % d for d in divisors))
print sum(divisibles(1000, 3, 5))
The problem with your first solution is that it double-counts multiples of 15 (because they are multiples of both 3 and 5).
The problem with your second solution is that it doesn't count 999 (a multiple of 3). Just set max = 1000 to fix this.
result = 0
for i in range(0,1000):
if (i % 3 == 0 or i % 5 == 0):
print i
result = result + i
print result
Output:
0
3
5
6
9
.
.
.
993
995
996
999
233168
max = 1000 # notice this here
result = 0
for i in range(0,max):
if i%3 == 0 or i%5 == 0:
result += i
print result
This works, but use 1000 for max, so it includes 999 too.
I know this was 3 months ago but as an experiment because I am new to python I decided to try and combine some of the other people answers and I came up with a method you can pass the max number to and the divisors as a list and it returns the sum:
def sum_of_divisors(below, divisors):
return sum((n for n in xrange(below) if 0 in (n % d for d in divisors)))
max = 1000
nums = [3, 5]
print sum_of_divisors(max, nums)
There are floor(999/3) multiples of 3, floor(999/5) multiples of 5, and floor(999/15) multiples of 15 under 1000.
For 3, these are: 3 + 6 + 9 + 12 +... + 999 = 3 * (1 + 2 + 3 + 4 +...+333)
= 3 * (333 * 334 / 2) because the sum of the integers from 1 to k is k*(k+1)/2.
Use the same logic for the sum of multiples of 5 and 15. This gives a constant time solution. Generalize this for arbitrary inputs.
I know this is from 6 years ago but I just thought id share a solution that found from a math formula that I thought was interesting as it removes the need to loop through all the numbers.
https://math.stackexchange.com/a/9305
def sum_of_two_multiples(nums, maxN):
"takes tuple returns multiples under maxN (max number - 1)"
n1, n2 = nums = nums[:2]
maxN -= 1
def k(maxN, kx):
n = int(maxN / kx)
return int(kx * (0.5 * n * (n+1)))
return sum([k(maxN, n) for n in nums]) - k(maxN, n1*n2)
Outputs the follows
print(sum_of_two_multiples((3,5), 10))
# 23
print(sum_of_two_multiples((3,5), 1000))
# 233168
print(sum_of_two_multiples((3,5), 10**12))
# 233333333333166658682880
I think only the last few lines from your code are important.
The or statement is the key statement in this code.
Also rater than setting the max value to 999, you should set it to 1000 so that it will cover all values.
Here is my code.
ans=0
for i in range(1,1000):
if(i%3==0 or i%5==0):
ans += i
print(ans)
input('press enter key to continue');#this line is only so that the screen stays until you press a key
t = int(input())
for a in range(t):
n = int(input().strip())
sum=0
for i in range(0,n):
if i%3==0 or i%5==0:
sum=sum+i
print(sum)
You can also use functional programming tools (filter):
def f(x):
return x % 3 == 0 or x % 5 == 0
filter(f, range(1,1000))
print(x)
Or use two lists with subtraction of multiples of 15 (which appears in both lists):
sum1 = []
for i in range(0,1000,3):
sum1.append(i)
sum2 = []
for n in range(0,1000,5):
sum2.append(n)
del sum2[::3] #delete every 3-rd element in list
print(sum((sum1)+(sum2)))
I like this solution but I guess it needs some improvements...
here is my solution:
for n in range(100):
if n % 5==0:
if n % 3==0:
print n, "Multiple of both 3 and 5" #if the number is a multiple of 5, is it a multiple of 3? if yes it has has both.
elif n % 5==0:
print n, "Multiple of 5"
elif n % 3==0:
print n, "Multiple of 3"
else:
print n "No multiples"
this is my solution
sum = 0
for i in range (1,1000):
if (i%3)==0 or (i%5)==0:
sum = sum + i
print(sum)
count = 0
for i in range(0,1000):
if i % 3 == 0 or i % 5 ==0:
count = count + i
print(count)
I know it was 7 years ago but I wanna share my solution to this problem.
x= set()
for i in range(1,1001):
if (i % 3) == 0:
x.add(i)
for j in range(1,1001):
if (j % 5) == 0:
x.add(j)
print(sum(x))
I had to do it in range 1 , 100
This is how I did it.
For i in range(1,100):
If i ÷ 3 == 0 and i ÷ 5 == 0:
print(i)
So with 1000 you just change the 100 to 1000
I had to find the multiples of 3 and 5 within 100 so if you need 3 or 5 just change it to or and it will give you more answers too. I'm just starting to learn so correct me if I'm wrong
Here is the code:
count = 1000
m = [3, 5, 3*5]
result = 0
Sum = 0
for j in m:
result = 0
for i in range(count):
if i*j < 1000:
result = result + i*j
elif i == (count - 1):
if j < 15:
Sum = result + Sum
elif j == 15:
Sum = Sum - result
print(Sum)
total = 0
maxrange = input("Enter the maximum range") #Get the maximum range from the keyboard
print("")
max = int(maxrange)
for i in range (0,max):
if i%3 == 0 or i%5 ==0:
total = total +i
print (total)

Categories

Resources