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.
Related
I wrote this simple python code but now I have to convert this into a class structure which accepts an iterator and act as a generator to yield the tuples(instead of return it should yield). I am unable to convert it:
def func(str,size):
size1 = size
list1 = []
for i in str:
list1.append(i)
if len(list1) < size1:
return (0)
continue
if len(list) > win_size1:
list1.pop(0)
min = min(list1)
return (min)
if __name__ == '__main__':
str = [1,2,3,4,5,6]
size = [4]
res = sol2(str,size)
Also I have to get the time and space complexity. In my view time complexity looks O(n)(I am not 100% confident though) but I am unable to determine space complexity.
How can I convert this code into a class with generator and what would be the time and space complexity?
Currently the continue statements which follow the return statements make no sense - continue will never be reached. However, you can yield each tuple with yield instead of return, e.g., replace
return (None,None,None,None)
with
yield (None,None,None,None)
Now the continue statement can actually be executed, and your algorithm can return more than one tuple.
Simply changing the returns into yields makes your function a generator.
I don't see any necessity to make this a "class structure". You can create a class and make sol2() a method of that class, but it's not clear why you should want to do that.
only the window1 and window2 will ask for extra space, so I think the space complexity will be O(n).
I'm attempting to generate all n choose k combinations of a list (not checking for uniqueness) recursively by following the strategy of either include or not include an element for each recursive call. I can definitely print out the combinations but I for the life of me cannot figure out how to return the correct list in Python. Here are some attempts below:
class getCombinationsClass:
def __init__(self,array,k):
#initialize empty array
self.new_array = []
for i in xrange(k):
self.new_array.append(0)
self.final = []
self.combinationUtil(array,0,self.new_array,0,k)
def combinationUtil(self,array,array_index,current_combo, current_combo_index,k):
if current_combo_index == k:
self.final.append(current_combo)
return
if array_index >= len(array):
return
current_combo[current_combo_index] = array[array_index]
#if current item included
self.combinationUtil(array,array_index+1,current_combo,current_combo_index+1,k)
#if current item not included
self.combinationUtil(array,array_index+1,current_combo,current_combo_index,k)
In the above example I tried to append the result to an external list which didn't seem to work. I also tried implementing this by recursively constructing a list which is finally returned:
def getCombinations(array,k):
#initialize empty array
new_array = []
for i in xrange(k):
new_array.append(0)
return getCombinationsUtil(array,0,new_array,0,k)
def getCombinationsUtil(array,array_index,current_combo, current_combo_index,k):
if current_combo_index == k:
return [current_combo]
if array_index >= len(array):
return []
current_combo[current_combo_index] = array[array_index]
#if current item included & not included
return getCombinationsUtil(array,array_index+1,current_combo,current_combo_index+1,k) + getCombinationsUtil(array,array_index+1,current_combo,current_combo_index,k)
When I tested this out for the list [1,2,3] and k = 2, for both implementations, I kept getting back the result [[3,3],[3,3],[3,3]]. However, if I actually print out the 'current_combo' variable within the inner (current_combo_index == k) if statement, the correct combinations print out. What gives? I am misunderstanding something to do with variable scope or Python lists?
The second method goes wrong because the line
return [current_combo]
returns a reference to current_combo. At the end of the program, all the combinations returned are references to the same current_combo.
You can fix this by making a copy of the current_combo by changing the line to:
return [current_combo[:]]
The first method fails for the same reason, you need to change:
self.final.append(current_combo)
to
self.final.append(current_combo[:])
Check this out: itertools.combinations. You can take a look at the implementation as well.
I have this:
def ppend(n):
lis = []
if n.rest == None:
pass
else:
lis.append(n.first)
ppend(n.rest)
return lis
n is a linked-list [1,2,3]
The output I am getting is :
[1]
But the output I am looking for is:
[1,2,3]
You are creating a new lis list on every recursion. (Incidentally, you might try to find more descriptive names.) Only the first list is returned, however, because you don't do anything with the other lists that result from recursion. Instead, you simply call the function, which simply creates a new list without doing anything with the value returned by the function. You can see this in the following line:
ppend(n.rest) # a new list is created but nothing is done with the result of the function
If you only plan to use the function once, you can simply move the lis assignment outside of the function:
lis = []
def ppend(n):
if n.rest is not None: # the first if statement appears unnecessary
lis.append(n.first)
ppend(n.rest)
return lis # or don't return it but simply refer to lis where you need to
The above approach, however, will not work as well if you plan to use the function multiple times and always need a new list. In the latter case, you might add a second function like this:
def make_ppend(n, lis): # add lis as a parameter to be explicit, but you could rely on scope instead of adding this extra parameter
if n.rest is not None:
lis.append(n.first)
make_ppend(n.rest, lis)
def ppend(n):
lis = [] # now in the local scope
make_ppend(n, lis)
return lis
I am guessing you are after something like the second solution.
I want every element in l(which is a list) to be added to a.
When I run the function, it gives me '[]' every time. How can I fix this?
def sim(l):
a = []
if len(l)>0:
a = a.append(l.pop())
l.pop()
return sim(l)
return a
Several things are wrong:
You shouldn't use lowercase L for a variable name - it looks like one
At the top of the function you assign an empty list to a - ultimately sim will be called with an empty list, then a will be assigned an empty list, the conditional statement will fail and sim will return an empty list.
Inside the conditional statement you assign the return value of list.append() to a. The return value is None so whatever a was before, it gets wiped out.
Inside the conditional statement you pop() two items out of your control list
An empty list has a boolean value of false so there is no need to explicitly check its length,
def sim(el, a = None):
if el:
a.append(el.pop())
return sim(el, a)
return a
I was taught to write the base case of a recursive function as the first statement:
def sim(el, a = None):
if not el:
return a
a.append(el.pop())
return sim(el, a)
append() doesn't return anything but does update the existing list. In other words, by trying to assign the result of the append() method, you're setting a to nothing after you have already appended the item.
Your Code :def sim(l):
a = []
when you call Function recursively return sim(l) every time it is call sim(l) and a=[] is empty.
Try This :
def sim(l,a):
if len(l)>0:
a.append(l.pop())
print a
return sim(l,a)
return a
Is this a homework assignment where you're required to do it in a certain (overly complicated) way? Because if not, you can add one list to another in Python like so:
>>> l = [1, 2, 3]
>>> a = []
>>> a.extend(l)
>>> a
[1, 2, 3]
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.