x = y // 2 # For some y > 1
while x > 1:
if y % x == 0: # Remainder
print(y, 'has factor', x)
break # Skip else
x -= 1
else: # Normal exit
print(y, 'is prime')
This is an example for understanding while loop in a book I'm reading, I don't quite understand why a floor division and then y % x? Can someone please explain this piece of code, whats it doing?
Thanks!
This is a lame primality test.
% is the mod operator. It performs division and returns the remainder rather than the result of the division. For example, 5 // 2 == 2, and 5 % 2 == 1.
Commented:
x = y // 2 # For some y > 1 ##Reduce search space to half of y
while x > 1:
if y % x == 0: # Remainder ##If x divides y cleanly (4 / 2 == 2)
print(y, 'has factor', x) ##y is not prime
break # Skip else ##Exit the loop
x -= 1 # Normal exit ##Try the next value
else:
print(y, 'is prime')
The program prints at least one factor of an integer y, or if it has no factors (other than itself and 1), prints that y is prime.
It uses the variable x to try all possible factors greater than one. It starts at the floor of y divided by 2, because no number larger than half of y could be a factor. Using normal division rather than floor division could give you a fractional value if y is odd. (An even better solution is to start with the square root of y - if y is not prime, one of its factors will be less than or equal to its square root.)
Inside the loop, it tests y % x, which is the remainder after dividing y by x. If the remainder is zero, that means that x is a factor of y, and it prints it.
The else clause is executed at the end of the loop, unless a factor is found, in which case the "break" skips out of the loop and the else clause. So either a factor is found, or it's prime.
Here's the improved code with the indentation fixed:
import math
def check_primality(y):
x = int(math.sqrt(y))
while x > 1:
if y % x == 0:
print y, 'has factor', x
break
x -= 1
else:
print y, 'is prime'
The code simply checks if the square root of x has been reached. Note that you can check the primality of a number by checking if the integers from 2 up to the square root of x divides x perfectly (without a remainder).
the logic is:
if y modulo x is 0, it means that x is a dividor of y, so y has a factor. print that, and break out of the loop.
if not, decrease x by 1, and try again.
but some things are broken in this code:
the else statement position
the fact the 'print y is prime' is after the loop - it will always print it.
For any number (x) which is not prime, there would be a factor greater than 1 and less than (x/2).
9 = 3*3
The logic is to iterate through all the numbers <= x/2 and check if the number divides.
I think the program tries to find the biggest prime factors of y.
If y is a prime factor it prints this as well.
x = y // 2 is for testing the numbers in the range x: 2..y/2.
A better approach would be to test only the numbers x: 2..sqrt(y)
the % denotes a modulus which gives you the remainder of division...
and this code checks for prime Y and also checks if Y is a multiplier of x...
x = y // 2 #x=the division or modulus of y , 2
while x > 1: #you want to check if this is a division result or a modulus
if y % x == 0: # if y is a multiplier of x
print(y, 'has factor', x)
break # break the while loop
x -= 1 # decreament x
else: # this line executes if the wihle reached x > 1 and didnt break
print(y, 'is prime')
so if y is a multiplier of x it will decreament x and the loop continue
otherwise it will print y is prime
Related
So, basically I have to built an algorithm that tells me how many times X is divisible by Y. If its not divisible, it should return print -1.
Here's what i've got so far:
def divisible(x, y):
n = int(x/y)
if (n != 0 and x%y == 0):
print(x, "its divisible by",y,n,"times")
else:
print(-1)
divisible(5, 2)
The exercise its asking to use a counter to do this. How can I make It?
Thanks
Integer division and the modulo function should get you there -
divisible = lambda x, y: x // y if x % y == 0 else -1
divisible(13, 3)
# -1
divisible(12, 3)
# 4
def divisible (x, y):
# Initialize times to keep track of how many times x is
# divisible by y:
times = 0
# Enter an infinite loop:
while True:
# If the remainder of x divided by y is 0
# (= if x is divisible by y):
if ( x % y == 0 ):
# Increment times by 1 and actually divide x by y:
times += 1
x = x / y
# If x is *not* divisible by y, break out of the infinite loop:
else:
break
# If the original x was not divisible by y at all, return -1
# (otherwise, keep times unchanged):
if times == 0:
times = -1
return times
print(divisible(2, 2))
# 1
print(divisible(3, 2))
# -1
print(divisible(8, 2))
# 3
print(divisible(10000, 2))
# 4
I was writing the solution to this codewars problem however I've ran into a bit of an issue.
Problem statement:
Write a function, persistence, that takes in a positive parameter num and returns its multiplicative persistence, which is the number of times you must multiply the digits in num until you reach a single digit, e.g.:
persistence(39) # returns 3, because 39=27, 27=14, 1*4=4 and 4 has only one digit
def persistence(n, t=1, x=0):
if len(str(n)) > 1:
number = [int(i) for i in str(n)]
for i in number:
t = t * i
if len(str(t)) > 1:
x += 1
return(persistence(t,x))
else:
return(x)
else:
return 0
I can't quite figure out what the error is in this code. My hunch is that it's either a parameter error or the way the return() value is placed.
In essence, the code for distilling an integer to it's multiples is correct, so I just added an extra parameter to persistence; setting x = 0 and making it so that each time the if condition was fulfilled it would increment that exact x value. Once the number was distilled, simply output x. Yet it continues to simply output 0 as the final answer. What's the problem here?
Edit: Solution was in the comments, didn't realise how the parameters were passing. Correct version is:
return(persistence(t,1,x))
Also had to set x = 1 for the logic to work on codewars.
There are 2 flaws in Your code:
return(persistence(t,x))
should be
return(persistence(t,1,x))
otherwise the value of x will be assigned to t and x will be defaulted to 0.
Then you must increment x directly after the first test, otherwise You will miss one iteration.
Another way to calculate this is not to switch over to strings, but to do it numerically:
def persistence(n):
iterations = 0; # no iterations yet
while n > 9: # while n has more than 1 digit:
product = 1 # neutrum for result product
while n > 0: # while there a digit to process:
digit = n % 10 # retrieve the right most digit
product *= digit # do the multiplication
n = n // 10 # cut off the processed digit
iterations += 1 # increment iterations
n = product # let n be the newly calculated product
return iterations # return the result
I think you your function's parameters work not as you expect them to do.
When you call function persistence(t, x), the first argument n should become t, and second argument x, should become new x. But in your function, x becomes new t because of their position.
It is quite useful to have bunch of print statements to reveal the bug.
def persistence(n, x=1, t=1):
print('x:', x)
if len(str(n)) > 1:
number = [int(i) for i in str(n)]
for i in number:
t = t * i
print('t:', t)
if len(str(t)) > 1:
x += 1
print('x has changed:', x)
return persistence(t, x)
else:
return x
else:
return 0
print(persistence(39))
print('---------------')
print(persistence(999))
print('---------------')
print(persistence(4))
Passes all test cases with two changes:
You were not updating your n with the new t everytime
Your x was being set to 0 every time. That should be set to 1 in the beginning (default value)
def persistence(n, t=1, x=1):
if len(str(n)) > 1:
number = [int(i) for i in str(n)]
for i in number:
t = t * i
if len(str(t)) > 1:
x += 1
return (persistence(n=t, x=x))
else:
return (x)
else:
return 0
Actually, you can write it without needing both parameters t and n. Just one n is fine as shown below:
def persistence(n, x=1):
if len(str(n)) > 1:
number = [int(i) for i in str(n)]
t = 1
for i in number:
t = t * i
if len(str(t)) > 1:
return x + (persistence(n=t, x=x))
else:
return (x)
else:
return 0
I want to check if number, based on lower and upper bound, has prime divisors only 3 and 5 and number should be multiplication of power of 3 and power of 5. My current solution is this. I want to optimize it, since checking powers with for loops isn't good way in my opinion. Thanks in advance.
def checkNum(x):
for i in range(1,50):
for j in range(1,50):
return x == (3**i) * (5**j)
def printResult(l, r):
for i in range(l,r):
if checkNum(i):
print(i)
Based on comments I think this is the best way:
def checkNum(x):
while x%3==0:
x = x //3
while x%5==0:
x = x//5
return x==1
I want to optimize it, since checking powers with for loops isn't good
way in my opinion.
Over a range of random numbers, we improve its speed by doing:
def checkNum0(x):
if x % 2 == 0: # eliminate half the numbers in one test!
return False
while x % 15 == 0: # speed up the process
x = x // 15
while x % 5 == 0:
x = x // 5
while x % 3 == 0:
x = x // 3
return x == 1
Or we can use a nested loop and combine both divisions into one:
def checkNum(x):
if x % 2 == 0: # eliminate half the numbers in one test!
return False
for divisor in (15, 5, 3):
while (quotient_remainder := divmod(x, divisor))[1] == 0:
x = quotient_remainder[0]
return x == 1
I'm a beginner working with Python and I was given this task: write a function which returns the highest perfect square which is less or equal to its parameter (a positive integer).
def perfsq(n):
x = 0
xy = x * x
if n >= 0:
while xy < n:
x += 1
if xy != n:
print (("%s is not a perfect square.") % (n))
x -= 1
print (("%s is the next highest perfect square.") % (xy))
else:
return(print(("%s is a perfect square of %s.") % (n, x)))
When I run the code to execute the function it doesn't output anything. I'll admit, I'm struggling and if you could give me some advice on how to fix this, I would be grateful.
your loop condition which is
while xy < n:
this will be true always as xy is always 0 and n is always greater then zero if you will call the function with n = 0, it will print 0 is a perfect square of 0. and will return None.
for n > 0
why it is always true in the case of xy < n because you have assigned xy 0 and never modified it to anyother value when a loop runs it check the condition and it will always get True
Like Patrick Haugh says, try examining when the while loop exits. It can be helpful to put print() statements throughout your method to figure out how your method executes. In order to figure out when your loop exits, look at the exit condition of your while loop: xy < n.
Remember, a variable isn't updated until you update it.
def perfsq(n):
x = 0
xy = x * x
print("xy: {}".format(xy))
if n >= 0:
while xy < n:
x += 1
print("xy in loop: {}".format(xy))
if xy != n:
print (("%s is not a perfect square.") % (n))
x -= 1
print (("%s is the next highest perfect square.") % (xy))
else:
return(print(("%s is a perfect square of %s.") % (n, x)))
I see your mistake, and it's an easy one for someone to make. When you define
xy = x*x
the computer calculates x*x and assigns that number to be the value of xy. So when you then add one to x it does not change the value of xy. You have to tell the computer to recalculate xy every time:
while xy < n:
x += 1
xy = x*x
def perfsq(n):
x = 0
xy = x * x
if n >= 0:
while xy < n:
x += 1
xy = x*x <-- Here
if xy != n:
print (("%s is not a perfect square.") % (n))
x -= 1
xy = x*x <--Here
print (("%s is the next highest perfect square.") % (xy))
else:
print(("%s is a perfect square of %s.") % (n, x)) <--And here
Think about that.
I am trying to solve problem 4 in project Euler which is:
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 × 99.
Find the largest palindrome made from the product of two 3-digit numbers.
The initial code that I wrote is:
def check_reversed(number):
number = str(number)
if number == number[::-1]:
return True
for x in range(100,1000):
for y in range(100,1000):
if check_reversed(x*y) == True:
print x,y,x*y
For some reason the second loop stops at number 583 and outputs the wrong answer. When I change the range though of the second "for" loop to (584,1000), it outputs the correct answer.
My question is why does the second loop ends at number 583?
EDIT : SOLVED: (Thank you for your help!)
def check_reversed(number):
number = str(number)
return number == number[::-1]
max_pal = 0
for x in range(100,1000):
for y in range(100,1000):
if check_reversed(x*y) == True:
if x*y > max_pal:
max_pal = x*y
print max_pal
Your second loop doesn't end at 583 at all; 583 just happens to be the highest y for x = 995 that is a palindrome.
Two lines earlier, your code prints:
993 913 906609
which clearly contradict your analysis.
You need to track the maximum result and not assume that the maximum x gives you the answer.
Note that there is little point in testing the same numbers for y each loop; no need to test the product of range(100, 1000) when combinations will do:
from itertools import combinations
def check_reversed(x, y):
number = str(x * y)
return number == number[::-1]
x, y = max((c for c in combinations(range(100, 1000), r=2) if check_reversed(*c)),
key=lambda c: c[0] * c[1])
print x, y, x * y
your loops just work fine because the last two numbers in your conditions are 995 583
however this script solves your problem
def check_reversed(number):
number = str(number)
if number == number[::-1]:
return True
temp = 0
for x in range(100,1000):
for y in range(100,1000):
if check_reversed(x*y) and temp <= x*y:
temp = x * y
print x,y,x*y