I have this sample quiz question but not to sure how to approach it with while loops.
Implement the nearest_square function. The function takes an integer argument limit, and returns the largest square number that is less than limit.
A square number is the product of an integer multiplied by itself, for example 36 is a square number because it equals 6*6.
There's more than one way to write this code, but I suggest you use a while loop!
Here is a test case you can copy to test your code. Feel free to write additional tests too!
test1 = nearest_square(40)
print("expected result: 36, actual result: {}".format(test1))
I have managed to solve it. Thank you.
def nearest_square(limit):
limit = limit ** (0.5)
y = int (limit)
while y < limit :
y = y*y
return y
test1 = nearest_square(40)
print("expected result: 36,actual result:{}".format(test1))
Try using the following method to return the nearest square given the limit parameter:
def nearest_square(limit):
answer = 0
while (answer+1)**2 < limit:
answer += 1
return answer**2
Normally, it's more efficient to approach this kind of questions mathematically (maybe not for low inputs but certainly yes for pretty big numbers). That said, we have a good tool at hand: the square root.
If computing the square root of any number, n, yields a double value whose decimal part is fully composed by zeroes then your number is a perfect square (square of an integer).
Interestingly (and this is more related to your question), if you choose another number (that is not a perfect square) and apply a rounding operation (floor or ceil) you'll get the closest square (lower or bigger).
An example:
n = 24
sqrt = math.sqrt(n) # sqrt(24) = 4.898979485566356...
closest = [math.floor(sqrt)**2, math.ceil(sqrt)**2] # closest = [16, 25]
this is how i did it with while loop:
def nearest_square(value):
i = 2
while i < value:
square = i*i
if square == value:
return square
i+=1
value-=1
print (nearest_square(40))
def nearest_square(value):
i = 1
result = 1
while (result < value):
if (result == value):
return result
i+=1
result = i*i
return (i-1)*(i-1)
print (nearest_square(82))
Here is my code:
`
def nearest_square(limit):
while limit > 3:
i = 2
while i <= limit//2:
square = i*i
if square == limit:
return square
else:
i += 1
limit -= 1
return 1
`
Here's what i did.
def nearest_square(limit):
y = 0
while y**2 < limit:
y+=1
if y**2 == limit:
return(y)
return(y-1)
print(nearest_square(40))
Here is my implementation of it.
this one is with while loop
def near1(limit):
i = 1
square = 1
while (i*i) < limit:
square = i*i
i = i+1
return square
but the easiest one is below.
Simple math and modulo
import math
def near(limit):
i = int(math.pow(limit, .5))
return i*i
This is what i did.
import math
def nearest_square(limit):
a = math.sqrt(limit)
while type(a) != type(int()):
limit -=1
return limit
Related
I am trying to do square root using newton-raphson algorithm of random numbers given by this formula:
a = m * 10 ^c
where m is random float in range (0,1) and c is random integer in range (-300,300).
Code i wrote works perfectly with precision of root as 0.01 and c in range (-30,30) but freezes or returns wrong results when i use c range given in task.
here is code for newton function
def newton_raphson(a):
iterations_count = 0
x_n_result = a/2
while abs(x_n_result - a / x_n_result) > 0.01:
x_n_result = (x_n_result + a/x_n_result)/2
iterations_count = iterations_count + 1
if x_n_result*x_n_result == a:
break
iterations.append(iterations_count)
results.append(x_n_result)
print("Result of function", x_n_result)
return
and part where numbers to root are randomized
for i in range(0, 100):
m = random.uniform(0, 1)
c = random.randint(-30, 30)
a = m * 10 **c
random_c.append(c)
numbers.append(a)
print("Number to root : ", i, "|", a, '\n')
newton_raphson(a)
plot of the amount of iteration from the value of c
plt.bar(random_c, iterations, color='red')
Script is supposed to root 100 random numbers and then plot amount of iteration required to root number from values of c. Problem is like i said before with proper range of c value. I believe it has to do something with range of variables. Any sugestion how to solve this?
First observation is that your logic will get you a square root, not a cubic root.
The second thing is that your random numbers can contain negative values which will never converge for a square root.
If you really wanted a cubic root, you could do it like this:
def cubic(number):
result = number
while abs(number/result/result - result) > 0.01:
result += (number/result/result - result)/2
return result
you could also approach this in a generic fashion by creating a newton/raphson general purpose function that takes a delta function as parameter to use on a number parameter:
def newtonRaphson(delta,n):
result = n
while abs(delta(n,result)) > 0.01:
result += delta(n,result)/2
return result
def cubic(n,r): return n/r/r - r
def sqrt(n,r): return n/r - r
The use the newtonRaphson method with your chosen delta function:
newtonRaphson(sqrt,25) # 5.000023178253949
newtonRaphson(cubic,125) # 5.003284700817307
I was curious if any of you could come up with a more streamline version of code to calculate Brown numbers. as of the moment, this code can do ~650! before it moves to a crawl. Brown Numbers are calculated thought the equation n! + 1 = m**(2) Where M is an integer
brownNum = 8
import math
def squareNum(n):
x = n // 2
seen = set([x])
while x * x != n:
x = (x + (n // x)) // 2
if x in seen: return False
seen.add(x)
return True
while True:
for i in range(math.factorial(brownNum)+1,math.factorial(brownNum)+2):
if squareNum(i) is True:
print("pass")
print(brownNum)
print(math.factorial(brownNum)+1)
break
else:
print(brownNum)
print(math.factorial(brownNum)+1)
brownNum = brownNum + 1
continue
break
print(input(" "))
Sorry, I don't understand the logic behind your code.
I don't understand why you calculate math.factorial(brownNum) 4 times with the same value of brownNum each time through the while True loop. And in the for loop:
for i in range(math.factorial(brownNum)+1,math.factorial(brownNum)+2):
i will only take on the value of math.factorial(brownNum)+1
Anyway, here's my Python 3 code for a brute force search of Brown numbers. It quickly finds the only 3 known pairs, and then proceeds to test all the other numbers under 1000 in around 1.8 seconds on this 2GHz 32 bit machine. After that point you can see it slowing down (it hits 2000 around the 20 second mark) but it will chug along happily until the factorials get too large for your machine to hold.
I print progress information to stderr so that it can be separated from the Brown_number pair output. Also, stderr doesn't require flushing when you don't print a newline, unlike stdout (at least, it doesn't on Linux).
import sys
# Calculate the integer square root of `m` using Newton's method.
# Returns r: r**2 <= m < (r+1)**2
def int_sqrt(m):
if m <= 0:
return 0
n = m << 2
r = n >> (n.bit_length() // 2)
while True:
d = (n // r - r) >> 1
r += d
if -1 <= d <= 1:
break
return r >> 1
# Search for Browns numbers
fac = i = 1
while True:
if i % 100 == 0:
print('\r', i, file=sys.stderr, end='')
fac *= i
n = fac + 1
r = int_sqrt(n)
if r*r == n:
print('\nFound', i, r)
i += 1
You might want to:
pre calculate your square numbers, instead of testing for them on the fly
pre calculate your factorial for each loop iteration num_fac = math.factorial(brownNum) instead of multiple calls
implement your own, memoized, factorial
that should let you run to the hard limits of your machine
one optimization i would make would be to implement a 'wrapper' function around math.factorial that caches previous values of factorial so that as your brownNum increases, factorial doesn't have as much work to do. this is known as 'memoization' in computer science.
edit: found another SO answer with similar intention: Python: Is math.factorial memoized?
You should also initialize the square root more closely to the root.
e = int(math.log(n,4))
x = n//2**e
Because of 4**e <= n <= 4**(e+1) the square root will be between x/2 and x which should yield quadratic convergence of the Heron formula from the first iteration on.
Here is a link to the problem: link. My code seems to be slowing down exponentially but I can't identify why or a more efficient algorithm. My approach was to identify all of the abundant numbers up to the limit and identify the numbers up to the upper limit that are not sums of the numbers by subtracting each number from the original and seeing if the difference is inside the abundant numbers list. Any ideas as to what is going on and or a better approach to this problem?
Here is the code that I used:
import numpy as np
import math
import itertools
def divisors(n): return sorted(np.unique(np.array([[x,n/x] for x in range(1,int(round(math.sqrt(n))+1)) if n%x == 0]).flatten()).tolist())[0:-1]
ubound = 28123
abundant_numbers = [x for x in range(1,ubound) if x < sum(divisors(x))]
def is_sum_of_abundant(n):
isob = False
for i in abundant_numbers:
if (n - i) <=0:
continue
else:
if (n - i) in abundant_numbers:
isob = True
return isob
s = 0
for x in range(1,ubound):
print "%.2f percent\n" % ((float(x)/ubound)*100)
if is_sum_of_abundant(x):
print "{} is abundant".format(x)
else:
s+=x
print "{} is not abundant".format(x)
print s
One thing you try is a better way to calculate the sum of the divisors - see the definition of the sigma function here. Essentially you find the prime factors and use the fact that
sigma(ab) = sigma(a) * sigma(b)
sigma(p^n) = (p^(n+1)-1)/(p-1)
where sigma(n) is the sum of the positive divisors.
I am having some trouble with this algorithm. I am attempting to find the least common multiple for a given range of numbers. The following functions find the factors of a number, count the different factors in the number, counts the factors so that I can find the lcm of the range of numbers based on this algorithm, and then finally calculates the lcm; however, if you run this code, the print statement at the bottom does not print the correct answer. Instead I get a number that I KNOW for sure is not right. I mainly need a second set of eyes to point out the problem with this code. Can anyone help?
from collections import defaultdict
def factors_of(number):
factors = [];
i = 2
while number >= 2:
if number % i == 0:
factors.append(i)
number = number / i
else:
i += 1
return factors
def count_factors(number):
count = {}
factors = factors_of(number)
for factor in factors:
if not factor in count:
count[factor] = 1
else:
count[factor] += 1
return count
def count_factors_of_numbers_in_range(start, stop):
count = defaultdict(int)
for number in range(start, stop):
factor_count = count_factors(number)
for key in factor_count:
if count[key] < factor_count[key]:
count[key] = factor_count[key]
return dict(count)
def find_lcm_of_numbers_in_range(start, stop):
count = count_factors_of_numbers_in_range(start, stop)
lcm = 1
for key in count:
total = count[key] * key
lcm = total * lcm
return lcm
print find_lcm_of_numbers_in_range(1, 21)
why can't you simply find gcd by euclid's algorithm and the multiply the numbers and divide by gcd to find LCM?
def decorator(d):
"""This is a decorator that will decorate all decorators. This will add update_wrapper
to all decorators.
(fun) -> fun
"""
def _d(f):
return update_wrapper(d(f), f)
return update_wrapper(_d, d)
#decorator
def nary(f):
"""This is docp implementation of n_ary function above.
(function) -> function
Tue-23-April-2013
"""
def n_ary(x, *args):
if len(args) == 0:
return x
return f(x, n_ary(*args))
return n_ary
#nary
def gcd(a, b):
"""Calculate the Greatest Common Divisor of a and b.
Unless b==0, the result will have the same sign as b (so that when
b is divided by it, the result comes out positive).
"""
while b:
a, b = b, a%b
return a
I figured out what I did wrong. I guess I just needed a good night's sleep.
The problem did not lie in a quirk with Python (which was what I thought this might be) but in my own implementation of the algorithm. In my code
def find_lcm_of_numbers_in_range(start, stop):
count = count_factors_of_numbers_in_range(start, stop)
lcm = 1
for key in count:
total = count[key] * key
lcm = total * lcm
return lcm
I messed up multiplying all of the numbers together in the statement total. Instead of multiplying the number 2 by the number 4, I needed to multiply 2 by itself 4 times (2 ** 4). By simply tweaking the code to look like
def find_lcm_of_numbers_in_range(start, stop):
count = count_factors_of_numbers_in_range(start, stop)
lcm = 1
for key in count:
total = key ** count[key]
lcm = total * lcm
return lcm
everything worked out and I am now happy. :)
I have got this code to solve Newton's method for a given polynomial and initial guess value. I want to turn into an iterative process which Newton's method actually is. The program should keeping running till the output value "x_n" becomes constant. And that final value of x_n is the actual root. Also, while using this method in my algorithm it should always produce a positive root between 0 and 1. So does converting the negative output (root) into a positive number would make any difference? Thank you.
import copy
poly = [[-0.25,3], [0.375,2], [-0.375,1], [-3.1,0]]
def poly_diff(poly):
""" Differentiate a polynomial. """
newlist = copy.deepcopy(poly)
for term in newlist:
term[0] *= term[1]
term[1] -= 1
return newlist
def poly_apply(poly, x):
""" Apply a value to a polynomial. """
sum = 0.0
for term in poly:
sum += term[0] * (x ** term[1])
return sum
def poly_root(poly):
""" Returns a root of the polynomial"""
poly_d = poly_diff(poly)
x = float(raw_input("Enter initial guess:"))
x_n = x - (float(poly_apply(poly, x)) / poly_apply(poly_d, x))
print x_n
if __name__ == "__main__" :
poly_root(poly)
First, in poly_diff, you should check to see if the exponent is zero, and if so simply remove that term from the result. Otherwise you will end up with the derivative being undefined at zero.
def poly_root(poly):
""" Returns a root of the polynomial"""
poly_d = poly_diff(poly)
x = None
x_n = float(raw_input("Enter initial guess:"))
while x != x_n:
x = x_n
x_n = x - (float(poly_apply(poly, x)) / poly_apply(poly_d, x))
return x_n
That should do it. However, I think it is possible that for certain polynomials this may not terminate, due to floating point rounding error. It may end up in a repeating cycle of approximations that differ only in the least significant bits. You might terminate when the percentage of change reaches a lower limit, or after a number of iterations.
import copy
poly = [[1,64], [2,109], [3,137], [4,138], [5,171], [6,170]]
def poly_diff(poly):
newlist = copy.deepcopy(poly)
for term in newlist:
term[0] *= term[1]
term[1] -= 1
return newlist
def poly_apply(poly, x):
sum = 0.0
for term in poly:
sum += term[0] * (x ** term[1])
return sum
def poly_root(poly):
poly_d = poly_diff(poly)
x = float(input("Enter initial guess:"))
x_n = x - (float(poly_apply(poly, x)) / poly_apply(poly_d, x))
print (x_n)
if __name__ == "__main__" :
poly_root(poly)