Recursive calling of a method as an argument in python - python

I'm trying to write a recursive function in python, but instead of returning an integer type it returns a nonetype. I know there are other questions smiliar to this but not a single solution there worked for me.
Here is the code:
class t:
def search(self, globina, board):
board.legals = board.legal()
bestMove = 0
if(globina == 0):
return board.evaluation()
elif board.turn == False:
bestMove = -9999
for i in range(0, len(board.legals)):
board.move(board.legals[i])
board.display()
bestMove = max(bestMove, self.search(globina-1, board))
board.undo()
return bestMove
else:
bestMove = 9999
for i in range(0, len(board.legals)):
board.move(board.legals[i])
board.display()
bestMove = min(bestMove, self.search(globina-1, board))
board.undo()
return bestMove
z = t()
z.search(globina, board)

Your recursive method (as it appears in edited question) is doing the right thing, since it uses return in all of its cases.
That means that the None value must not be due to the recursive function itself, but rather it's a value being returned in the base case somewhere. For your function, that means board.evaluation() returns None at least some of the time.
In Python 3, I'd expect that to cause an exception in any of the recursive cases, as min and max will choke on a None value (since None isn't comparable to anything, including itself). In Python 2 however, all objects are comparable, though there may not be any particular meaning to comparisons between unlike types. The default behavior is to compare class names alphabetically (so all int and float instances are less than all str instances, which are less than all tuples), though if I recall correctly, None compares as less than all other values.

Related

How to call one of multiple returns?

def sudoku_solver(sudoku):
l = [0, 0]
if not find_empty_location(sudoku, l):
return True
row = l[0]
col = l[1]
for num in range(1, 10):
if check_location_is_safe(sudoku, row, col, num):
sudoku[row][col] = num
if sudoku_solver(sudoku):
return True,sudoku
sudoku[row][col] = 0
return False
def P():
a = np.zeros((9,9))
if sudoku_solver(sudoku):
a = sudoku_solver(sudoku)[1]
else:
a = 1
return a
There are two returns, True and sudoku. How can I call sudoku only in function P? When I run the function P(), it will show
'bool' object is not subscriptable.
You could make your function return a single value that would be either None or the sudoku data.
Python treats None as false so your condition could then be:
...
if sudoku_solver(sudoku):
a = sudoku_solver(sudoku)
...
Note that if sudoku_solver() is a complex and time consuming function, you will want to place its result in a variable BEFORE testing the condition so that it is not executed twice (as would be the case in the above condition)
...
a = sudoku_solver(sudoku)
if a:
...
Another option would be to systematically return a tuple with the boolean and the sudoku data (or None).
Your return statements would have to be changed to return True,sudoku and return False,None
Then your condition could use indexing directly:
...
if sudoku_solver(sudoku)[0]:
a = sudoku_solver(sudoku)[1]
...
but again, you probably don't want to execute the function twice so :
...
ok,a = sudoku_solver(sudoku)
if ok :
...
Another thing is that, if you're passing sudoku as a parameter, you have to realize that your function will modify the content of the calling variable even when it returns False. That may not be what you want but if it is, then there is no point in returning a second value because the caller's instance of the sudoku variable will already be modified and available.
When you see
return True,sudoku
you can catch the returned values like so
result, sudoku = my_function()
or if you've no interest in result
_, sudoku = my_function()
---Edit---
It seems your question centers around the two returns. Namely
return True,sudoku
versus
return False
That's adds unnecessary complexity. Can I suggest you simplify by instead using
return sudoku
and then later
return None
That means you can check the returned value like so
sudoku = my_function()
if (sudoku):
// Do something here
else:
// Do something else
You can't return multiple objects from a function, but you can return a container object, such as a list or tuple, that contains multiple member objects. Try using
return [ True, sudoku ]

Defining a default argument after with None: what if it's an array?

I'm passing an argument to a function such that I want to delay giving the default parameter, in the usual way:
def f(x = None):
if x == None:
x = ...
The only problem is that x is likely to be a numpy array. Then x == None returns a boolean array, which I can't condition on. The compiler suggests to use .any() or .all()
But if I write
def f(x = None):
if (x == None).any():
x = ...
this won't work if x goes to its default value, because then None == None is a Boolean, which has no .any() or .all() methods. What's my move here?
When comparing against None, it is a good practice to use is as opposed to ==. Usually it doesn't make a difference, but since objects are free to implement equality any way they see fit, it is not always a reliable option.
Unfortunately, this is one of those cases where == doesn't cut it, since comparing to numpy arrays returns a boolean mask based on the condition. Luckily, there is only a single instance of None in any given Python program, so we can actually check the identity of an object using the is operator to figure out if it is None or not.
>>> None is None
True
>>> np.array([1,2,3]) is None
False
So no need for any or all, you can update your function to something like:
def f(x=None):
if x is None:
print('None')
else:
print('Not none')
In action:
>>> f()
None
>>> f(np.array([1,2,3]))
Not none

recursive sorting in python

I am trying to run a sorting function recursively in python. I have an empty list that starts everything but everytime I try to print the list I get an empty list. here is my code. Any help would be greatly appreciated
def parse(list):
newParse = []
if len(list) == 0:
return newParse
else:
x = min(list)
list.remove(x)
newParse.append(x)
return sort(list)
The value of newParse is not preserved between invocations of the function; you're setting it equal to [] (well, you're creating a new variable with the value []).
Since the only time you return is
newParse = []
if len(list) == 0:
return newParse`
you will always be returning [] because that is the value of newParse at that time.
Because you are doing this recursively, you are calling the function anew, without keeping the function's own state. Take a moment to consider the implications of this on your code.
Instead of initialising newParse = [], add an optional parameter newParse defaulting to a bogus value, and set newParse = [] if you receive that bogus value for newParse. Otherwise, you'll actually be getting the same list every time (i.e. the contents of the list object are being mutated). And newParse through in your tail call.
You also seem to have the problem that your definition and and the supposedly-recursive call refer to different functions.
def sort(list, newParse = None):
if newParse is None:
newParse = []
if len(list) == 0:
return newParse
else:
x = min(list)
list.remove(x)
newParse.append(x)
return sort(list, newParse)
Here is what I think you are trying to do:
def recursive_sort(a_list):
def helper_function(list_to_be_sorted, list_already_sorted):
new = []
if len(list_to_be_sorted) == 0:
return list_already_sorted
else:
x = min(list_to_be_sorted)
list_to_be_sorted.remove(x)
new.append(x)
return helper_function(list_to_be_sorted, list_already_sorted + new)
return helper_function(a_list, [])
You shouldn't name variables list, as that is a builtin.
Also, if you are trying to implement a recursive sort function, you might want to look at quicksort, which is a very common (and fast) recursive sorting algorithm. What you have tried to implement is a recursive version of selection sort, which is much slower.
Also, if you actually need a sorting function, rather than just wanting to implement a recursive one, you should use the list method sort, or the function on an iterable sorted, both of which will be a lot faster than anything you could make in Python.

How do you make an object return a sorted array instead of an empty one in python?

I'm trying to create a library of some common algorithms so that people will be able to use them easily. I created an object called Compare, which has some methods that would be useful in these algorithms.
Code for Compare:
class Compare(list):
def __init__(self,arr):
self.arr = arr
def __compare(self,u,v):
# Compares one item of a Compare
# object to another
if u < v:
return 1
if u == v:
return 0
if u > v:
return -1
def __swap(self,arr,i,j):
# Exchanges i and j
temp = arr[i]
arr[i] = arr[j]
a[j] = temp
def __determine(self,arr):
# Determines if the array is sorted or not
for i in range(0,len(array)):
if self.__compare(arr[i], arr[i+1]) == -1:
return False
return True
def __printout(self,arr):
for i in range(0,len(array)):
return arr[i] + '\n'
def sorted(self):
if self.__determine(arr):
return True
return False
Here's one of the algorithms that uses this class:
def SelectionSort(array):
try:
array = Compare(array)
for ix in range(0, len(array)):
m = ix
j = ix+1
for j in range(0,len(array)):
if array.__compare(array[j], array[m]) == -1:
m = j
array.__swap(arr, ix, m)
return array
except(TypeError) as error:
print "Must insert array for sort to work."
The problem I'm having is that whenever I try to use this or any of the other algorithms, it returns an empty array instead of the sorted array. I'm not sure how to get the Compare object to return the sorted array.
I'm pretty sure this is what is happening. When you call :
array = Compare(array)
You overwrite the reference to the original array. Array is now a reference to a Compare object. Replace array with array.arr (or name array something better) and this should work I think! :)
Remember that python is loosely typed, so that your "array" variable is just a reference to some data. In this case, you are switching it from a reference to a list to a reference to a Compare object.
Think about:
>>> x = 1
>>> x
1
>>> x = 's'
>>> x
's'
And think about what happens to the 1 ;)
Your code has many problems some of them make it to fail
for example
in sorted you are using a maybe global arr that doesn't exist, instead
of self.arr).
in swap you also use a[j] = temp, but a is local to the method and you do not use it for anything
you are using two underscores for your methods. This puts name mangling to work, So the calls in the function do not work in the way you do them. Probably you want a single underscore to indicate that this are private methods.
But the main problem is that Compare is not returnig a list. For that you need:
class Compare(list):
def __init__(self, arr):
list.__init__(self, arr)
then:
>>> print Compare([1,2,3,4])
[1, 2, 3, 4]
In this way you should use in your methods self instead of self.arr because your instance is a list (or an instance of a subclass of list).
So the following is your code modified to actually work. The only problem is that your sorting algorithn is wrong an it is not sorting right. But you can do from here I suppose:
class Compare(list):
def __init__(self, arr):
list.__init__(self, arr)
def _compare(self, u, v):
# Compares one item of a Compare
# object to another
if u < v:
return 1
if u == v:
return 0
if u > v:
return -1
def _swap(self, i, j):
# Exchanges i and j
temp = self[i]
self[i] = self[j]
self[j] = temp
def _determine(self):
# Determines if the array is sorted or not
for i in range(len(array)):
if self._compare(self[i], self[i+1]) == -1:
return False
return True
def _printout(self):
for i in self:
return i + '\n'
def sorted(self):
if self._determine():
return True
return False
def SelectionSort(array):
try:
array = Compare(array)
for ix in range(len(array)):
m = ix
j = ix + 1
for j in range(len(array)):
if array._compare(array[j], array[m]) == -1:
m = j
array._swap(ix, m)
return array
except(TypeError) as error:
print "Must insert array for sort to work."
You're not returning the array, you're returning a Compare wrapped around the array. If you intend Compare to be a proxy, the wrapping is incomplete, as you don't forward the standard container operations to the proxied array. In addition, you'll need to consistently use the Compare instance. Currently, you sometimes use the Compare and other times use the original sequence object, such as every place you pass the sequence to a method. Instead, use the Compare object within its own methods.
However, that's having Compare do two things: be an algorithm collection, and be a sequence. If you keep the Compare object separate and work on the list directly, you can switch out the algorithms easily. This is the more typical approach; list.sort works this way, taking a comparator as an argument. You'll also need to fix your implementation of Compare, which uses the wrong variable name in numerous places (array, when the local variable is named arr). If you want anyone to use your library, it's going to have to be much better designed.
As further reasons not to make Compare a sequence, consider what happens when you need to change comparison methods: you end up wrapping the Compare in another, making the wrapped Compare useless.
Consider the approach used in math: an order is a relationship defined on a set, not an intrinsic part of the set, and it especially isn't a part of sequences of items from the set. This reveals another conceptual error with your original approach: it couples an ordering (which is a set relationship) with operations on sequences of elements from the set. The two should be kept separate, so that you can use different comparisons with the sequence operations.
Off-Topic
There are a number of other mistakes of various types in the code. For example, in SelectionSort you assume that type errors must be due to a non-sequence being passed as array. Comparing instances of uncomparable types (such as 0 and 'd') will also result in a type error. For another example, Compare.sorted is useless; it's of the pattern:
if test:
return True
return False
This is logically equivalent to:
return test
which means Compare.sorted is equivalent to Compare.__determine. Make the latter the former, as sorted is a more descriptive name. "determine" is too ambiguous; it begs the question of what's being determined.
You can get more code reviews at codereview.stackexchange.com.

recursive search boolean return function

Write a recursive function search(l,key) that returns a boolean: True if key is in the list l; False if it isn’t. Describe the base case(s) and how the smaller problem relates to the bigger one. You may not use the in operator or the index() list method.
Can anyone explain what i need to do here for the description? I dont know anything about recurrsion to know where to start. Its for a exam review lab assignment.
Here is the code i have been provided.
def search(l,key):
"""
locates key in list l. if present, returns True; else returns False.
PRE: l is a list.
POST: l is unchanged; returns True if key in l; False otherwise.
"""
Sample Main:
l1 = [1, '2', 'x', 5, -2]
print search(l1, 'x') # should output: "True"
print search(l1, 2) # should output: "False"
All recursion tends to follow the same rules:
Have one or more terminating cases.
Every other case is a slightly simpler form of the current case.
So, for example, a (very inefficient) way to add two positive numbers a and b:
if b is zero, return a.
otherwise add the two numbers a+1 and b-1.
Something like:
def addtwo (a, b):
if b == 0:
return a
return addtwo (a+1, b-1)
Now let's think about the cases for your assignment:
if the list is empty, you didn't find it: return false.
if the first element of the list is equal to your key, you found it: return true.
otherwise look in the list made by removing the first element.
In pseudo-code (which is very similar to Python but different enough that you'll have to do some work):
def search (list, key):
if list is empty:
return false
if key == first item in list:
return true
return search (list with first element removed, key)
Every question regarding recursion should be dealt with the same way (usually)...Ask yourself what is the base case and then build on that for higher cases...
So in this question, ask yourself, when can i be certain there is no key in the list...
It's obviously when the list is empty, you're certain it's not present.
For a bigger list, you compare the first element, if it's the same as the key, you return True right away, but incase it's not, you perform all the checks for the rest of the list....
So studying all these aspects,
Here's your Algorithm.
function locate(lst,key)
if lst == emptylist then return False
if lst[0] == key then return True
else return locate(lst[1..],key) //i use the notation lst[1...] to indicate list starting from 1 index.

Categories