i wanted to do the project euler problems by using python.
but i am having problems with the following task:
A palindromic number reads the same both ways. The largest palindrome made from the product of two 2-digit numbers is 9009 = 91 x 99.
Find the largest palindrome made from the product of two 3-digit numbers.
my code for the given task:
def palindrome_number():
n=0
lower_range = 100
upper_range = 999
while x >= lower_range or x <= upper_range and y >= lower_range or y <= upper_range:
z = x * y
while z > n:
s = str(x * y)
if s == s[::-1]:
n = x * y
print(n)
now i dont know how to check for all the x and y numbers varying from 100-999.
i thought it has to be like in my code, but it doesnt work
Solution 1: using a generator expression
Actually the problem can be solved in one line :)
max(x*y for x in range(100, 1000) for y in range(100, 1000) if str(x*y)==str(x*y)[::-1])
Solution 2: using a for loop
for loops are better suited for this kind of operation than while loops. Below is the solution (I have only replaced your while with two for loops. The first loop tells the variable x to run from 100 to 999 and the second one tells y to do the same. With these two loops you will try out all combinations for x and y.)
def palindrome_number():
n = 0
lower_range = 100
upper_range = 999
for x in range(lower_range, upper_range+1):
for y in range(lower_range, upper_range+1):
z = x * y
if z > n: # an *if* suffices ;)
s = str(x * y)
if s == s[::-1]:
n = x * y
print(n)
Solution 3: using a while loop
To get the same thing with while loops you would have to take care of changing x and y to get all combinations:
x = y = lower_range
while x >= lower_range and x <= upper_range: # (*and* instead of *or*)
while y >= lower_range and y <= upper_range: # (again you want the >= *and* the <= to be fulfilled)
z = x * y
if z > n:
s = str(x * y)
if s == s[::-1]:
n = x * y
y += 1 # change y to get all combinations
y = lower_range
x += 1 # change x to get all combinations
Related
creating array using numpy from 1 to 100000 as value of x and y = x*x
x = np.arange(1,100000)
y = x*x
but when checked y value there are 31k+ negative value
count = 0
for i in y:
if i < 0:
count+=1
print(count)
31612
https://www.linkedin.com/posts/sandeep-agrawal-3b8857196_python-python3-pythonlearning-activity-6852679546345521152-cG-a
You are probably having integer overflow, try convert x to float before raising the power:
x = np.arange(1,100000)
y = x**10
sum(y < 0)
49760
Convert to float:
x = np.arange(1,100000).astype(float)
y = x**10
sum(y < 0)
0
So I've been doing some exercises from matura exam and there was one to draw a heighway dragon.
The program should focus on two pairs of variables:
x' = -0,4*x - 1
y' = -0,4*y + 0,1
and
x' = 0,76*x -0,4*y
y' = 0,4*x + 0,76*y
At the start x = 1 and y = 1, then, count a new x and y using the formula of randomly taken pair shown above (50/50 chance) and mark the point (x,y) on the chart. Everything repeat 5000 times.
So I tried it using python but the problem is that when I've finally drawn a dragon, at the chart I could see it was not one constant drawing but it had blank areas as in the photo below. Is it still acceptable or I made any mistake? Is there any way to make it look like the correct one?
My chart
The correct one to compare
My code:
import matplotlib.pyplot as plt
import random
x = 1
y = 1
sumx = 0
sumy = 0
max_x = 0
max_y = 0
for i in range(5000):
rand = random.randint(0, 1)
if rand == 0:
x = (-0.4 * x) - 1
y = (-0.4 * y) + 0.1
else:
x = (0.76 * x) - (0.4 * y)
y = (0.4 * x) + (0.76 * y)
if i >= 100:
sumx += x
sumy += y
plt.plot(x, y, c='black', marker='P', markersize=6)
if x > max_x:
max_x = x
if y > max_y:
max_y = y
plt.show()
avg_x = sumx / 5000
avg_y = sumy / 5000
print(round(avg_x, 1), round(avg_y, 1))
print('maximum x: ' + str(max_x) + ', maximum y: ' + str(max_y))
If the coordinates x' and y' are definitely calculated in the way you have written them above then your code is OK (although I'm not sure why you only start plotting once you've iterated 100 times).
However, calling pyplot's plot function is computationally expensive so I would suggest the following:
calculate all your x and y values and store them in lists
make one call to plt.scatter outside your for loop
this way the execution time for your code is drastically improved. I've done that in the following code, and also removed the condition that i >= 100. I also changed the way the random number was generated to see if this had an effect but it still produces a very similar output to the original code (see image below).
import matplotlib.pyplot as plt
import random
import sys
x = 1
y = 1
sumx = 0
sumy = 0
max_x = 0
max_y = 0
x_values = []
y_values = []
for i in range(5000):
rand = random.uniform(0,1)
if rand <= 0.5:
x = ((-0.4 * x) - 1)
y = ((-0.4 * y) + 0.1)
x_values.append(x)
y_values.append(y)
else:
x = ((0.76 * x) - (0.4 * y))
y = ((0.4 * x) + (0.76 * y))
x_values.append(x)
y_values.append(y)
sumx += x
sumy += y
if x > max_x:
max_x = x
if y > max_y:
max_y = y
plt.scatter(x_values, y_values, c='black', marker='P')
plt.ylim([-1, 0.4])
plt.xlim([-1.5, 0.5])
plt.show()
avg_x = sumx / 5000
avg_y = sumy / 5000
print(round(avg_x, 1), round(avg_y, 1))
print('maximum x: ' + str(max_x) + ', maximum y: ' + str(max_y))
For illustration purpose, see image below.
Given a point p and two vectors u and v, we can get a linear combination of u and v, t = m*u + n*v, m and n are integer, and t should be within the box. Solve this problem is not too difficult. As m and n can both be positive and negative. It can be discussed:
m > 0 and n > 0
m > 0 and n < 0
m < 0 and n > 0
m < 0 and n < 0
Here is the python code for case 1:
m = 0
n = 0
t = m*u+n*v
x = t[0]
y = t[1]
l = []
while (x>0 and x < 1024 and y > 0 and y < 1024):
l.append(t)
m = m + 1
t = m*u+n*v
x = t[0]
y = t[1]
while (x>0 and x < 1024 and y > 0 and y < 1024):
l.append(t)
n = n +1
t = m*u+n*v
x = t[0]
y = t[1]
Using two loops for 4 sets may solve the problem.
Another way is generate too many points and then remove the points outside the box
I think maybe there is other simple and elegant way to do it?
Transform box into coordinate system defined with p as origin, and u as x direction of axis and v as direction of y axis. Result will be parallelogram. It is enough to find integer coordinates that are inside that parallelogram. That can be done by finding minimal and maximal m that is inside parallelogram, and searching for each m between minimal and maximal what range on n's are inside parallelogram.
def max3bad(x,y,z):
maximum = 0
if x >= y:
if x >= z:
maximum = x
elif y >= z:
maximum = y
else:
maximum = z
return(maximum)
wrong output for what input?
get an input for which u get wrong output
for case: x = 2, y = 1, z = 3
the code output is 0 not 3.
It's better to get max number by :
max(x, y, z)
or you fix bug in your code:
def max3bad(x,y,z):
maximum = 0
if x >= y:
if x >= z:
maximum = x
else:
maximum = z
elif y >= z:
maximum = y
else:
maximum = z
return maximum
"Encapsulate this loop in a function called square_root that takes a as a parameter, chooses a reasonable value of x, and returns an estimate of the square root of a."
def square_root(a):
x = 2
y = (x + a/x) / 2
epsilon = 0.00000000001
if abs(y - x) < epsilon:
print y
while abs(y - x) > epsilon:
x = x + 1
y = (x + a/x) / 2
break
else:
return
print y
square_root(33)
up to putting 33 for 'a', it estimates the correct square root. after that, it starts jumping exponentially, to the point where when I send 100 in for 'a', it guesses the square root to be approximately 18. I don't know if maybe this is the nature of estimating. I know of how to find the precise square root, but this is an exercise from the book "Think Python" and it's to practice with recursion and thinking algorithmically.
You shouldn't be incrementing x by 1 in the loop body. You should be setting x to y (look at the Wikipedia article and notice how x3 depends on x2, and so on):
while abs(y - x) > epsilon:
x = y
y = (x + a/x) / 2
You want to get rid of that break as well, as it makes your while loop pointless. Your final code will then be:
def square_root(a):
x = 2
y = (x + a/x) / 2
epsilon = 0.00000000001
if abs(y - x) < epsilon:
print y
while abs(y - x) > epsilon:
x = y
y = (x + a/x) / 2
print y
But there's still room for improvement. Here's how I'd write it:
def square_root(a, epsilon=0.001):
# Initial guess also coerces `a` to a float
x = a / 2.0
while True:
y = (x + a / x) / 2
if abs(y - x) < epsilon:
return y
x = y
Also, since Python's floating point type doesn't have infinite precision, you can only get about 15 digits of precision anyways, so you might as well just remove epsilon:
def square_root(a):
x = a / 2.0
while True:
y = (x + a / x) / 2
# You've reached Python's max float precision
if x == y:
return x
x = y
But this last version might not terminate if y oscillates between two values.
Here's another way; it just updates x instead of using a y.
def square_root(a):
x = a / 2.0
epsilon = 0.00000001
while abs(a - (x**2)) > epsilon:
x = (x + a/x) / 2
return x
If you want it more abstract create good-enough? and guess as primitives .. Refer to the classic text of SICP here http://mitpress.mit.edu/sicp/full-text/sicp/book/node108.html
so simple , just take x = a and then follow neuton formula , like this :
def square_root(a):
x = a
while True:
print x
y = (x+a/x)/2
if abs(y-x) < 0.0000001:
break
x = y