Ordering of evaluation using boolean or - python

So I've got this snippet of code. And it works (It says 1 is non-prime).:
n = 1
s = 'prime'
for i in range(2, n / 2 + 1):
if n == 1 or n % i == 0:
s= 'non-' +s
break
print s
My problem is that if I change the fourth line to: if n % i == 0 or n == 1:, it doesn't work (it says 1 is prime.)
Why is that? Since I'm using or should it be that either one of them is True so the order doesn't count?
(I'm still learning about boolean so I may be making some basic mistake.)
Thanks in advance!
EDIT: Thanks for the answers; I never realized my issue with the range() function. And about the code working and not working: I have no idea what happened. I may have made some mistake somewhere along the way (maybe forgot to save before running the script. Although I could've sworn that it worked differently :P ). Maybe I'm just getting tired...
Thanks for the answers anyways!

In both cases, the body of the loop does not run, because when 'n' is 1, it does not fall within the range of (n,n/2+1)
The code you posted says that 1 is prime (again, because the loop body does not execute at all)

The precedence is fine. % is evaluated first, then ==, then or, so it breaks down into:
___or___
/ \
== ==
/ \ / \
n 1 % 0
/ \
n i
Your problem is that your for loop is not being executed at all, so that s is still set to "prime".
The range 2,n/2+1 when n is 1 equates to 2,1 which will result in the body not being executed.
In fact it won't be executed where n is 2 either since 2/2+1 is 2 and the range 2,2 doesn't execute. The values are the start and terminating value, not start and end (last) value - it's just fortuitous there that 2 is considered a prime by virtue of the initialisation of s :-)
Try this instead:
#!usr/bin/python
n = 9
s = 'prime'
if n == 1:
s = 'non-prime'
else:
i = 2
while i * i <= n:
if n % i == 0:
s= 'non-prime'
break
i = i + 1
print s
It's wasteful going all the way up to n/2, the square root of n is all that's needed.

i think the problem is when n is 1, the loop is skipped.

Other answers already correctly addressed your specific problem (which, in other words, is that the loop executes only if n/2 + 1 > 2, that is, n/2 > 1, which means n > 2 with new-style division [[python 3 or suitable imports from the future or flags...]], n > 3 with classic style truncating division).
Wrt the specific question you posed:
Since I'm using or should it be that
either one of them is True so the
order doesn't count?
The order does count because or (like and) is a short-circuiting operator: specifically, or is guaranteed to go left to right, and stop if the left operand is true (because it does not need to know about the right one). This doesn't matter for your specific code, but it's crucial in cases such as, e.g.:
if i == 0 or n / i > 3: ...
If or wasn't going left-to-right (and stopping ASAP), the right-hand operand might get executed even when i equals 0 -- but then the division would raise an exception! With Python's rules, this code snippet won't raise exceptions (if i is an int, at least;-).
Again: this has nothing to do with the specific problem you're having (see other answers and the start of this one), but it's important for you to know for the future, so, since you asked, I took the opportunity to explain!-)

for n in range(101):
s = 'prime'
if n < 2 or not (n & 1): ## not(n & 1) == is even number (last bit 0) == not (n % 2)
s = 'non-'+s
else:
for i in range(3, int(n**0.5) + 1,2):
if not(n % i):
s= 'non-' +s
break
print "%i is %s" % (n,s)
You need not check all even numbers and you can stop the check at square root of n.

Related

Optimal placement of assert statements to assure correctness using invariant

I'm trying to understand invariants in programming via real examples written in Python. I'm confused about where to place assert statements to check for invariants.
My research has shown different patterns for where to check for invariants. For examples:
before the loop starts
before each iteration of the loop
after the loop terminates
vs
... // the Loop Invariant must be true here
while ( TEST CONDITION ) {
// top of the loop
...
// bottom of the loop
// the Loop Invariant must be true here
}
// Termination + Loop Invariant = Goal
Below I have put code for an invariant example from a Maths book. There are two version, one using a function and one not. I expect it makes no difference, but I want to be thorough.
My questions are:
what is the minimum number of assert statemnts I need to assure program correctness, in keeping with the invariant?
which of the assert statments in my examples are redundant?
If there are multiple answers to the above question, which would be considered best practice?
Ideally I'd like to see a rewriting of my code to include best pratices and attention to any issues I may have overlooked in my work so far.
Any input much appreciated.
Here's the exercise:
E2. Suppose the positive integer n is odd. First Al writes the numbers 1, 2,..., 2n on the blackboard. Then he picks any two numbers a, b, erases them, and writes, instead, |a − b|. Prove that an odd number will remain at the end.
Solution. Suppose S is the sum of all the numbers still on the blackboard. Initially this sum is S = 1+2+···+2n = n(2n+1), an odd number. Each step reduces S by 2 min(a, b), which is an even number. So the parity of S is an invariant. During the whole reduction process we have S ≡ 1 mod 2. Initially the parity is odd. So, it will also be odd at the end.
import random
def invariant_example(n):
xs = [x for x in range(1, 2*n+1)]
print(xs)
assert sum(xs) % 2 == 1
while len(xs) >= 2:
assert sum(xs) % 2 == 1
a, b = random.sample(xs, 2)
print(f"a: {a}, b: {b}, xs: {xs}")
xs.remove(a)
xs.remove(b)
xs.append(abs(a - b))
assert sum(xs) % 2 == 1
assert sum(xs) % 2 == 1
return xs
print(invariant_example(5))
n = 5
xs = [x for x in range(1, 2*n+1)]
print(xs)
assert sum(xs) % 2 == 1
while len(xs) >= 2:
assert sum(xs) % 2 == 1
a, b = random.sample(xs, 2)
print(f"a: {a}, b: {b}, xs: {xs}")
xs.remove(a)
xs.remove(b)
xs.append(abs(a - b))
assert sum(xs) % 2 == 1
assert sum(xs) % 2 == 1
print(xs)
The only technically redundant assert statement you have is either of the ones in the loop. As in, you don't really need both of them.
For example:
If you have both of them, the first assert in the while loop will execute immediately after the second (as the code will return to the top of the loop). No values change in between those calls, so the first assert statement will always have the same result as the second.
Best practice would probably be to keep the assert at the top of the loop, to prevent code within the loop from executing if the loop invariant is violated.
EDIT: The final assert statement should also include the loop exit condition, as Kelly Bundy noted. I forgot to mention this above.

Improving perfomance(speed) of exponent problem

I'm currently learning Python on repl.it and I have a problem with one of my work.
My code is supposed to:
1.Input a given integer X
2.Find the greatest integer n where 2ⁿ is less than or equal to X.
3.Print the exponent value(n) and the result of the expression 2ⁿ.
But my code fail as the machine insert too big number like 10^8+2. The program completely failed
Here is the piece of code that I'm working on:
X = int(input())
a = X//2
while a > -1:
if (2**a) < =x:
print(a)
print(2**a)
break
else:
a -= 1
Can anyone find me another solution to this problem, or improve the bit of code I'm working on by its runtime? It works with small number(less than 10^6) but otherwise the program freeze.
Thanks in advance!
Of course, I can't refer to the "too big input" that you mention (since you didn't provide it), but as for the problem itself, it could be easier solved in the following way:
import numpy as np
a = int(np.log2(your_input))
The first issue I see is that in you code
if (2**a) < =x:
print(a)
print(2**a)
you calculate the value of 2**a twice. A good start could be to save the value of 2**a into a variable. However, since you are only doing powers of 2 you could also take a look at bitwise operations. So instead of doing a = X//2 you could also write
a= X >> 2
and instead of doing 2**a write
temp = 1 << a
When working with powers of 2 it can be significantly faster to work with bitwise operations.
I did it! (using some of your solutions of course)
This is my teachers code :
x = int(input())
n = 1
while 2 ** n <= x:
n += 1
print(n - 1, 2 ** (n - 1))

error in "if" loop (Sage)

I'm using "Sage," but I do not think that it is relevant for this question.
I have made the following definitions, and attempted to implement an if loop:
Q = DiagonalQuadraticForm(ZZ,[1,1,1,1])
L = Q.representation_number_list(10)
for i in range(len(L)):
if L[i] == 0 % 2:
print i
Upon looking up Python demos, it seems as though my syntax is correct and (I haven't been made aware of any syntax errors.)
However, nothing is being printed! In fact, if I declare "i" in the next textbox, all that displays is "9," which doesn't change despite my fiddling with the modulus. What is wrong?
Modulus syntax in Python (and most other programming languages) is not the same as mathematical notation. In math, you write
a ≡ b (mod n)
to indicate that a and b are congruent modulo n. In programming languages, modulus is treated as an arithmetic operation on a and n, analogous with division (it returns the remainder of the division rather than the quotient). To determine if the number is congruent with another number, you compare that remainder with the number, so it's written as:
a % n == b
Therefore, your if statement should be:
if L[i] % 2 == 0:
When you write
if L[i] == 0 % 2:
it's parsed as:
if L[i] == (0 % 2):
And since the remainder of 0 / 2 is 0, it's equivalent to:
if L[i] == 0:
which isn't what you intended.
You intend to print even numbers? This should work:
Q = DiagonalQuadraticForm(ZZ,[1,1,1,1])
L = Q.representation_number_list(10)
for i, v in enumerate(L):
if v % 2 == 0:
print i
enumerate(...) can replace range(len(...))

Python while loop speed

I would like it if someone could please explain to me why the following code has so much additional overhead. At 100k iterations, the speed is the same for either case (2.2 sec). When increasing to 1E6 iterations case "B" never finishes, while case "A" takes only 29 seconds.
Case "A"
while n is not 1:
foo
Case "B"
while n > 1:
foo
Complete code if of any help
def coll(n):
count = 0
# while n is not 1:
while n > 1:
count += 1
if not n % 2:
n /= 2
else:
n = 3*n + 1
return count
for x in range(1,100000):
count = coll(x)
First of all, you should use n > 1 or n != 1, not n is not 1. The fact that the latter works is an implementation detail, and obviously it's not working for you.
The reason it's not working is because there are values of x in your code that cause the Collatz sequence to go over the value of sys.maxint, which turns n into a long. Then, even when it ends up going back down to 1, it's actually 1L; a long, not an int.
Try using while n is not 1 and repr(n) != '1L':, and it'll work as you expect. But don't do that; just use n > 1 or n != 1.
Generally in Python, is is extremely fast to check, as it uses referential equality, so all that needs to be checked is that two objects have the same memory location. Note that the only reason your code works is that most implementations of Python generally maintain a pool of the smaller integers, so that every 1 always refers to the same 1, for example, where there may be multiple objects representing 1000. In those cases, n is 1000 would fail, where n == 1000 would work. Your code is relying on this integer pool, which is risky.
> involves a function call, which is fairly slow in Python: n > 1 translates to n.__gt__(1).

Python Syntax Problem

I'm just getting back into Project Euler and have lost my account and solutions, so I'm back on problem 7. However, my code doesn't work. It seems fairly elementary to me, can someone help me debug my (short) script?
Should find the 10001st Prime.
#!/usr/bin/env python
#encoding: utf-8
"""
P7.py
Created by Andrew Levenson on 2010-06-29.
Copyright (c) 2010 __ME__. All rights reserved.
"""
import sys
import os
from math import sqrt
def isPrime(num):
flag = True
for x in range(2,int(sqrt(num))):
if( num % x == 0 ):
flag = False
if flag == True:
return True
else:
return False
def main():
i, n = 1, 3
p = False
end = 6
while end - i >= 0:
p = isPrime(n)
if p == True:
i = i + 1
print n
n = n + 1
if __name__ == '__main__':
main()
Edit*: Sorry, the issue is it says every number is prime. :/
The syntax is fine (in Python 2). The semantics has some avoidable complications, and this off-by-one bug:
for x in range(2,int(sqrt(num))):
if( num % x == 0 ):
flag = False
range(2, Y) goes from 2 included to Y excluded -- so you're often not checking the last possible divisor and thereby deeming "primes" many numbers that aren't. As the simplest fix, try a 1 + int(... in that range. After which, removing those avoidable complications is advisable: for example,
if somebool: return True
else: return False
is never warranted, as the simpler return somebool does the same job.
A simplified version of your entire code (with just indispensable optimizations, but otherwise exactly the same algorithm) might be, for example:
from math import sqrt
def isPrime(num):
for x in range(3, int(1 + sqrt(num)), 2):
if num % x == 0: return False
return True
def main():
i, n = 0, 3
end = 6
while i < end:
if isPrime(n):
i += 1
print n
n += 2
if __name__ == '__main__':
main()
"Return as soon as you know the answer" was already explained, I've added one more crucial optimization (+= 2, instead of 1, for n, as we "know" even numbers > 3 are not primes, and a tweak of the range for the same reason).
It's possible to get cuter, e.g.:
def isPrime(num):
return all(num % x for x n range(3, int(1 + sqrt(num)), 2))
though this may not look "simpler" if you're unfamiliar with the all built-in, it really is, because it saves you having to do (and readers of the code having to follow) low level logic, in favor of an appropriate level of abstraction to express the function's key idea, that is, "num is prime iff all possible odd divisors have a [[non-0]] remainder when the division is tried" (i.e., express the concept directly in precise, executable form). The algorithm within is actually still identical.
Going further...:
import itertools as it
def odd():
for n in it.count(1):
yield n + n + 1
def main():
end = 5
for i, n in enumerate(it.ifilter(isPrime, odd())):
print n
if i >= end: break
Again, this is just the same algorithm as before, just expressed at a more appropriate level of abstraction: the generation of the sequence of odd numbers (from 3 included upwards) placed into its own odd generator, and some use of the enumerate built-in and itertools functionality to avoid inappropriate (and unneeded) low-level expression / reasoning.
I repeat: no fundamental optimization applied yet -- just suitable abstraction. Optimization of unbounded successive primes generation in Python (e.g. via an open-ended Eratosthenes Sieve approach) has been discussed in depth elsewhere, e.g. here (be sure to check the comments too!). Here I was focusing on showing how (with built-ins such as enumerate, all, and any, the crucial itertools, plus generators and generator expressions) many "looping" problems can be expressed in modern Python at more appropriate levels of abstraction than the "C-inspired" ones that may appear most natural to most programmers reared on C programming and the like. (Perhaps surprisingly to scholars used to C++'s "abstraction penalty" first identified by Stepanov, Python usually tends to have an "abstraction premium" instead, especially if itertools, well known for its blazing speed, is used extensively and appropriately... but, that's really a different subject;-).
Isn't this better?
def isPrime(num):
for x in range(2,int(sqrt(num))):
if( num % x == 0 ):
return False
return True
And this:
def main():
i, n = 1, 3
while i <= 6:
if isPrime(n):
i = i + 1
print n
n = n + 1
Also, I'm not seeing a 10001 anywhere in there...

Categories

Resources