The question is to write a recursive function that Removes duplicates from the list.
Hint: it can be implemented with two auxiliary functions.
The list contains one and only one of each value formerly present
in the list. The first occurrence of each value is preserved.
Implement and test a recursive version of this method
def clean(self):
key_node = self._front
while key_node is not None:
# Loop through every node - compare each node with the rest
previous = key_node
current = key_node._next
while current is not None:
# Always search to the end of the list (may have > 1 duplicate)
if current._value == key_node._value:
# Remove the current node by connecting the node before it
# to the node after it.
previous._next = current._next
self._count -= 1
else:
previous = current
# Move to the _next node.
current = current._next
# Check for duplicates of the _next remaining node in the list
key_node = key_node._next
return
And this is what I have so far, I don't understand what is auxiliary functions:
def clean(list):
i = 1
if len(list) == 0:
return []
elif len(list) == 1:
return list
elif list[i] == list[i-1]:
del list[i]
return clean(list[i:])
Example: for list = [1,2,2,3,3,3,4,5,1,1,1], the answer is [1,2,3,4,5,1]
Here is one function that calls a another, recursive function and produces the result you want. I suppose you could call clean2 an auxiliary function, although, like you, I don't know exactly what that's supposed to mean. It's a rather ridiculous piece of code but it doesn't use any standard library functions and it modifies x in place. I would expect it to be horribly inefficient. If I wrote this for my day job I'd probably resign.
def clean(x):
clean2(x, 1)
def clean2(x, i):
if i >= len(x):
return
if x[i] == x[i - 1]:
del x[i]
clean2(x, i)
else:
clean2(x,i+1)
the_list = [1,2,2,3,3,3,4,5,1,1,1]
clean(the_list)
print(the_list)
>>> [1,2,3,4,5,1]
Here's a recursive definition using an auxiliary function go to actually implement the recursion. The idea is that the outer clean function can take any iterable object (e.g. a list) and it always produces a list of values:
def clean(iterable):
def go(iterator, result):
try:
x = next(iterator)
if result == [] or result[-1] != x:
result.append(x)
return go(iterator, result)
except StopIteration:
return result
return go(iter(iterable), [])
clean just invokes a locally-defined go function, passing an iterator and the eventual result value (initially an empty list). go then tries to advance the iterator and compares the referenced value with the end of the result: if it's different (or if the result is empty), the value is appended. go then recurses.
Related
I am trying to pass a parameter "by value". I have tried making a deep copy of the parameter that is passed recursively in order to prevent any changes from circling back to the parent function calls.
Here is a snippet of code that tries to generate the array of all possible parentheses.
def generateParenthesis(n):
#Iterate for each move.
M = 2 * n
retArray = []
def recHelper(numMoves, perm, stack):
print("Function call: ", numMoves, perm, stack)
newPerm = copy.deepcopy(perm)
newStack = stack.copy()
#Base case, no moves
if (numMoves == 0):
retArray.append(newPerm)
return
#Case when left move is valid
if (numMoves != len(newStack)):
#Apply the left move. Pass it recursively
newPerm +='('
#Update the stack accordingly
newStack.append('(')
#Decrease numMoves
newNumMoves = numMoves - 1
#Call it recursively
recHelper(newNumMoves, newPerm, newStack)
#Case when right move is valid
if len(newStack) != 0:
#Apply the right move. Pass it recursively
newPerm +=')'
#Update the stack accordingly, delete the top, last elm
newStack.pop()
#Decrease numMoves
newNumMoves = numMoves - 1
#Call it recursively
recHelper(newNumMoves, newPerm, newStack)
#done
return
recHelper(M, "", [])
return retArray
Unfortunately, calling generateParenthesis(1) returns ['()','()(', '()()'] and not ['()'].
def generateParenthesis(n):
retArray = []
def append_solutions(partial, opened_p, closed_p):
if opened_p < n:
append_solutions(partial + '(', opened_p + 1, closed_p)
if closed_p < n and opened_p > closed_p:
append_solutions(partial + ')', opened_p, closed_p + 1)
if opened_p == closed_p == n and partial:
retArray.append(partial)
append_solutions('', 0, 0)
return retArray
print(generateParenthesis(1))
print(generateParenthesis(2))
print(generateParenthesis(3))
print(generateParenthesis(4))
print(generateParenthesis(5))
After 3 hours of simplifying ideas, I came with this working code.
Now it finds things like (()())() for generateParenthesis(4), for instance.
The code is very self explanatory. You keep a count of opened/closed parenthesis and only close parenthesis when there are correspondent opened.
I chose not to use a stack because since everything in Python is passed by "pointer copy", stacks (i.e. lists in your OP) would require a costly list(stack) in the function body, creating a local copy of the list.
Notice that I create new strings (partial + '(', for instance), and these new string objects are passed by "pointer copy" to recursion calls.
(Sorry I lack a better term now. But this is important)
Edit
Your solution has a problem with the variable newPerm. Its value is leaking into the second recursive function. Also, you need to understand that all your copying of values is not needed except for the stack.
See how your function can be simplified. I think it's working:
def generateParenthesisOP(n):
#Iterate for each move.
M = 2 * n
retArray = []
def recHelper(numMoves, perm, stack):
print("Function call: ", numMoves, perm, stack)
if numMoves == 0:
retArray.append(perm)
return
if numMoves != len(stack):
left_stack = list(stack)
left_stack.append('(')
recHelper(numMoves - 1, perm + '(', left_stack)
if len(stack) != 0:
right_stack = list(stack)
right_stack.pop()
recHelper(numMoves - 1, perm + ')', right_stack)
recHelper(M, "", [])
return retArray
Use + operator to add to a list rather than .append() behavior to best emulate pass by value behavior.
Python officially abides by pass-by-object-reference. In your case, when a list stack or perm passed and modified in the child function, the parent function's stack or perm will see the updated variable.
I'm new to recursion and finding it pretty difficult to grasp. I can't figure out how to append an empty array if I can't directly "touch" it. If its a string I would add the value each time. If it was a number that involved multiplication, I could multiply it each time, but with an array, I don't know what to do.
I dont know how to append to an empty array without being able to directly "touch" it.
This is what I've done so far:
def laugh(num):
if num == 0:
return []
# This doesnt work since we can't append a function call. I'm unsure what to do.
return laugh(num - 1).append("ha ")
print(laugh(3)) -> ["ha, ha, ha"]
If could do this easily if i could just return a string of "Ha"'s instead. I could return an empty string and just add a "Ha" for each step.
You can modify it like:
def laugh(num):
if num == 0:
return []
haha = laugh(num-1)
haha.append("ha")
return haha
Since append does not return the modified list, you have to do it in two steps. Using concatenation and the ternary operator, you can shrink this to:
def laugh(num):
return laugh(num-1) + ["ha"] if num else []
In this case you are mutating the list by calling append on it. What you want to do is return a new list:
def laugh(num):
# base case
if num == 0:
return []
# recursive case
return ["ha"] + laugh(num-1)
I have this function:
def most(P, S):
def recursion(P,S):
if len(S) == 0:
return []
elif P(S[0]):
return [P(S[0])] + recursion(P, S[1:])
else:
return recursion(P, S[1:])
if len(recursion(P,S)) > len(S)/2:
return True
else:
return False
It takes an input of function, P and list, S. If the result of P(S[i]) is true for most of S, then the function most() should return true. Any idea how I can do this recursively without a function inside of a function? In other words, how can I return a single boolean value from a recursive function that takes a list as its input?
Thanks!
The biggest key to recursion is understanding the "terminal condition." What is the state where the function must stop? In this case, it's the empty list.
def most(pred, lst):
if lst == []:
return # but what do we return?
You will need to keep track of the number of list elements that meet an expectation... so you have to keep track of both the expectation (i.e. how many have to be true in order for "most" to be true), as well as the count so far. Let's add those...
def most(pred, lst, threshold=None, count=0):
if threshold is None:
threshold = len(lst) // 2
if lst == []:
return count > threshold
So, then we need to "deconstruct" the list so that we can recurse over it. Let's add that...
def most(pred, lst, threshold=None, count=0):
if threshold is None:
threshold = len(lst) // 2
if lst == []:
return count > threshold
# Check the 'truth' of the head of the list...
if pred(lst[0]):
count += 1
# ...and pass the tail of the list into the next iteration.
return most(pred, lst[1:], threshold, count)
That should be all that you need. Now, I'll caution you that if your lists are of significant length, Python will blow its stack. This is also significantly slower than a solution using a for loop or reduce, because of all the additional function calls.
If I were implementing most for production code, I would do this:
def most(pred, lst):
return sum(1 for x in lst if pred(x)) > len(lst) // 2
Im not sure how to get my recursion to work properly or keep from infinitely repeating.
This is what i have so far:
def listSquareR(lst):
if len(lst)== 1:
return lst[0]**2
else:
return lst[0]**2+[listSquareR(lst[1:])]
last return line is obviously wrong
Another possibility:
def listSquare(L):
if L: return [L[0]**2] + listSquare(L[1:])
else: return []
An even shorter version (as Cristian Ciupitu mentions below) is:
def listSquare(L):
return [L[0]**2] + listSquare(L[1:]) if L else []
You have it almost right, but the key is to mind your types. In your code:
def listSquareR(lst):
if len(lst)== 1:
return lst[0]**2 # Returning a number
else:
return lst[0]**2+[listSquareR(lst[1:])] # Returning a number plus a list of a list
We just need two small fixes:
def listSquareR(lst):
if len(lst)== 1:
return [lst[0]**2] # Returning a list
else:
return [lst[0]**2] + listSquareR(lst[1:]) # Returning a list plus a list
def SquareArea(width):
if width == 0:
return 0
else:
return SquareArea(width-1) + (2*width-1)
This is a recursive function I've recently used to find the area of a square.
And since the area of a square is Side*Side, one can use it to find the square of any function.
Now all that is required of you is to make a loop, eg:
for i in range (list):
and implement this function on i
Or maybe use while loop.
newList=[]
length = len(list)
while i != length:
newList.append(SquareArea(i))
And then return the newList
I looked up and found a close example, but the answer found in this link: Remove adjacent duplicate elements from a list won't run the test cases for this problem. So this is all I have so far:
def remove_dups(thelist):
"""Returns: a COPY of thelist with adjacent duplicates removed.
Example: for thelist = [1,2,2,3,3,3,4,5,1,1,1],
the answer is [1,2,3,4,5,1]
Precondition: thelist is a list of ints"""
i = 1
if len(thelist) == 0:
return []
elif len(thelist) == 1:
return thelist
elif thelist[i] == thelist[i-1]:
del thelist[i]
return remove_dups(thelist[i:])
def test_remove_dups():
assert_equals([], remove_dups([]))
assert_equals([3], remove_dups([3,3]))
assert_equals([4], remove_dups([4]))
assert_equals([5], remove_dups([5, 5]))
assert_equals([1,2,3,4,5,1], remove_dups([1,2,2,3,3,3,4,5,1,1,1]))
# test for whether the code is really returning a copy of the original list
mylist = [3]
assert_equals(False, mylist is remove_dups(mylist))
EDIT while I do understand that the accepted answer linked above using itertools.groupby would work, I think it wouldn't teach me what's wrong with my code & and would defeat the purpose of the exercise if I imported grouby from itertools.
from itertools import groupby
def remove_dups(lst):
return [k for k,items in groupby(lst)]
If you really want a recursive solution, I would suggest something like
def remove_dups(lst):
if lst:
firstval = lst[0]
# find lowest index of val != firstval
for index, value in enumerate(lst):
if value != firstval:
return [firstval] + remove_dups(lst[index:])
# no such value found
return [firstval]
else:
# empty list
return []
Your assertion fails, because in
return thelist
you are returning the same list, and not a copy as specified in the comments.
Try:
return thelist[:]
When using recursion with list it is most of the time a problem of returning a sub-list or part of that list. Which makes the termination case testing for an empty list. And then you have the two cases:
The current value is different from the last one we saw so we want to keep it
The current value is the same as the last one we saw so we discard it and keep iterating on the "rest" of the values.
Which translate in this code:
l = [1,2,2,3,3,3,4,5,1,1,1]
def dedup(values, uniq):
# The list of values is empty our work here is done
if not values:
return uniq
# We add a value in 'uniq' for two reasons:
# 1/ it is empty and we need to start somewhere
# 2/ it is different from the last value that was added
if not uniq or values[0] != uniq[-1]:
uniq.append(values.pop(0))
return dedup(values, uniq)
# We just added the exact same value so we remove it from 'values' and
# move to the next iteration
return dedup(values[1:], uniq)
print dedup(l, []) # output: [1, 2, 3, 4, 5, 1]
problem is with your return statement,
you are returning
return remove_dups(thelist[i:])
output will be always last n single element of list
like for above soon,
print remove_dups([1,2,2,3,3,3,4,5,1,1,1])
>>> [1] #as your desired is [1,2,3,4,5,1]
which returns finally a list of single element as it don't consider Oth element.
here is recursive solution.
def remove_dups(lst):
if len(lst)>1:
if lst[0] != lst[1]:
return [lst[0]] + remove_dups(lst[1:])
del lst[1]
return remove_dups(lst)
else:
return lst