While loop not existing as expected - python-3.x

I have the code below where in the function neural_net_trainer(p, a), the while-loop is meant to end/exit when the value of p is equal to the value of a. However, the loop keeps running infinitely.
Instead of while-loop I tried for-loop, to loop it 30 times (running the 'update' function each time), and 'p' eventually becomes equal to 'a'. But I need to use while-loop instead because I don't know how many times the loop will run. It's whenever 'p' will become equal to 'a'.
# 'p' represent prediction. 'a' represent actual output of Neural network.
#-- improving Neural Network prediction (using derivative of cost function) --
def slope(p, a):
return 2 * (p - a)
# --- Create the Update rule function (to correct prediction) ---
def update(p, a):
p = p - 0.1 * slope(p, a)
return p
# -- Train network - minimising the cost function until prediction is equal to actual output
# - In while loop, if 'p' is not equal to 'a', then 'update' function will increment/decrement 'p' accordingly, until 'p' == 'a'. While-loop should then exit.
def neural_net_trainer(p, a):
print('prediction = ' + str('{:.2f}'.format(p)) + '. Actual Output = ' + str('{:.2f}'.format(a)))
while p != a:
p = update(p, a)
print('prediction = ' + str('{:.2f}'.format(p)))
else:
print('Prediction = ' + str('{:.2f}'.format(p)) + ', and actual output = ' + str('{:.2f}'.format(a)) + '. Our Neural Network is trained on this dataset.')
# - Testing 'neural_net_trainer' function
a = 4
p = 3
neural_net_trainer(p, a)
Basically the code simulates functions of a very simple neural network, where the functions receive two values - p (the predicted output) and a (the actual output). In the code - the slope function is a formula needed to correct the prediction (to become equal to the actual output). update function does the updating/correction. And neural_net_trainer function uses a while-loop to run update function enough times, until p (prediction) is equal to a (actual output). At which point the while-loop should exit.
Any help would be really appreciated.

The problem here is that you're checking for exact equality and p - a never reaches the exact 0.
Try a weaker condition as a guard of the while loop, for example:
THRESHOLD = 1e-5
while abs(p - a) > THRESHOLD:

p is not reaching 4.0, it is merely reaching 3.999999999999999..., which gets rounded to 4.00 when you use {:.2f} to format it. p != a remains True because 4.0 != 3.999999999999999.
This is more of an algorithmic problem than a python problem, but perhaps round() will come in handy to solve this based on p approaching a instead of a fixed number of iterations.

Related

The sum of the primes below 10 is 2 + 3 + 5 + 7 = 17. Find the sum of all the primes below two million.(I am not getting what is wrong in this code)

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

Finding palindrome of sum

Here's the problem statement:
For a given no. num, perform:
1. Add num and reverse(num)
2. Check whether the sum is palindrome or not. Else repeat.
Here is my solution. The program seems to be working for the 3 test cases given but when I am executing this program, for 1 private test case I am getting server time out error. Is my program not efficient?
flag=0
iteration=0
num = 195 # sample no. output produced is 9339 which is a palindrome.
while(flag!=1):
#print("iteration ",iteration)
num_rev= int(str(num)[::-1]) #finding rev of number
#print(num_rev)
total= num+num_rev #adding no and no_rev
#print(total)
total_rev= int((str(total))[::-1]) # finding total rev
iteration=iteration+1
if total==total_rev: #if equal, printing palindrome
print("palindrome")
flag=1
else:
num=total #else the new no becomes sum of old num and old_rev
Begin by profiling your code for each of your test cases to find out what is taking so long. I suggest using Jupyter Notebook's code profiling magic. Paste your code into a Jupyter Notebook cell and being the cell with %%prun. Along with other information, it will return a list of function calls, the number of times each function is called, and the amount of time each function takes to run. Compare the run time of your test cases to your server's timeout limit.
If the problem is not with your code and its evolving complexity as the number increases in size, it may be a problem with your server.
...
Note that a palindrome must contain at least 2 or 3 elements depending on your accepted definition.
Consider that one of your test cases may be venturing into arbitrarily large integers that take an unpredictable amount of time to compute. Consider that this compute time may exceed your server's timeout limit.
Furthermore, consider this modified version of your code that accepts an arbitrarily-defined max iteration depth per seed number. It also accepts an arbitrary seed number and a max seed number. Then returns an ordered list of all non-duplicate seed numbers, their respective palindrome sums, the number of iterations required to find the palindrome, and the approximate time required to perform the search:
#flag = 0
iteration = 0
maxiter = 1000
num = 0
max_num = 10000
used_seeds = []
palindromes = []
while num < max_num:
seed = num
while(iteration <= maxiter) and len(str(total))>2:
if num in used_seeds:
break
iteration+=1
num_reversed = int(str(num)[::-1])
total = num + num_reversed
total_reversed = int((str(total))[::-1])
if total == total_reversed:
used_seeds.append(num)
palindromes.append( [num, total] )
break
else:
num = total
num = seed+1
iteration = 0
palindromes.sort(key=lambda elem: elem[0])
print(palindromes)
The results are fascinating, by the way. Hopefully this helps.

Euler 4, Modulo issue

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.

Not showing output python, no error showing

Let us consider polynomials in a single variable x with integer coefficients: for instance, 3x^4 - 17x^2 - 3x + 5. Each term of the polynomial can be represented as a pair of integers (coefficient,exponent). The polynomial itself is then a list of such pairs.
We have the following constraints to guarantee that each polynomial has a unique representation:
Terms are sorted in descending order of exponent
No term has a zero coefficient
No two terms have the same exponent
Exponents are always nonnegative
For example, the polynomial introduced earlier is represented as
[(3,4),(-17,2),(-3,1),(5,0)]
The zero polynomial, 0, is represented as the empty list [], since it has no terms with nonzero coefficients.
Write Python functions for the following operations:
addpoly(p1,p2) ?
def addpoly(p1,p2):
p1=[]
p2=[]
for i in range(0,len(p1)):
for j in range(0,len(p2)):
L=[]
if p1[i][1]==p2[j][1]:
L=L[p1[i][0]+p2[j][0]][p1[i][1]]
elif p1[i][1]!=p2[j][1]:
L=L+p1[i][j]
L=L+p2[i][j]
print("L")
You are reassigning the p1 and p2 arguments to empty lists at the top of your function. This means you will always be checking for i in range(0, 0), which is an empty range. In other words, nothing in your loop will be executed. This is why you are not seeing any output. You are not seeing any error messages, because there is nothing wrong with your syntax, the problem is with the logic.
My math skills are nonexistent, so I cannot comment on the accuracy of most of the logic in your code, but for sure you need to get rid of the first two lines of your function (p1 = [] and p2 = []) or your function will do nothing.
Also, make sure to print the variable L rather than the string "L" to print your list:
print(L)
try this code
def addpoly(p1,p2):
L=[]
for i in range(0,len(p1)):
for j in range(0,len(p2)):
if p1[i][1] == p2[j][1] and p1[i][0]+p2[j][0] != 0 :
L.append((p1[i][0]+p2[j][0],p1[i][1]))
elif p1[i][1] == p2[j][1] and p1[i][0]+p2[j][0] == 0 :
pass
elif i == j:
L.append(p2[i])
L.append(p1[i])
return (L)

11+ digit ints not working

I'm using python 3 for a small extra credit assignment to write an RSA cracker. The teacher has given us a fairly large (large enough to require more than 32 bits) int and the public key. My code works for primes < 32 bits. One of the reasons I chose python 3 is because I heard it can handle arbitrarily large integers. In the python terminal I tested this by doing small things such as 2**35 and factorial(70). This stuff worked fine.
Now that I've written the code, I'm running in to problems with overflow errors etc. Why is it that operations on large numbers seem to work in the terminal but won't work in my actual code? The errors state that they cannot be converted to their C types, so my first guess would be that for some reason the stuff in the python interpreter is not being converter to C types while the coded stuff is. Is there anyway to get this working?
As a first attempt, I tried calculating a list of all primes between 1 and n (the large number). This sort of worked until I realized that the list indexers [ ] only accept ints and explode if the number is higher than int. Also, creating an array that is n in length won't work if n > 2**32. (not to mention the memory this would take up)
Because of this, I switched to using a function I found that could give a very accurate guess as to whether or not a number was prime. These methods are pasted below.
As you can see, I am only doing , *, /, and % operations. All of these seem to work in the interpreter but I get "cannot convert to c-type" errors when used with this code.
def power_mod(a,b,n):
if b < 0:
return 0
elif b == 0:
return 1
elif b % 2 == 0:
return power_mod(a*a, b/2, n) % n
else:
return (a * power_mod(a,b-1,n)) % n
Those last 3 lines are where the cannot convert to c-type appears.
The below function estimates with a very high degree of certainty that a number is prime. As mentioned above, I used this to avoid creating massive arrays.
def rabin_miller(n, tries = 7):
if n == 2:
return True
if n % 2 == 0 or n < 2:
return False
p = primes(tries**2)
if n in p:
return True
s = n - 1
r = 0
while s % 2 == 0:
r = r+1
s = s/2
for i in range(tries):
a = p[i]
if power_mod(a,s,n) == 1:
continue
else:
for j in range(0,r):
if power_mod(a, (2**j)*s, n) == n - 1:
break
else:
return False
continue
return True
Perhaps I should be more specific by pasting the error:
line 19, in power_mod
return (a * power_mod(a,b-1,n)) % n
OverflowError: Python int too large to convert to C double
This is the type of error I get when performing arithmetic. Int errors occur when trying to create incredibly large lists, sets etc
Your problem (I think) is that you are converting to floating point by using the / operator. Change it to // and you should stay in the int domain.
Many C routines still have C int limitations. Do your work using Python routines instead.

Resources