Runtime error, sorting function without using .sort - python

I am supposed to write the sorting function. Define
a function sort list that takes in a list and returns a list sorted in ascending order.
(4 marks)
Note: your code should make use of the insert list function defined earlier.
With my previous defined variables:
def search(x , seq):
for i in seq:
if x > max(seq):
return len(seq)
elif x < min(seq):
return 0
return search(x, seq[:-1])
def insert_tup(x, tup):
searchtuple = search(x, tup)
ontheleft = tup[:searchtuple]
ontheright = tup[ searchtuple:]
altogether = ontheleft + (x,) + ontheright
return altogether
def insert_list(x, lst):
A = search(x, lst)
lst.insert(A, x)
return lst
I did a trial
def sort_list(lst):
result = []
for i in lst:
result += [i]
return insert_list(result[0], lst)
But i keep getting Runtime error where
File "", line 7, in search
return search(x, seq[:-1])
The output is desired to be
sort_list([5, 1, 9])
[1, 5, 9]

You are recursively calling the search() method and never breaking out of this loop. I expect this is raising a RuntimeError: maximum recursion depth exceeded exception.
Python has a recursion limit to protect against infinite recursion. FYI you can modify the recursion limit via sys.setrecursionlimit - but this is not something you should be doing.
Instead you can fix this by re-writing your algorithm iteratively.
I also suggest you read the Python sorting wiki, as this demonstrates the pythonic way to sort things with the built in sorted() function and the list method sort(). You don't need to re-invent the wheel.

You need a base case for the recursion. Something like:
if len(seq)==1:
return seq
Otherwise it calls itself forever. And the result is the error that you see.

Related

Am I using list comprehensions wrong?

So my Python code to keep on finding the sum of a number's digits (9983 = 9+9+8+3 = 29 = 2+9 = 11 = 1+1 = 2) below isn't working, and it gives me this exception
ValueError: invalid literal for int() with base 10: '['".
It was working before when instead of using list comprehension, I did it by iterating through the list normally, so I suspect it's a problem with the list comprehension? Help?
x = int(input())
def rec(x):
if (x<10):
return x
return rec(sum(x))
def sum(x):
lst = [int(y) for y in list(str(x))]
return sum(lst)
print(rec(x))
There's a built-in function called sum, and you defined a function with the same name - but you need the original function as part of the solution.
Let's start by renaming your version of sum to summation, and let's take the opportunity to simplify the code a bit more:
def rec(x):
if x < 10:
return x
return rec(summation(x))
def summation(x):
return sum(int(y) for y in str(x))
See how the built-in sum was needed inside summation? that's why your function must have a different name! And although we could have used a list comprehension, it's easier and more efficient to pass a generator expression to sum. Alternatively (but less efficiently) we could have used a list comprehension:
def summation(x):
lst = [int(y) for y in str(x)]
return sum(lst)
Either way, it works as expected:
rec(9983)
=>2
You are creating confusion for Python ;-)
The problem is in def sum(x):, not in the list comprehension. sum is a reserved keyword. Just rename the function (and the call to the function) and it works.

convert a python code with function structure to class structure with generator and calculate time and space complexity

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).

Writing filter() function but getting typeError

my code consists of me recreating the function 'filter()' and using it with a function to filter words longer than 5 characters. It worked with the actual function filter when I tried it btw...I'm using python 3+
def filter1(fn, a):
i = 0
while i != len(a):
u = i - 1
a[i] = fn(a[i], a[u])
i += 1
return a
def filter_long_words(l):
if len[l] > 5:
return [l]
listered = ['blue', 'hdfdhsf', 'dsfjbdsf', 'jole']
print(list(filter1(filter_long_words, listered)))
getting error
TypeError: filter_long_words() takes 1 positional argument but 2 were given
You are passing two parameters to fn (which refers to filter_long_words) here:
a[i] = fn(a[i], a[u])
But filter_long_words only accepts one parameter.
Notes:
You can loop through lists using for item in my_list, or if you want index as well for index, item in enumerate(my_list).
I think you might get an IndexError since u will be -1 in the first round of your loop.
The filter function can also be expressed as a list comprehension: (item for item in listered if filter_long_words(item))
My version of filter would look like this, if I have to use a for loop:
def my_filter(fn, sequence):
if fn is None:
fn = lambda x: x
for item in sequence:
if fn(item):
yield item
Since you have stated that you are using Python 3, this returns a generator instead of a list. If you want it to return a list:
def my_filter(fn, sequence):
if fn is None:
fn = lambda x: x
acc = []
for item in sequence:
if fn(item):
acc.append(item)
return acc
If you don't need to use a for loop:
def my_filter(fn, sequence):
if fn is None:
fn = lambda x: x
return (item for item in sequence if fn(item))
Your're calling fn with 2 parameters in filter1(fn, a), and since you've passed filter_long_words() to filter1 as fn, that triggers the error.
But there's more weird stuff:
I don't understand the magick of filter1 or what you were trying to
accomplish, but it seems to me that you don't have a clear idea what to do.
But if you want to mimic (somehow) how filter works, you have to return a
list which contains only items for which the fn function returns true. When
you know this, you can rewrite it - here are a few suggestions for rewrite
# explicit, inefficient and long, but straightforward version:
def filter1(fn, a):
new_list = []
for item in a:
if fn(item):
new_list.append(item):
return new_list
# shorter version using list comprehensions:
def filter1(fn, a):
return [item for item in a if fn(item)]
The filter_long_words function is wrong too - it should return True or
False. The only reason why it could work is because any non-empty list is
treated as True by python and default return value of a function is None,
which translates to False. But it's confusing and syntactically wrong to use
len[l] - the proper usage is len(l).
There are a few suggestions for rewrite, which all returns explicit boolean
values:
# unnecessary long, but self-explanatory:
def filter_long_words(l):
if len(l) > 5:
return True
else
return False
# short variant
def filter_long_words(l):
return len(l) > 5
You are calling "filter_long_words" with 2 parameter => fn(a[i], a[u]) also there is an error
def filter_long_words(l):
if **len[l]** > 5:
return [l]
len is builtin method it should be len(l)

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.

Using recursion to create a linked list from a list

how would one go about using recursion in order to take a list of random values and make it a linked list? Where each value is a node. As of right now, i've tried implementing the following...
def pyListToMyList(pylst):
lists = mkMyList()
lists.head = pyListToMyListRec(pylst)
return lists
def pyListToMyList(pylst):
if pylst:
return mkEmptyNode()
else:
return mkNode(pylst[0], pyLstToMyListRec(pylst[1:]))
The problem is the the else statement which returns an error saying that the index is out of range.
def pyListToMyList(pylst):
if not pylst:
return mkEmptyNode()
else:
return mkNode(pylst[0], pyLstToMyListRec(pylst[1:]))
EDIT: Though this is O(n^2) because of all the list copying.
I would do
def pyListToMyList(pylst, i=0):
if i > len(pylst):
return mkEmptyNode()
else:
return mkNode(pylst[i], pyLstToMyListRec(pylst, i+1))
or even more efficient and less likely to overflow stack (though this does not use recursion):
def pyListToMyList(pylst):
lst = mkEmptyNode()
for x in reversed(pylist):
lst = mkNode(x, lst)
return lst

Categories