Newbie programmer fresh off of code academy. I wanted to keep going so I started the Euler examples. I've got to no.4, https://projecteuler.net/problem=4:
My program is getting to the number 980089 happily enough but decides that this number is divisible by 994. But the other value is actually 986.0050302. That isn't the answer that I'm looking for. So modulo isn't doing its job because there is a remainder of 0.0050302. Why is this happening?
Full code:
x = 999998
g = 2
while g < 99:
e = str(x)
if e[::-1] == str(x):
print(e)
for f in reversed(range(100, 1000)):
f = float(f)
h = x/f
if int(x) % f == 0.000000 and h < 1000:
print("%s and %s" % (f, h))
break
else:
x = x - 1
else:
x = x - 1
Tips on how I could improve my code would be great too, I don't think my while command was used how I originally imagined.
It looks like the general idea of what you're trying to do is to start at a number larger than anything two 3-digit numbers could multiply to, and then just start going down by one seeing if there are any possible 3-digit numbers that will multiply to your current number.
First thing I notice is that your while loop uses g, but you never modify it inside your loop, so it's rather useless. I also notice you're casting x to an int using int(x) at one point, which is not needed because x will always already be an int.
I'm going to try and rewrite your code to do the right thing - let me know if you have any questions about it!
x = 999998
found_an_answer = False
# We'll certainly find an answer before we get here
while x > 10000:
# get the string version of the number
x_string = str(x)
# See if its the same as its reverse
if x_string == x_string[::-1]:
# Print out the palindrome we're currently looking at
print ("Looking for 3-digit factors of " + x_string)
# Let's try all the factors from 999 to 100
for f in reversed(range(100, 1000)):
# First, check if f is a factor of x by checking if the
# remainder is 0 when we divide x by f.
# Then, check if the other factor, x/f, is less than 1000
# to make sure it is three digits
if x%f == 0 and x/f < 1000:
# If we made it here, we found the number!!
print("Found the number!")
print("Number: {}".format(x))
print("Factors: {}, {}".format(f, x/f))
# We set this to be true because using a "break"
# statement will only break out of the inner most
# loop (the one where we're modifying f
found_an_answer = True
break
# Now that we left the inner loop, we can check the
# found_an_answer variable to see if we should
# break out of the outer loop to.
if found_an_answer:
break
# Guess we didn't find an answer yet. LEt's look at the next
# smallest number.
x = x-1
One more little thing - instead of having using a while loop and manually decreasing x inside it, you could just do a for loop counting down, by changing the loop to be
for x in range(999998, 10000, -1):
Then you don't need the x=999998 line or the x = x-1 line.
Related
I was solving the 3rd Question on Project Euler (Largest Prime Factor) and I'm a beginner at Python 3.
This is the solution I came up with, it works but not with very large numbers
x=int(input("Enter a number:"))
a=[]
for i in range(1,x+1):
cnt=0
if x%i==0:
for j in range(1,i+1):
if i%j==0:
cnt=cnt+1
if cnt==2:
a.append(i)
print(a[len(a)-1])
I understand its very basic, and its too slow to run large inputs, but is there any way a compiler could give me the output for this input - 600851475143. I tried using pypy3, it was taking too long as well.
Its my first time I'm using stackoverflow, so let me know if I'm doing anything wrong too.
I know you said you don't want to change the code but you would have to, if you want to solve it efficiently.
There actually a lib just for this eulerlib but the built-in math module can do it too.
If you want to use python with no modules you could try this but it is probably just as slow for large numbers
def Largest_Prime_Factor(n):
prime_factor = 1
i = 2
while i <= n / i:
if n % i == 0:
prime_factor = i
n /= i
else:
i += 1
prime_factor = max(prime_factor, n)
return prime_factor
The built-in math module can also do this and is far quicker. Since it is built-in you don't need any external libs like eulerlib
import math
# Getting input from user
n = int(input("Enter the number : "))
maxPrimeFactor = 0
# Checking and converting the number to odd
while n % 2 == 0:
maxPrimeFactor = 2
n = n/2
# Finding and dividing the number by all
# prime factors and replacing maxPrimeFactor
for i in range(3, int(math.sqrt(n)) + 1, 2):
while n % i == 0:
maxPrimeFactor = i
n = n / i
if n > 2:
maxPrimeFactor = n
print("The largest prime Factor of the number is ",int(maxPrimeFactor))
sum = 2
x=3
y=5000
for i in range (x,y):
for j in range (2,i):
if i%j==0:
break
elif i%j!=0 and j==i-1:
sum += i
if i==y-1 and y<2000000:
x=y
y+=5000
else:
continue
print(sum)
**I am not getting what is wrong in this code. By running this I came to know that the Last If and Else statement are not running **
Given your code, there are a couple of things wrong. First, sum is a python function name and should never be used as a variable name. It will get you into trouble in more ways than I care to think about. Second, the last else statement is not needed, because whether the if clause above it is or is not executed executed, the for loop will be executed again. Third, I don't understand the purpose of y and the magical value 5000, unless you are trying to provide an end value for your loop. The problem with this approach is you seem to try and extend it's range in increments of 5000. The problem is that once the initial for loop is executed, it creates a local iterable from x to 5000, and subsequent changes to y do not affect the for loops range.
I would approach the problem differently, by creating a list of primes and then use the python sum method to add all the values. Here is the code:
def sum_primes(max_prime):
""" Return Sum of primes Less than max_prime"""
primes = [2]
indx_num = 3
while primes[-1] <= max_prime:
update = True
for prime in primes:
if indx_num == prime or indx_num % prime == 0:
update = False
break
if update:
primes.append(indx_num)
indx_num += 2
#return summ of all values except the last
return sum(primes[:-1])
Executing sum_primes(2000000)
yields 1709600813
list1 = [140,232,857,273,405,374,1234,394,1803]
u = 0
b = 4
for i in list1[u:b]
u+= 4
u+= 4
print(max(i))
Now I wanna take the max value from that list but only from list1[0:4] and continue with that.
Now I want to do something like it on this code:
for im in images:
ww, hh = zip(*(im.size for im in images))
www, hhh = im.size
max_h = max(hh)
y_test = []
try:
new_im.paste(im, (x_offset,y))
with open('x.txt', 'a') as file:
file.write(str(x_offset) + "\n")
with open('y.txt', 'a') as file:
file.write(str(y) + "\n")
with open('w.txt', 'a') as file:
file.write(str(www) + "\n")
with open('h.txt', 'a') as file:
file.write(str(hhh) + "\n")
x_offset += im.size[0]
if x_offset > int(q_w) - www:
print(max(hh))
x_offset =0
y += max(hhh)
if hh < y:
y += hhh
if hh > y:
y -= hhh
else:
y += max_h
except:
continue
if x_offset > int(q_w) - www then I want to take the max value of hhh until here.
How can I do that?
Please understand that we apply max( ... ) to a sequence,
rather than to a single scalar value,
e.g. max([6, 7, 8]) rather than max(4).
That first example was unclear.
I think your intent is to run a window of size k=4 over the list
and display local maxima.
A more natural way to express that, without incrementing u inside the loop,
would be:
for i in range(len(list1) - k):
window = list1[i : i + k]
print(i, max(window))
A very similar approach would apply to your second example.
Phrase the for loop in this way, and slice off k elements:
for i, im in enumerate(images):
if i + k < len(images):
window = images[i : i + k]
...
After that you're on your own,
do something useful with window,
as your question was unclear on details of what you want.
You wrote this line within the loop:
ww, hh = zip(*(im.size for im in images))
It computes the same thing each time, so to make things quicker
it belongs outside the loop.
Additionally, it trashes the im iteration variable,
so for the rest of the loop im is a constant value,
it is always the last element of images.
This seems Bad, it's probably not what you wanted.
Similarly, this is a constant
which could be hoisted outside the loop:
max_h = max(hh)
Also, your except: continue is correct,
but except: pass would be the more usual idiom,
expressing the intent to simply ignore the exception.
No statements follow it in the code you posted,
so both would work out the same.
Understand that continue would skip to top-of-loop,
skipping the following statements if there were any.
For the given sorted list,the program should return the index of the number in the list which is greater than the number which is given as input.
Now when i run code and check if it is working i am getting 2 outputs. One is the value and other output is None.
If say i gave a input of 3 for the below code.The expected output is index of 20 i.e., 1 instead i am getting 1 followed by None.
If i give any value that is greater than the one present in the list i am getting correct output i.e., "The entered number is greater than the numbers in the list"
num_to_find = int(input("Enter the number to be found"))
a=[2,20,30]
def occur1(a,num_to_find):
j = i = 0
while j==0:
if a[len(a)-1] > num_to_find:
if num_to_find < a[i]:
j=1
print(i)
break
else:
i = i + 1
else:
ret_state = "The entered number is greater than the numbers in the list"
return ret_state
print(occur1(a,num_to_find))
This code is difficult to reason about due to extra variables, poor variable names (j is typically used as an index, not a bool flag), usage of break, nested conditionals and side effect. It's also inefficient because it needs to visit each element in the list in the worst case scenario and fails to take advantage of the sorted nature of the list to the fullest. However, it appears working.
Your first misunderstanding is likely that print(i) is printing the index of the next largest element rather than the element itself. In your example call of occur1([2, 20, 30], 3)), 1 is where 20 lives in the array.
Secondly, once the found element is printed, the function returns None after it breaks from the loop, and print dutifully prints None. Hopefully this explains your output--you can use return a[i] in place of break to fix your immediate problem and meet your expectations.
Having said that, Python has a builtin module for this: bisect. Here's an example:
from bisect import bisect_right
a = [1, 2, 5, 6, 8, 9, 15]
index_of_next_largest = bisect_right(a, 6)
print(a[index_of_next_largest]) # => 8
If the next number greater than k is out of bounds, you can try/except that or use a conditional to report the failure as you see fit. This function takes advantage of the fact that the list is sorted using a binary search algorithm, which cuts the search space in half on every step. The time complexity is O(log(n)), which is very fast.
If you do wish to stick with a linear algorithm similar to your solution, you can simplify your logic to:
def occur1(a, num_to_find):
for n in a:
if n > num_to_find:
return n
# test it...
a = [2, 5, 10]
for i in range(11):
print(i, " -> ", occur1(a, i))
Output:
0 -> 2
1 -> 2
2 -> 5
3 -> 5
4 -> 5
5 -> 10
6 -> 10
7 -> 10
8 -> 10
9 -> 10
10 -> None
Or, if you want the index of the next largest number:
def occur1(a, num_to_find):
for i, n in enumerate(a):
if n > num_to_find:
return i
But I want to stress that the binary search is, by every measure, far superior to the linear search. For a list of a billion elements, the binary search will make about 20 comparisons in the worst case where the linear version will make a billion comparisons. The only reason not to use it is if the list can't be guaranteed to be pre-sorted, which isn't the case here.
To make this more concrete, you can play with this program (but use the builtin module in practice):
import random
def bisect_right(a, target, lo=0, hi=None, cmps=0):
if hi is None:
hi = len(a)
mid = (hi - lo) // 2 + lo
cmps += 1
if lo <= hi and mid < len(a):
if a[mid] < target:
return bisect_right(a, target, mid + 1, hi, cmps)
elif a[mid] > target:
return bisect_right(a, target, lo, mid - 1, cmps)
else:
return cmps, mid + 1
return cmps, mid + 1
def linear_search(a, target, cmps=0):
for i, n in enumerate(a):
cmps += 1
if n > target:
return cmps, i
return cmps, i
if __name__ == "__main__":
random.seed(42)
trials = 10**3
list_size = 10**4
binary_search_cmps = 0
linear_search_cmps = 0
for n in range(trials):
test_list = sorted([random.randint(0, list_size) for _ in range(list_size)])
test_target = random.randint(0, list_size)
res = bisect_right(test_list, test_target)[0]
binary_search_cmps += res
linear_search_cmps += linear_search(test_list, test_target)[0]
binary_search_avg = binary_search_cmps / trials
linear_search_avg = linear_search_cmps / trials
s = "%s search made %d comparisons across \n%d searches on random lists of %d elements\n(found the element in an average of %d comparisons\nper search)\n"
print(s % ("binary", binary_search_cmps, trials, list_size, binary_search_avg))
print(s % ("linear", linear_search_cmps, trials, list_size, linear_search_avg))
Output:
binary search made 12820 comparisons across
1000 searches on random lists of 10000 elements
(found the element in an average of 12 comparisons
per search)
linear search made 5013525 comparisons across
1000 searches on random lists of 10000 elements
(found the element in an average of 5013 comparisons
per search)
The more elements you add, the worse the situation looks for the linear search.
I would do something along the lines of:
num_to_find = int(input("Enter the number to be found"))
a=[2,20,30]
def occur1(a, num_to_find):
for i in a:
if not i <= num_to_find:
return a.index(i)
return "The entered number is greater than the numbers in the list"
print(occur1(a, num_to_find))
Which gives the output of 1 (when inputting 3).
The reason yours gives you 2 outputs, is because you have 2 print statements inside your code.
I am a beginner at learning python 3 and I am just writing basic programs. I wrote this simple program which would take a number in and divide it by numbers starting from 1 to the square root of the number and find the remainders and add it to a list and print it.
import math
def prime_checker(num):
n=1
list_of_remainder=[]
while n == math.floor(num**0.5):
var=int(num % n)
list_of_remainder.append(var)
n += 1
return list_of_remainder
var=prime_checker(10)
print(var)
Please tell me what I did wrong. I would like to point out here that I did try to research a bit and find error but I couldn't and only then have I posted this question.
The problem that I faced was that it printed out an empty list.
to start with, your while loop is not executed even once. The condition for your while loop is
while n == math.floor(num**0.5):
The argument num you are passing to the function prime_checker is equal to 10. In this case your condition test is:
while 1 == math.floor(10**0.5)
which is
while 1 == 3 which is obviously not true and as a result the loop is not executed even once.
import math
def prime_checker(num):
list_of_remainder = []
number=num;
n=1
x=math.floor(number**0.5)
while n <= x:
v=int(number % n)
list_of_remainder.append(v)
n += 1
return list_of_remainder
var=prime_checker(10)
print(var)