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))
def reverse_number(x):
return x[::-1]
number_of_sums = int(input())
for i in range(number_of_sums):
s1 = input().split()
print(int(reverse_number(s1[0])) + int(reverse_number(s1[1])))
I have the following code, which should be a solution to a SPOJ problem. It compiles fine and works for examples that I provide, but as soon as I submit it says that it found an EOF error.
It points me to line 5 in the code, and I believe I understand why. When I use input() I try to get the whole line, right? So, how would I go ahead to only get the number? If that is the problem of course, it might be something else that ruins the code.
def reverse_number(x):
return x[::-1]
try:
number_of_sums = int(input())
for i in range(number_of_sums):
s1 = input().split()
if len(s1) > 0:
print(int(reverse_number(s1[0])) + int(reverse_number(s1[1])))
except ValueError:
print("Invalid Input")
Now, if you run the program and submit it will throw error stating "Invalid Input". Apart from adding the try block, also included the condition check for s1 as you might encounter an "Index out of range" error if not given proper input.
It may be that the grader/engine that checks the code is running Python2, in which case you could change to:
number_of_sums = int(raw_input())
before submitting (and a similar change on line 8).
I am a newbie in python, started learning the language a week ago tried to test it out in codechef...
Here is the question link: https://www.codechef.com/problems/COOMILK
So with what i understood so far i typed the following piece of code..
t=int(input())
f=[]
if(t >= 1 and t <= 50):
for each in range(t):
n=int(input())
if(n >= 1 and n <=50):
m=input().split()
for i in range(len(m)):
if(m[i]=='milk'):
q=1
elif(len(m)==1 and m[0]=='cookie'):
q=0
break
elif(m[i]=='cookie' and m[i+1]!='milk'):
q=0
break
f.append(q)
for i in f:
if(i==1):
print("YES")
elif(i==0):
print("NO")
So apart from the n constraint being not checked during the input, what actually showed was a runtime error.
New to this can someone explain it clearly why i am getting the nzec error?
Compiled it on my own and for all the test cases it worked properly but does not compile on code chef.. any help would be appreciated.
What i have gathered from the net is that there is no raw_input in python 3.x that i am using currently, so just a friendly reminder here....
NZEC stands for "Non Zero Exit Code". It occurs when you encounter a runtime error usually index out of bound error.
There is a mistake in the 14th line of your code:
elif (m[i]=='cookie' and m[i+1]!='milk'):
what if i+1 is out of range?
e.g.,
Consider the input to be:
1
3
cookie milk cookie
1 is the number of testcases.
3 is the number of elements in the
list.
'cookie milk cookie' composes the list elements.
When the value of i is 2 and your code's 14th line comes to execution, it will generate an index out of bound error(because m[i+1] i.e. m[3] doesn't exist!) which is a type of runtime error and thus generates NZEC error.
Add this code after the 7th line of your code:
if m[-1]=='cookie':
f.append(0)
continue
You could try using
try:
#working code
except Exception:
pass
Try and catch exception for java code.
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.
def travel():
travel.s=0
travel.frate=[]
travel.tr=[]
def accomodation():
print"""specialises
1.place 1
a.hotel 1
b.hotel 2
Hotel1:ac/non ac rooms
Ac.for ac...
Noac.for non ac...."""
hd=[5000,6000]
hg=[4000,7000]
TAc=[1000]
Nac=[400]
ch5=input("Enter your choice")
fav=raw_input("ENter hotel choice")
mode=raw_input("Enter ac/no ac")
if(ch5==1):
for i in hd:
frate=hd[i]+TAc
else:
frate=hd[i]+Nac
if(ch5==2):
for i in range(0,2,1):
frate=hg[i]+TAc
else:
frate=hg[i]+Nac
accomodation()
travel()
When i run the program , i get the error as List Index out of range.but in hd and hg list,there are only two elements, so index number will be from 0 right?? Is there anything i should import?? I even gave statements like this:
travel.frate=travel.hg[i]+TAc
but it still doesn't come.Thank you for your effort.
the indentation is proper now,but the output is still not coming.
The specific issue you are encountering is caused by these lines here:
if(ch5==1):
for i in hd:
frate=hd[i]+TAc
hd[i] looks at hd[5000] and hd[6000] which will throw an IndexError.
But if you fix that, you're going to run into another error, because
frate=hd[i]+TAc
tries to add a list TAc to an integer hd[i], which is an unsupported operation. You probably need frate=hd[i]+TAc[0], or even better, make TAc a number rather than a list. This issue occurs elsewhere in your code as well.
Finally, while not causing explicit issues in your code right now, there are two other problems:
ch5=input("Enter your choice") is dangerous since input tells Python to run whatever code snippet the user enters. In this case, much safer to do ch5=int(raw_input("Enter your choice"))
for i in range(0,2,1): is really for i in range(2): - only use the starting index and jump parameters if you need to change them from their default, namely 0 and 1.
There are other issues like variable scope (you're expecting travel.frate to be modified from within accommodation, but that's not happening) and defining variables in functions like travel.frate (not invalid syntax, but definitely strange) but those are probably better addressed outside of this question.