I was wondering what the equivalent in python to this would be:
n = 100
x = (10 < n) ? 10 : n;
print x;
For some reason this does not work in Python. I know I can use an if statement but I was just curious if there is some shorter syntax.
Thanks.
x = min(n, 10)
Or, more generally:
x = 10 if 10<n else n
Here is the ternary operator in Python (also know as conditional expressions in the docs).
x if cond else y
There are various ways to make a ternary operation, the first one is the expression added with 2.5:
n = foo if condition else bar
If you want to be compatible with versions lower than 2.5 you can exploit the fact that booleans are subclasses from int and that True behaves like 1 whereas False behaves like 0:
n = [bar, foo][condition]
Another possibility is to exploit the way operators in Python behave or more exactly how and and or behave:
n = condition and foo or bar
>>> n = 100
>>> x = 10 if n > 10 else n
>>> x
10
10 if 10 < n else n
see http://en.wikipedia.org/wiki/Ternary_operation
x = 10 if (10 < n) else n
(requires python 2.5)
Related
I decided to start learn Python a few days ago (as a native C++ programmer) and I've got a silly coding problem here:
Given a non-negative number "num", return True if num is within 2 of a
multiple of 10.
I've got what I'd consider a pretty ad-hoc solution and I'm hoping an experienced python programmer can give me a cleaner solution. Thanks in advance!
My solution:
def near_ten(num):
return abs(num%10) in [0,1,2,8,9]
This is actually pretty neat! I'd probably use abs(..) around num , though. And I might use a set instead of a list -- it doesn't make much difference but it sort of slightly improves readability in my opinion.
def near_ten(num):
return abs(num)%10 in {0, 1, 2, 8, 9}
Note that I prefer the above solution with a comment to the solution below.
def near_ten(num):
return abs(abs(num)%10 - 10) <= 2
Why don't you try following solution.
def near_ten(num):
return not(2 < (num % 10) < 8)
I would do it like:
def near_ten(num):
return abs(num%10 - 10) <= 2
Update: Added another check to make it work, although now it is less readable
def near_ten(num):
return num%10 <=2 or abs(num%10 - 10) <= 2
#not sure if this is any better than your solution.
def near_ten(num):
return (abs(num)+2)%10//5==0
The round function takes a precision argument which specifies the number of decimal places, however this can be negative to round to multiples of ten. For example:
>>> round(38, -1)
40.0
>>> round(41, -1)
40.0
So you could use something like:
>>> def near_ten(num):
... return abs(num - round(num, -1)) <= 2
...
>>> near_ten(0)
True
>>> near_ten(1)
True
>>> near_ten(2)
True
>>> near_ten(3)
False
>>> near_ten(7)
False
>>> near_ten(8)
True
>>> near_ten(9)
True
>>> near_ten(10)
def near_ten(num):
nums = [ num-2, num-1, num, num+1, num+2]
for n in nums:
if n % 10 == 0:
return True
else:
return False
This question already has answers here:
Why does the expression 0 < 0 == 0 return False in Python?
(9 answers)
Closed 6 years ago.
This baffles me. Even without knowing the precedence order, one can check that the two possible ways to gather the expression would give False :
>>> (0 is 0) == 0
False
>>> 0 is (0 == 0)
False
But
>>> 0 is 0 == 0
True
How come?
You are using comparison operator chaining. The expression is interpreted as:
(0 is 0) and (0 == 0)
From the Comparisons documentation:
Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).
0 is 0 is true because Python interns small integers, an implementation detail, so you get (True) and (True) producing True.
When chaining comparison operators in Python, the operators aren't actually applied to the result of the other operators, but are applied to the operands individually. That is x ? y ?? z (where ? and ?? are supposed to stand in for some comparison operators) is neither equivalent to (x ? y) ?? z nor x ? (y ?? z), but rather x ? y and y ?? z.
This is particularly useful for > and co., allowing you to write things like min < x < max and have it do what you want rather than comparing a boolean to a number (which would happen in most other languages).
This code adds all natural numbers up to 10, then takes the square of that sum in Python. Where did I go wrong?
def square_of_sum():
sum = 0
for x in xrange(11):
if x <= 10:
x + sum = sum
x += 1
else:
print sum*sum
break
Ah, I see you like Project Euler :)
Solution
I think this is what you meant by your code:
def square_of_sum():
sum_ = 0
for x in xrange(1, 11):
sum_ += x
return sum_ ** 2
To rewrite this more idiomatically, use generator comprehensions and built-ins:
def square_of_sum():
return sum(range(11)) ** 2
If your performance conscious, you can eliminate the loop by noticing that your finding the sum of an arithmetic series:
def square_of_sum(x):
print (x * (x + 1) / 2) ** 2
Fixes
As to why your code isn't working, it's b'coz of many reasons.
First of all, I think you're confused about how the for loop in Python works. Basically, it just loops over an array. You didn't have to check and break when x became greater than 10, nor increment it. Read up on the Python docs on how to use the for loop. To see an example of when to use it, see the wiki page.
Secondly, variable assignments are done with the variable on the left and the expression to be evaluated on the right. So x + sum = sum should really have been sum = sum + x or sum += x for brevity.
Thirdly, sum is a built-in function. You probably didn't want to nor shouldn't over-shadow it, so rename your sum variable to something else.
And last, sum*sum is equivalent to just raising it to the power of 2 and you can do that using the ** operator as so: sum ** 2.
Hope this helped you understand.
To fix the errors in your code:
def square_of_sum():
s = 0
for x in xrange(11):
s += x
print s**2
or, more idiomatically,
def square_of_sum(n):
print sum(range(n + 1)) ** 2
or, to eliminate the loop:
def square_of_sum(n):
print (n * (n + 1) / 2) ** 2
A couple of problems. First of all, sum is a builtin function, so you probably don't want to name anything that, so use a variable called something like total instead.
Second, variables assignment is done with the variable on the left and the expression on the right, so x + total = total should be total = x + total, or total += x for brevity.
Third, since the case when x == 11 is basically just a return case, it should be outside the loop.
And, finally, total * total is equivalent to total ** 2; this is easier to use for things like
def square_of_sum():
total = 0
for x in xrange(11):
if x <= 10:
total += x
x += 1
print total ** 2
But, if I were you, I'd just use
sum(range(11))**2
For an assignment we were asked to define a fibonacci function, which I accomplished with this:
def fibonacci(n):
if n < 2:
return n
return fibonacci(n-1) + fibonacci(n-2)
However, I have seen recursive functions, such as the factorial function, defined in a one line return statement like so:
def factorial(n):
return n > 1 and n * factorial(n-1) or 1
So, I attempted to apply the same to my fibonacci function. After several attempts, I got it to work for all tested cases except when s = 0, in which case it returns False when it should return 0. Here is where I am:
def fibonacci(n):
return ((n == 0 or n == 1) and n) or (n > 1 and (fibonacci(n-1) + fibonacci(n-2)))
I understand that python evaluates 0 to False, so how would I have python return zero instead of False when n is 0 while maintaining the current length/structure of the code? Is that even possible?
Also, is this style of creating a function (recursive or otherwise) more or less desirable/pythonic than the textbook version? (I would imagine not just because of readability)
To be clear, I have satisfied the requirements for the assignment, and for personal knowledge only, I would like a clearer understanding of what is happening in the return statement.
The x and y or z idiom doesn't work if y is falsy. You can swap the condition to make it work nonetheless:
def fibonacci(n):
return n >= 2 and fibonacci(n-1) + fibonacci(n-2) or n
However, as of Python 2.5 (released 6 years ago), we have proper conditional expressions and don't need the and/or hack any longer:
def fibonacci(n):
return n if n < 2 else fibonacci(n-1) + fibonacci(n-2)
Now this has an exponential runtime complexity. If you want to be efficient, use the O(n) algorithm:
def fibonacci(n):
a, b = 0, 1
for _ in range(n):
a, b = b, a + b
return a
Or even write a generator to yield all the numbers and only take as much as you need.
Perhaps this makes it clearer:
def fibonacci(n):
print ((n == 0 or n == 1) and n)
print (n > 1 and (fibonacci(n-1) + fibonacci(n-2)))
return ((n == 0 or n == 1) and n) or (n > 1 and (fibonacci(n-1) + fibonacci(n-2)))
print 0 or False
print False or 0
I have started looking at the project Euler site as a way to learn Haskell, and improve my Python and Ruby. I think the Haskell and Python versions are ok, but I'm sure there must be a cleaner way for Ruby.
This is not about how can I make one language look like another one.
This is Problem 1:
Q: Add all the natural numbers below one thousand that are multiples of 3 or 5.
Haskell:
sum [ x | x <- [1..999], mod x 3 == 0 || mod x 5 == 0 ]
Python:
sum ( [ x for x in range(1,1000) if x % 3 == 0 or x % 5 == 0 ] )
Ruby:
(1..999) . map {|x| x if x % 3 == 0 || x % 5 == 0 } . compact . inject(:+)
They all give the same answer.
OK, so Python can become:
sum ( x for x in range(1,1000) if x % 3 == 0 or x % 5 == 0 )
it is now a generator (a good thing as we are not storing the list)
but even more fun is:
sum( set(range(0,1000,3)) | set(range(0,1000,5)) )
For some reason I was looking at this again and tried a summation approach which should be constant time. In Python 3:
def step_sum(mn,mx,step):
amax = mx - (mx - mn) % step
return (mn + amax) * ((1 + ((amax - mn) / step)) / 2)
step_sum(3,999,3) + step_sum(5,999,5) - step_sum(15,999,15)
Ruby can become:
(1..999) . select {|x| x % 3 == 0 || x % 5 == 0} . inject(:+)
or
(1..999) . select {|x| x % 3 == 0 or x % 5 == 0} . reduce(:+)
I am presuming as unlike map, select doesn't produce 'nul' and therefore there is no need to call compact. nice.
Haskell can also be:
let ƒ n = sum [0,n..999] in ƒ 3 + ƒ 5 - ƒ 15
or to be clearer:
let ƒ n = sum [ 0 , n .. 999 ] in ƒ 3 + ƒ 5 - ƒ (lcm 3 5)
as a function that lets us provide the two numbers ourselves:
ƒ :: (Integral a) => a -> a -> a
ƒ x y = let ƒ n = sum [0,n..999] in ƒ x + ƒ y - ƒ (lcm x y)
For Haskell I like
let s n = sum [0,n..999] in s 3 + s 5 - s 15
or
sum $ filter ((>1).(gcd 15)) [0..999]
For fun the Rube-Goldberg version:
import Data.Bits
sum $ zipWith (*) [1..999] $ zipWith (.|.) (cycle [0,0,1]) (cycle [0,0,0,0,1])
Okay, explanation time.
The first version defines a little function s that sums up all multiples of n up to 999. If we sum all multiples of 3 and all multiples of 5, we included all multiples of 15 twice (once in every list), hence we need to subtract them one time.
The second version uses the fact that 3 and 5 are primes. If a number contains one or both of the factors 3 and 5, the gcd of this number and 15 will be 3, 5 or 15, so in every case the gcd will be bigger than one. For other numbers without a common factor with 15 the gcd becomes 1. This is a nice trick to test both conditions in one step. But be careful, it won't work for arbitrary numbers, e.g. when we had 4 and 9, the test gdc x 36 > 1 won't work, as gcd 6 36 == 6, but neither mod 6 4 == 0 nor mod 6 9 == 0.
The third version is quite funny. cycle repeats a list over and over. cycle [0,0,1] codes the "divisibility pattern" for 3, and cycle [0,0,0,0,1] does the same for 5. Then we "or" both lists together using zipWith, which gives us [0,0,1,0,1,1,0,0,1,1,0,1...]. Now we use zipWith again to multiply this with the actual numbers, resulting in [0,0,3,0,5,6,0,0,9,10,0,12...]. Then we just add it up.
Knowing different ways to do the same thing might be wasteful for other languages, but for Haskell it is essential. You need to spot patterns, pick up tricks and idioms, and play around a lot in order to gain the mental flexibility to use this language effectively. Challenges like the project Euler problems are a good opportunity to do so.
Try this for Ruby:
(1..999).select {|x| x % 3 == 0 or x % 5 == 0}.reduce(:+)
Or a little different approach:
(1..999).reduce(0) {|m, x| (x % 3 == 0 or x % 5 == 0) ? m+x : m }
Not a list comprehension, I know, but to solve that I would use:
3*((999/3)**2+999/3)/2+5*((999/5)**2+999/5)/2-15*((999/15)**2+999/15)/2
Faster then any list comprehension one might come up with, and works in any language ;)
Only posting to show another way of looking at the same problem using http://en.wikipedia.org/wiki/Summation.
I think the following is a better Ruby one:
(1..999).select{|x| x % 3 == 0 || x % 5 == 0}.reduce(:+)
Try something like this:
(1...1000).inject(0) do |sum, i|
if (i % 3 == 0) or (i % 5 == 0)
sum + i
else
sum
end