Why does this Python code give Runtime Error(NZEC)? - python

I already read the other questions and answers but couldn't implement any of the solutions to my code. I'm still clueless about the reason why this code gives a runtime error.
I'm trying to submit the code on CodeChef, yet it gives the Runtime Error(NZEC), although the code runs flawlessly on my console for some inputs. Here's my code:
def GetSquares(base):
if not base or base < 4:
return 0
else:
x = (base - 4) - (base % 2) + 1
return x + GetSquares(base - 4)
num_test = int(input())
for test in range(num_test):
base = int(input())
print (int(GetSquares(base)))
Codechef's explanation for NZEC:
NZEC stands for Non Zero Exit Code. For C users, this will be
generated if your main method does not have a return 0; statement.
Other languages like Java/C++ could generate this error if they throw
an exception.
The problem I'm trying to solve:
https://www.codechef.com/problems/TRISQ

The problem description says that the input is constrained to be < 10^4. That's 10,000! Your code will need to make 10,000/4 = 2500 recursive calls to GetSquares, that's a lot! In fact, it's so much that it's going to give you, fittingly, this error:
RuntimeError: maximum recursion depth exceeded
You're going to have to think of a better way to solve the problem that doesn't involve so much recursion! Because you're doing this coding challenge, I'm not going to give a solution in this answer as that would sort of defeat the purpose, but if you'd like some prodding towards an answer, feel free to ask.

The question puts a constraint on the value of 'B' which is 10000 at max, which means there are a lot of recursive calls and giving a runtime error. Try solving using iteration.

Related

Is there a difference between these codes?

I am a beginner in coding and I've been learning python just lately.
I tried to do some recursion exercises, my codes run most of the time but there is one thing that is worrying me.
My code is always longer than the one in the solution.
Take this exercise for example
(Write a Python program to get the sum of a non-negative integer.Test Data:sumDigits(345) -> 12sumDigits(45) -> 9)
My answer is this
def sum_num(n,sum1=0):
k=int(n)
if k%10==k:
return sum1+k
else:
sum1+=k%10
k=k//10
return(sum_num(k,sum1))
print(sum_num(2384))
and the solution is this
def sumDigits(n):
if n == 0:
return 0
else:
return n % 10 + sumDigits(int(n / 10))
print(sumDigits(345))
print(sumDigits(45))
print(sumDigits(345))
print(sumDigits(45))
My code run perfectly but it's just longer. My question is 'is it okay to have a long code, if not how can I learn to shorten it'.
Thank you
Well, writing shorter and cleaner code is good practice because when you have long code thats hard to read its going to be harder for you and especially oher people to work with it, and troubleshooting can be really difficult. Think simple and try to write it as clean as it could possibly be. There isnt really a way to LEARN it but practice and studying and just trying to think simple should help.

Python Z3 solver not correctly reporting satisfiability for exponent constraints

I noticed the Z3 Solver library for python wasn't correctly reporting satisfiability for a problem involving exponents that I was working on. Specifically, it reported finding no solutions on cases where I knew a valid one -- unless I added constraints that effectively "told it the answer".
I simplified the problem to isolate it. In the code below, I'm asking it to find q and m such that q^m == 100. With the constraint 0 <= q < 100, you have, of course, q=10, m=2. But with the code below, it reports finding no solution (raise Z3Exception("model is not available")):
import z3.z3 as z
slv = z.Solver()
m = z.Int('m')
q = z.Int('q')
slv.add(100 == (q ** m))
slv.add(q >= 0)
slv.add(q < 100)
slv.add(m >= 0)
slv.add(m <= 100)
slv.check()
However, if you replace slv.add(m <= 100)) with slv.add(m <= 2) (or slv.add(m == 2)!), it has no problem finding the solution (of q=10, m=2).
Am I using Z3 wrong somehow?
I thought it would only report unsatisfiability ("model is not available") if it proved there was no solution and would otherwise hang while searching for a solution. Is that wrong? I didn't expect to be in a position where it only finds the solution if you shrink down the search space enough.
I haven't had this problem with any other operation besides exponentiation (e.g. addition, modulo, etc.).
You're misinterpreting what z3 is telling you. Change your line:
slv.check()
to:
print(slv.check())
print(slv.reason_unknown())
And you'll see it prints:
unknown
smt tactic failed to show goal to be sat/unsat (incomplete (theory arithmetic))
So, z3 doesn't know if your problem is sat or unsat; so you cannot ask for a model. The reason for this is the power operator: It introduces non-linearity, and the theory of non-linear integer equations is undecidable in general. That is, z3's solver is incomplete for this problem. In practice, this means z3 will apply a bunch of heuristics, and will hopefully solve the problem for you. But you can get unknown as well, as you observed.
It's not surprising that if you add extra constraints you're helping the solver and thus it finds an answer. You're just helping it further and those heuristics have an easier time. With different versions of z3, you can observe different behavior. (i.e., in the future, they might be able to solve this problem out-of-the-box, or maybe the heuristics will get worse and you helping it this way won't resolve the issue either.) Such is the nature of automatic-theorem proving with undecidable theories.
Bottom line: Any call to check can return sat, unsat, or unknown. Your program should check for all three possibilities and interpret the output accordingly.

Having some problems with Project Euler 31

I've been working on solving Problem 31 from Project Euler. I'm almost finished, but my code is giving me what I know is the wrong answer. My dad showed the right answer, and mine is giving me something completely wrong.
coins = (1,2,5,10,20,50,100,200)
amount = 200
def ways(target, avc):
target = amount
if avc <= 1:
return 1
res = 0
while target >= 0:
res = res + ways(target, avc-1)
target = target - coins[avc]
return res
print(ways(amount, 7))
This is the answer I get.
284130
The answer is supposed to 73682.
EDIT: Thank you to everyone who answered my question. Thanks to all of you, I have figured it out!
I see several ways how you can improve the way you're working on problems:
Copy the task description into your source code. This will make you more independent from Internet resources. That allows you to work offline. Even if the page is down or disappears completely, it will enable someone else understanding what problem you're trying to solve.
Use an IDE that does proper syntax highlighting and gives you hints what might be wrong with your code. The IDE will tell you what #aronquemarr mentioned in the comments:
There's also a thing called magic numbers. Many of the numbers in your code can be explained, but why do you start with an avc of 7?. Where does that number come from? 7 does not occur in the problem description.
Use better naming, so you understand better what your code does. What does avc stand for? If you think it's available_coins, that's not correct. There are 8 different coins, not 7.
If it still does not work, reduce the problem to a simpler one. Start with the most simple one you can think of, e.g. make only 1 type of coin available and set the amount to 2 cent. There should only be 1 solution.
To make sure this simple result will never break, introduce an assertion or unit test. They will help you when you change the code to work with larger datasets. They will also change the way you write code. In your case you'll find that accessing the variable coins from an outer scope is probably not a good idea, because it will break your assertion when you switch to the next level. The change that is needed will make your methods more self-contained and robust.
Then, increase the difficulty by having 2 different coins etc.
Examples for the first assertions that I used on this problem:
# Only 1 way of making 1 with only a 1 coin of value 1
assert(find_combinations([1], 1) == 1)
# Still only 1 way of making 1 with two coins of values 1 and 2
assert(find_combinations([1,2], 1) == 1)
# Two ways of making 2 with two coins of values 1 and 2
assert(find_combinations([1,2], 2) == 2)
As soon as the result does no longer match your expectation, use the debugger and step through your code. After every line, check the values in the debugger against the values that you think they should be.
One time, the debugger will be your best friend. And you can never imagine how you did stuff without it. You just need to learn how to use it.
Firstly, read Thomas Weller's answer. They give some excellent suggestions as to how to improve your coding and problem solving.
Secondly, your code works, and gives the correct answer after the following changes:
As suggested, remove the target = amount line. You're resigning the argument of the function to global amount on each call (even on the recursive calls). Having removed that the answer comes up to 3275 - still not the right answer.
The other thing you have to remember is that Python is 0-indexed. Therefore, your simplest case condition ought to read if avc <= 0: ... (not <=1).
Having made these two changes, your code gives the correct answer. Here is your code with these changes:
coins = (1,2,5,10,20,50,100,200)
amount = 200
def ways(target, avc):
if avc <= 0:
return 1
res = 0
while target >= 0:
res = res + ways(target, avc-1)
target = target - coins[avc]
return res
print(ways(amount, 7))
Lastly, there are plenty of Project Euler answers out there. Having solved the yourself, it might be useful to have a look at what others did. For reference, I have not actually solved this Project Euler before, so I had to do that first. Here is my solution. I've added a pile of comments on top of it to explain what it does.
EDIT
I've just noticed something quite worrying: Your code (after fixes) works only if the first element of coins is 1. All the other elements can be shuffled:
# This still works ok
coins = (1,2,200,10,20,50,100,5)
# But this does not
coins = (2,1,5,10,20,50,100,200)
To ensure that this is always the case, you can just do the following:
coins = ... # <- Some not necessarily sorted tuple
coins = tuple(sorted(coins))
In principle there are a few other issues. Your solution breaks for non-unique values coins, and which don't include 1. The former you could fix with the use of sets, and the latter by modifying your if avc <= 0: case (check for the divisibility of the target by the remaining coin). Here is you piece of code with these changes implemented. I've also renamed the variables and the function to be a bit easier to read, and used coins as the argument, rather that avc pointer (which, by the way, I could not stop reading as avec):
unique = lambda x: sorted(set(x)) # Sorted unique list
def find_combinations(target, coins):
''' Find the number of ways coins can make up the target amount '''
coins = unique(coins)
if len(coins)==1: # Only one coin, therefore just check divisibility
return 1 if not target%coins[0] else 0
combinations = 0
while target >= 0:
combinations += find_combinations(target, coins[:-1])
target -= coins[-1]
return combinations
coins = [2,1,5,10,20,50,100,200] # <- Now works
amount = 200
print(find_combinations(amount, coins))

Python PuLP RecursionError

I'm working in a LP problem with the PuLP Library and I have some strange that I can't explain by myself. I have nearly 100 variables and constraints, and I want to put it in my model, but I can't. It tells me
RecursionError: maximum recursion depth exceeded in comparison
First, I've tried to parse it in a for loop:
for cent_artic in df_demand['REQUIRED']:
display(df_offers[df_offers['REQUIRED']==cent_artic])
lista = list(df_ofertas1[df_ofertas1['REQUERIDO']==cent_artic]['OFERTADO'])
display(lista)
prob += lpSum(lista) >= cent_artic_dict[cent_artic], "Restriccion para cent_artic "+cent_artic
And the RecursionError showed up.
I've tried to pass only one restriction to the problem:
prob += lpSum(['c-1_a-2757_p-13','c-1_a-2757_p-12','c-1_a-2757_p-188']) >= cent_artic_dict['c-1_a-2757']
And it's the same. I can't understand why Python tell me something about a Error of Recursion, if I try to pass only one equation...
cent_artic_dict = {'c-5_a-17372_p-188': var_c_5_a_17372_p_188,
'c-179_a-2757_p-188': var_c_179_a_2757_p_188,
'c-18_a-17372_p-188': var_c_18_a_17372_p_188,
'c-26_a-2757_p-18': var_c_26_a_2757_p_18,
'c-41_a-2757_p-18': var_c_41_a_2757_p_18,
'c-156_a-2757_p-188': var_c_156_a_2757_p_188,
'c-24_a-17372_p-188': var_c_24_a_17372_p_188,
...
}
Now, the dataframe of df_offers have a shape of (89,6). At the beginning, it was (89,21)
Could anybody explain why I'm having the RecursionError? Thank you.
I've seen another question about it, but it doesn't have answer, only an advice
I had a similar issue and was getting the identical recursion error.
For me, I had a data type issue, and my constraint value was stored as a string and not a number! This is equivalent to the value in cent_artic_dict['c-1_a-2757'] in the original question. Once my right-hand side constraint was a number I was good to go. Based on comments I think Krakenudo might have been facing a similar situation.
I have very little idea what you are doing but i can point out that
prob += lpSum(['c-1_a-2757_p-13','c-1_a-2757_p-12','c-1_a-2757_p-188']) >= cent_artic_dict['c-1_a-2757']
is not valid because lpSum needs lists of LpVariables not strings

I keep on having problems with syntax and calculating the roots of the quadratic equation

Hey I am having problems with calculating the roots of the quadratic equation with the quadratic formula, using python's complex number functionality.
When I try
>>> if root<0:
root=abs(complex(root))
j=complex(0,1)
x1=(-b+sqrt(root))/2*a
x2=(-b-j+sqrt(root))/2*a
else:
I get the error message
SyntaxError: invalid syntax
Then, when I try instead
>>> if root<0:
root=abs(complex(root))
j=complex(0,1)
x1=(-b+j+sqrt(root))/2*a
x2=(-b-j+sqrt(root))/2*a
break
I get the error
SyntaxError: 'break' outside loop
I am trying to put:
else:
x1=(-b+j+sqrt(root))/2*a
x2=(-b-j+sqrt(root))/2*a
under it but it won't work.
Any help please?
Not sure I understand your problem, but it looks like you are not properly indenting -- Python uses white space to mark blocks, so the above should look like:
if root<0:
root=abs(complex(root))
j=complex(0,1)
x1=(-b+j+sqrt(root))/2*a
x2=(-b-j+sqrt(root))/2*a
else:
x1=(-b+j+sqrt(root))/2*a
x2=(-b-j+sqrt(root))/2*a
although that doesn't make sense because x1 and x2 are calculated the same in both branches, and j is not defined in the else branch... so maybe what you really want is
if root<0:
root=abs(complex(root))
j=complex(0,1)
x1=(-b+j+sqrt(root))/2*a
x2=(-b-j+sqrt(root))/2*a
Part of my confusion is the prompt: enter code here -- this is not a standard Python prompt so either you changed your prompt or you are using some other program with your Python. At any rate, hope this helps.
try importing the complex math module, available online in a number of forms. I believe there is an implementation for complex numbers in the standard python distributions, as well as in numpy/scipy. You can also try working out the real and complex components of your roots separately (by including a test based on the value of the discriminant). Also, your if and elif tests are identical.
As #bythenumbers points out, your if and elif conditions are the same. Also, are you getting exceptions or the wrong values? Also also, where you have j+sqrt(root), do you perhaps mean j*sqrt(root)?

Categories

Resources