Reputation: 1109
This is the problem statement my question stems from (from Hackerrank): You are given an integer N. Can you find the least positive integer X made up of only 9's and 0's, such that, X is a multiple of N? X is made up of one or more occurences of 9 and zero or more occurences of 0.
I thought I would use double recursion but I'm having trouble understanding how to make it work. My function takes in "multiple", which is a string (so that I can append either '0' or '9' to it in further function calls and not have to deal with arithmetic), and "divisor".
Basically I wanted to keep calling my function, adding either 9 or 0 to "multiple" at every call, returning the final "multiple" when it's finally divisible by "divisor". I was envisioning it as a tree of function calls splitting every time between function(multiple + '9', divisor) and function(multiple + '0', divisor).
However, it seems once I call return, it doesn't get to the second function call:
#multiple is a string
def rec_nine_zero(multiple, divisor):
if int(multiple) % divisor == 0:
return multiple
else:
return rec_nine_zero(multiple + '9', divisor)
return rec_nine_zero(multiple + '0', divisor)
The below works:
print(rec_nine_zero('9', 1111))
However, if I try this (where the desired multiple is 90):
print(rec_nine_zero('9', 5)
It crashes and tells me basically that the stack blew up, meaning it never got to the second function call.
One problem I can see is that even if I manage to get the return statement to call both functions (with multiple + '9' and multiple + '0'), I feel like all of the branches of the function call tree except one (the one that finally finds the right result) will keep going until the stack says "annnnd...we're done".
EDIT: Based on Prune's answer, here is my new function:
def rec_nine_zero(multiples, divisor):
for multiple in multiples:
if int(multiple) % divisor == 0:
return multiple
new_multiples = []
for multiple in multiples:
new_multiples.append(multiple + '0')
new_multiples.append(multiple + '9')
return rec_nine_zero(new_multiples, divisor)
Upvotes: 1
Views: 231
Reputation: 5860
Not the answer but heres another simpler way to do the question -
def rec_nine_zero(divisor):
d = divisor
while True:
if all([True if i in '09' else False for i in `d`]): return d
else: d+=divisor
print rec_nine_zero(111)
Anyways to answer your question -
There are some caveats in your code which might give you some tips about recursion.
And unfortunately, you cannot construct a base case for this problem if you solve it this way. The solution that @Prune gave is the right one.
Hope it helps!
Yeah you got it right! Anyways, I like shortening the code so here you go with the canonical bfs-
def rec_nine_zero(multiples, divisor):
que = [];que.append('9')
while(len(que) != 0):
k = que.pop()
if int(k)%divisor == 0:return k
que.append(k+'9');que.append(k+'0')
return -1
print rec_nine_zero('9', 5)
PS - I'm sure it can be shortened more!
Upvotes: 2
Reputation: 77827
It blows up because you've done this in the canonical fashion of depth-first search. The first branch you try in a string of 9's, as long as needed to find a solution. Since there isn't any such solution for N=5, you recur until you blow the stack.
Change over to breadth-first. Generate and test your smallest string, '9'. When that fails, recur on the list of strings you want to extend: ["9"].
In the recursion, you append '0' and '9' to each candidate in the list. On the first recursion, this gives you ["90", "99"]. With N=5, you'll return success on this stage. If you have some other number, such as 7, you'll recur with this new list.
On the next step, you'll test the list ["900", "909", "990", "999"], and continue this process until you succeed.
BTW, you can perhaps make this easier if you quit converting between string and int: just start with 9. The next stage will work on 10*x and 10*x+9 for each x in the previous list.
Does that get you moving?
Upvotes: 3