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
Related
This question already has answers here:
Check if a number is a perfect square
(25 answers)
Closed 9 days ago.
I wrote a function that returns whether a number input is a square or not
def is_square(n):
if n<1:
return False
else:
for i in range(int(n/2)+1):
if (i*i)==n:
return True
else:
return False
I am confident that this code works. But when I did the test cases, example:test.expect( is_square( 4)), it says that the value is not what was expected.
Your function doesn't actually work, as it will immediatley return False on the first non-square-root found. Instead you will want to modify your code to be:
def is_square(n):
if n<1:
return False
else:
for i in range(int(n/2)+1):
if (i*i)==n:
return True
return False
such that it only returns false once all possible square roots have been checked. You may also want to look into math.sqrt() and float.is_integer(). Using these methods your function would become this:
from math import sqrt
def is_square(n):
return sqrt(n).is_integer()
Keep in mind that this method will not work with very large numbers, but your method will be very slow with them, so you will have to choose which to use.
To stick to integer-based algorithms, you might look at implementation of binary search for finding square root:
def is_square(n):
if n < 0:
return False
if n == 0:
return True
x, y = 1, n
while x + 1 < y:
mid = (x+y)//2
if mid**2 < n:
x = mid
else:
y = mid
return n == x**2 or n == (x+1)**2
The main idea of Python philosophy is to write simple code. To check if a number is an perfect square:
def is_square(n):
return n**0.5 == int(n**0.5)
When power to a float you can find the root of a number.
In Python 3.8+, use this:
def is_square(n):
root = math.isqrt(n)
return n == root * root
You can simply use simpy module
import it as,
from sympy.ntheory.primetest import is_square
and you can check for a number like this:
is_square(number)
It will return a boolean value
I think the best take, using only "built-in" integer arithmetic, is:
def issquare(n): return math.isqrt(n)**2==n
(Squares x**2 are a priori more efficiently computed than products x*x...)
According to my timings, this is (at least up to ~ 10^8) faster than sympy.numtheory.primetest.is_square.
(I use a different name to make it easier to compare the two.)
The latter is first using some modular checks that should speed it up considerably, but it has so much conversion and testing overhead (int, as_int, squares become n-th powers with n=2, integers are converted from "small" to multiprecision integers and back, ...) that all the advantage is lost. After a lot of tests, it roughly does the above, using ntheory.nthroot, which is again an overkill: designed for any n-th root, the square root is just one special case, and noting is optimized for this case. Some subroutines there even do very weird floating point arithmetics including multiplication with 1.0000000001 and similar horrors... I once got the following horrible error message: (The original output has the full path "C:\Users\Username\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\" instead of each "..." below...)
File "...\sympy\ntheory\primetest.py", line 112, in is_square
return integer_nthroot(n, 2)[1]
File "...\sympy\core\power.py", line 86, in integer_nthroot
return _integer_nthroot_python(y, n)
File "...\sympy\core\power.py", line 94, in _integer_nthroot_python
x, rem = mpmath_sqrtrem(y)
File "...\mpmath\libmp\libintmath.py", line 284, in sqrtrem_python
y = isqrt_small_python(x)
File "...\mpmath\libmp\libintmath.py", line 217, in isqrt_small_python
r = int(x**0.5 * 1.00000000000001) + 1
KeyboardInterrupt
This gives a good idea of the abyss into which sympy's is_square hopelessly drowns...
Documentation: see is_square in Sympy's Ntheory Class Reference
P.S.: FWIW, regarding other answers suggesting to use round() etc, let me just mention here that ceil(sqrt(n))**2 < n (!!), for example when n is the 26th and 27th primorial -- not extremely large numbers! So, clearly, use of math.sqrt is not adequate.
def myfunct(num):
for i in range(0,num):
if i*i==num:
return 'square'
else:
return 'not square'
Easiest working solution, but not for large numbers.
def squaretest(num):
sqlist=[]
i=1
while i**2 <= num:
sqlist.append(i**2)
i+=1
return num in sqlist
Assuming that n >= 0:
def is_square(n):
tmp = int(n ** 0.5)
return n == tmp * tmp
print(is_square(81), is_square(67108864 ** 2 + 1)) # True False
Another approach:
def SQRT(x):
import math
if math.sqrt(x) == int(math.sqrt(x)):
return True
else:
return False
def is_square(n):
if n < 0:
return False
return round(n ** 0.5) ** 2 == n
To check if a number is a square, you could use code like this:
import math
number = 16
if math.sqrt(number).is_interger:
print "Square"
else:
print "Not square"
import math imports the math module.
if math.sqrt(number).is_interger: checks to see if the square root of number is a whole number. If so, it will print Square. Otherwise, it will print Not square.
Since math.sqrt() returns a float, we can cast that to a string, split it from "." and check if the part on the right(the decimal) is 0.
import math
def is_square(n):
x= str(math.sqrt(n)).split(".")[1] #getting the floating part as a string.
return True if(x=="0") else False
Undertaking a task to Write a function power that accepts two arguments, a and b and calculates a raised to the power b.
Example
power(2, 3) => 8
Note: Don't use
2 ** 3
and don't use
Math.pow(2, 3)
I have tried this
def power(a,b):
return eval(((str(a)+"*")*b)[:-1])
And it works but seems to fail one test which is to return_1_when_exp_is_0
and i also get the error
Unhandled Exception: unexpected EOF while parsing (, line 0)
Please how do i solve this issue considering that i am new to python
This worked fine
def power(a,b):
if b == 0:
return 1
else:
return eval(((str(a)+"*")*b)[:-1])
Using eval is a terrible idea, but if you really wanted to then using join() would be a better way to create the string:
def power(a, b):
return eval('*'.join([str(a)]*b))
>>> power(2, 3)
8
If you add ['1'] to the front then the 0 exponent behaves properly:
def power(a, b):
return eval('*'.join(['1']+[str(a)]*b))
>>> power(2, 0)
1
However, this is simple to implement for integer exponents with a for loop:
def power(n, e):
t = 1
for _ in range(e):
t *= n
return t
>>> power(2, 3)
8
>>> power(2, 0)
1
You could also use functools.reduce() to do the same thing:
import functools as ft
import operator as op
def power(n, e):
return ft.reduce(op.mul, [n]*e, 1)
You can use a for loop
x=1
for i in range(b):
x=x*a
print(x)
def power(theNumber, thePower):
#basically, multiply the number for power times
try:
theNumber=int(theNumber)
thePower=int(thePower)
if theNumber == 0:
return 0
elif thePower == 0:
return 1
else:
return theNumber * power(theNumber,thePower-1)
except exception as err:
return 'Only digits are allowed as input'
You should avoid eval by all costs, especially when it's very simple to implement pure algorithmic efficient solution. Classic efficient algorithm is Exponentiation_by_squaring. Instead of computing and multiplying numbers n times, you can always divide it to squares to archive logarithmic* complexity.
For example, for calculating x^15:
x^15 = (x^7)*(x^7)*x
x^7 = (x^3)*(x^3)*x
x^3 = x*x*x
Thus taking 6 multiplications instead of 14.
def pow3(x, n):
r = 1
while n:
if n % 2 == 1:
r *= x
n -= 1
x *= x
n /= 2
return r
Source: https://helloacm.com/exponentiation-by-squaring/
Note: it was not mentioned in the question, but everything above considers N to be positive integer. If your question was also covering fractional or negative exponent, suggested approach will not work "as is".
* Of course depends on length of x and complexity of multiplying, see Wikipedia for detailed complexity analysis.
Also may be interesting to check out following questions: C solution or Python implementing pow() for exponentiation by squaring for very large integers
def power(a, b):
if b == 0:
return 1
else:
return a ** b
I'm supposed to be writing a function that find the amount of shoes a given number of dogs would need. It can easily be done with multiplication, but we're required to use recursion, so i have
def dogShoes(n):
total = 0
if n>0:
shoes = n + dogShoes(n)
total = total + 1
if total == 4:
return shoes
But I now realize that line 4 will go towards infinity and the bottom part that I though would stop it won't even be implemented. Is there a way to say when total is 4, stop and return the answer without shoes going towards infinity?
You can simplify your function a lot:
def dogShoes(n):
if n == 0:
return 0
else:
return 4 + dogShoes(n-1)
Since you have to use recursion instead of just returning n * 4 you can simply rewrite multiplication as addition (recursively).
What a weird task...
You're calling your function recursively, but never changing the parameter, thus giving infinite recursion. Try:
>>> def dog_shoes(n):
... if n > 0:
... return 4 + dog_shoes(n-1)
... else:
... return 0
...
>>> dog_shoes(1)
4
>>> dog_shoes(2)
8
>>> dog_shoes(3)
12
def Mul(n, x):
if n==1:
return x
else:
return x+ Mul(n-1,x)
Here's a simple multiplication function using Python recursion using two arguments.
Mul(3,3)
>>>9
Question may sound complicated, but actually is pretty simple, but i can't find any nice solution in Python.
I have ranges like
("8X5000", "8X5099"). Here X can be any digit, so I want to match numbers that fall into one of the ranges (805000..805099 or 815000..815099 or ... 895000..895099).
How can I do this?
#TimPietzcker answer is correct and Pythonic, but it raises some performance concerns (arguably making it even more Pythonic). It creates an iterator that is searches for a value. I don't expect Python to be able to optimize the search.
This should perform better:
def IsInRange(n, r=("8X5000", "8X5099")):
(minr, maxr) = [[int(i) for i in l.split('X')] for l in r]
p = len(r[0]) - r[0].find('X')
nl = (n // 10**p, n % 10**(p-1))
fInRange = all([minr[i] <= nl[i] <= maxr[i] for i in range(2)])
return fInRange
The second line inside the function is a nested list comprehension so may be a little hard to read but it sets:
minr = [8, 5000]
maxr = [8, 5099]
When n = 595049:
nl = (5, 5049)
The code just splits the ranges into parts (while converting to int), splits the target number into parts, then range checks the parts. It wouldn't be hard to enhance this to handle multiple X's in the range specifiers.
Update
I just tested relative performance using timeit:
def main():
t1 = timeit.timeit('MultiRange.in_range(985000)', setup='import MultiRange', number=10000)
t2 = timeit.timeit('MultiRange.IsInRange(985000)', setup='import MultiRange', number=10000)
print t1, t2
print float(t2)/float(t1), 1 - float(t2)/float(t1)
On my 32-bit Win 7 machine running Python 2.7.2 my solution is almost 10 times faster than #TimPietzcker's (to be specific, it runs in 12% of the time). As you increase the size of the range, it only gets worse. When:
ranges=("8X5000", "8X5999")
The performance boost is 50x. Even for the smallest range, my version runs 4 times faster.
With #PaulMcGuire suggested performance patch to in_range, my version runs 3 times faster.
Update 2
Motivated by #PaulMcGuire's comment I went ahead and refactored our functions into classes. Here's mine:
class IsInRange5(object):
def __init__(self, r=("8X5000", "8X5099")):
((self.minr0, self.minr1), (self.maxr0, self.maxr1)) = [[int(i) for i in l.split('X')] for l in r]
pos = len(r[0]) - r[0].find('X')
self.basel = 10**(pos-1)
self.baseh = self.basel*10
self.ir = range(2)
def __contains__(self, n):
return self.minr0 <= n // self.baseh <= self.maxr0 and \
self.minr1 <= n % self.basel <= self.maxr1
This did close the gap, but even after pre-computing range invariants (for both) #PaulMcGuire's took 50% longer.
range = (80555,80888)
x = 80666
print range[0] < x < range[1]
maybe what your looking for ...
Example for Python 3 (in Python 2, use xrange instead of range):
def in_range(number, ranges=("8X5000", "8X5099")):
actual_ranges = ((int(ranges[0].replace("X", digit)),
int(ranges[1].replace("X", digit)) + 1)
for digit in "0123456789")
return any(number in range(*interval) for interval in actual_ranges)
Results:
>>> in_range(805001)
True
>>> in_range(895099)
True
>>> in_range(805100)
False
An improvement to this, suggested by Paul McGuire (thanks!):
def in_range(number, ranges=("8X5000", "8X5099")):
actual_ranges = ((int(ranges[0].replace("X", digit)),
int(ranges[1].replace("X", digit)))
for digit in "0123456789")
return any(minval <= number <= maxval for minval, maxval in actual_ranges)
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...