Pass by value for recursion? - python

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.

Related

How to recursively call out another function x number of times?

I have a working recursive function which I have to recursively call out in another function "depth" amount of times.
Working function:
def apply_dragon_rules(string):
"""
Write a recursive function that replaces characters in string.
Like so:
"a" -> "aRbFR"
"b" -> "LFaLb"
apply_dragon_rules("a") -> "aRbFR"
apply_dragon_rules("aa") -> "aRbFRaRbFR"
apply_dragon_rules("FRaFRb") -> "FRaRbFRFRLFaLb"
:param string: sentence with "a" and "b" characters that need to be replaced
:return: new sentence with "a" and "b" characters replaced
"""
if not string: # if the string is empty
return ""
elif string[0] == "b": # if the string start with b, replace it with a
return "LFaLb" + apply_dragon_rules(string[1:])
elif string[0] == "a": # if the string start with b, replace it with a
return "aRbFR" + apply_dragon_rules(string[1:])
else: # else, add this character and go to the next one
return string[0] + apply_dragon_rules(string[1:])
The function in which I have to recursively call out the working function "depth" times:
def curve(string, depth):
"""
Recursively generate the next depth of rules.
Calls apply_dragon_rules() function `depth` times.
curve("Fa", 2) -> "FaRbFRRLFaLbFR"
:param string: current instruction string
:param depth: how many times the rules are applied
:return: instructionset at iteration 'depth'
"""
if depth == 0:
return ""
elif depth == 1:
return apply_dragon_rules(string)
else:
return depth * apply_dragon_rules(apply_dragon_rules(string))
Expected output:
curve("Fa", 2) -> "FaRbFRRLFaLbFR"
My output(2x the expected output):
curve("Fa", 2) -> "FaRbFRRLFaLbFRFaRbFRRLFaLbFR"
I was able to produce a correct output by making function curve (although, that is not a recursive solution and only works if the "depth" is 2):
return apply_dragon_rules(apply_dragon_rules(string))
Any ideas how to implement depth into the curve function so it works as intended?
The second function doesn't need to be recursive. You can simply loop to achieve that effect in general.
def curve(string, depth):
if depth == 0:
return ""
else:
for i in range(depth):
string = apply_dragon_rules(string)
return string
print(curve("Fa", 2) == "FaRbFRRLFaLbFR") # Test result
A common approach is to pass the remaining depth as a parameter and make the base case of the recursion that this remaining depth is zero.
...which you already did halfway, but what's missing is to actually make the recursive call and pass the remaining depth—which is one less than the current depth:
def curve(string, depth):
if depth == 0:
return ""
else:
return curve(apply_dragon_rules(string), depth - 1)

Reverse a string in-place using recursion

There is a leetcode question on recursion. Reverse a string, in place, using recursion. Do not allocate an additional array.
Write a function that reverses a string. The input string is given as
an array of characters char[].
Do not allocate extra space for another array, you must do this by
modifying the input array in-place with O(1) extra memory.
You may assume all the characters consist of printable ASCII
characters.
My solution doesn't work as my slicing operator is creating a copy of the list, rather than being in place. I can't seem to add a parameter to the function, as the test harness isn't expecting an additional parameter.
How do you do this, without an additional parameter to detect the current position index into the string you are trying to reverse, or without an intermediate data structure you append to through the recursive call?
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
if len(s) <= 1:
return
temp = s[0]
s[0] = s[len(s)-1]
s[len(s)-1] = temp
return self.reverseString(s[1:len(s)-1])
My function with an input of "hello" returns ["o","e","l","l","h"]. This is because the first time the function is called it operates on the list in place, and subsequent calls are achieved through a slice of the string.
From what i understood, the solution should be recursive. Try this:
EDIT: (as should look in leetcode)
def reverseStringHelper(s, index):
length = len(s)
if index >= length / 2:
return
temp = s[index]
s[index] = s[length - 1 - index]
s[length - 1 - index] = temp
reverseString(s, index + 1)
def reverseString(s):
reverseStringHelper(s, 0)
Defining arr = ['h', 'e', 'l', 'l' ,'o'] and calling reverseString(arr, 0) will result in ['o', 'l', 'l', 'e', 'h']
You may call it from a different function so it would only accept the list.
Thanks all. The solution was to add a parameter with a default, to get over the issues with the leetcode test harness, so now I can do it as below:
class Solution:
def reverseString(self, s: List[str], start = 0) -> None:
"""
Do not return anything, modify s in-place instead.
"""
if len(s[start:len(s)-start]) <= 1:
return
end = len(s) - start - 1 # end postition
temp = s[start]
s[start] = s[end]
s[end] = temp
self.reverseString(s, start+1)
Try this
chars=list('string')
for i in range((len(chars)-len(chars)%2)//2):
chars[i], chars[-i-1]=chars[-i-1], chars[i]
print(chars)
print(''.join(chars))
This'll pass, since it has to be done in-place:
from typing import List
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
left, right = 0, len(s) - 1
while left < right:
s[left], s[right] = s[right], s[left]
left, right = left + 1, right - 1
References
For additional details, please see the Discussion Board where you can find plenty of well-explained accepted solutions with a variety of languages including low-complexity algorithms and asymptotic runtime/memory analysis1, 2.

How to introduce extra brackets into mathematical expressions in python

I'm working on a project to implement infix-to-postfix transformations in python.
The implementation of the code works as long as the expression is fully bracketed. It cannot handle expressions where humans would implicitly assume an order to the calculation.
For instance, I can use a fully-bracketed expression such as:
((3+15)*2)+(6-3)
And get the right result.
However, humans might normally write:
(3+15)*2+(6-3)
Where the first outer bracket is assumed.
Are there any algorithms that could correctly add brackets. If not, is there a best-practice solution for how to handle this sort of problem?
Update:
Here is the implementation of the parse tree function:
class BinaryTree:
def __init__(self, root):
self.key = root
self.left_child = None
self.right_child = None
def insert_left(self, new_node):
if self.left_child == None:
self.left_child = BinaryTree(new_node)
else:
t = BinaryTree(new_node)
t.left_child = self.left_child
self.left_child = t
def insert_right(self, new_node):
if self.right_child == None:
self.right_child = BinaryTree(new_node)
else:
t = BinaryTree(new_node)
t.right_child = self.right_child
self.right_child = t
def get_right_child(self):
return self.right_child
def get_left_child(self):
return self.left_child
def set_root_val(self, obj):
self.key = obj
def get_root_val(self):
return self.key
def build_parse_tree(fp_exp):
fp_list = re.findall('[+-/*//()]|\d+', fp_exp)
p_stack = Stack()
e_tree = BinaryTree('')
p_stack.push(e_tree)
current_tree = e_tree
for i in fp_list:
if i == '(':
current_tree.insert_left('')
p_stack.push(current_tree)
current_tree = current_tree.get_left_child()
elif i not in ['+', '-', '*', '/', ')']:
current_tree.set_root_val(int(i))
parent = p_stack.pop()
current_tree = parent
elif i in ['+', '-', '*', '/']:
current_tree.set_root_val(i)
current_tree.insert_right('')
p_stack.push(current_tree)
current_tree = current_tree.get_right_child()
elif i == ')':
current_tree = p_stack.pop()
else:
raise ValueError
return e_tree
def postorder(tree):
if tree != None:
postorder(tree.get_left_child())
postorder(tree.get_right_child())
print (tree.get_root_val())
The output from the second expression postorder:
3
6
15
2
3
-
+
The one with the first (correct) is:
3
15
+
6
2
3
-
+
Disclaimer: Sorry for that huge response; I was curious and just wrote down what I did during testing around a bit for your question. Find the entire code here: https://gist.github.com/jbndlr/3657fa890539d29c9e4b0311dc60835d
By the way, this is just test code and not meant to be used in production, as it may still be flawed.
Response
Your sequence parsing and tree setup with pushes of empty strings seems a bit odd, but I cannot accurately point to your error. Your parsing somehow swallows the * operator, probably because its left element is a closing bracket.
While I was playing around with this a bit, I tried to reproduce and came up with a solution that correctly parses simple equations and can generate the required parentheses. Even though no longer required, if the tree is already parsed correctly, you can use this to generate fully bracketed equations, or extend it by your own needs.
Preparation: The Imports
from __future__ import print_function
import re
Step 1: Tokenizing the Input
This function takes a string as an expression and generates a list of tuples representing your tokens. It also already classifies them as kind of simple (string-represented) types for later processing.
def tokenize(expression):
'''Generate tokens from a string following fixed rules.
'''
scanner = re.Scanner([
(r'[0-9]\.[0-9]+', lambda _, t: ('FLOAT', t)),
(r'[0-9]+', lambda _, t: ('INTEGER', t)),
(r'[a-z_]+', lambda _, t: ('IDENTIFIER', t)),
(r'\(', lambda _, t: ('P_OPEN', t)),
(r'\)', lambda _, t: ('P_CLOSE', t)),
(r'[+\-*/]', lambda _, t: ('OPERATOR', t)),
(r'\s+', None),
])
tokens, _ = scanner.scan(expression)
return tokens
This approach is by far not complete, but it is sufficient for demonstrating building binary parse trees. Note that the order of rules is important; it makes no difference here, as I do not catch single dots, but putting INTEGER before FLOAT could mess things up later.
Step 2: Parse the Hierarchy
The next function takes a list of tokens as generated in Step 1 and resolves all parts that are put into brackets as individual sub-lists. The result is a nested list where each previously bracketed part is shifted to a deeper level.
def parse(tokens, in_parens=False):
'''Parse a list of tokens that may contain brackets into a token hierarchy
where all brackets are removed and replaced by list nesting.
'''
cur = []
i = 0
while i < len(tokens):
t = tokens[i]
if t[0] == 'P_OPEN':
# If we hit an opening bracket, we memorize its position and search
# for the corresponding closing one by counting the stacked
# brackets.
pos_open = i
pos_close = None
par_stack = 0
for j, p in enumerate(tokens[i:]):
if p[0] == 'P_OPEN':
# Deeper nesting, increase.
par_stack += 1
elif p[0] == 'P_CLOSE':
# Level closed, decrease.
par_stack -= 1
if par_stack == 0:
# If we hit level 0, we found the corresponding closing
# bracket for the opening one.
pos_close = i + j
break
if pos_close is None:
# If we did not find a corresponding closing bracket, there
# must be some syntax error.
raise Exception('Syntax error; missing closing bracket.')
# For the bracketed subset we just found, we invoke a recursive
# parsing for its contents and append the result to our hierarchy.
elem = parse(tokens[i + 1:j], in_parens=True)
cur.append(elem)
i = j
elif t[0] == 'P_CLOSE':
if not in_parens:
# If we hit a closing bracket but are not searching for one, we
# found too many closing brackets, which is a syntax error.
raise Exception('Syntax error; too many closing brackets.')
return cur
else:
cur.append(t)
i += 1
return cur
This makes sure that we do not miss the explicit grouping given by parentheses in the expression. At the same time, as we count parenthesis levels, we can spot syntax errors that result from wrong bracket counts.
Step 3: Build a Tree
In order to proceed, we need to build an actual binary tree from our hierarchy. The hierarchy we got from Step 2 still has all un-bracketed chained operators on the same level, so we do not know yet about the order in which the operators need to be executed. This is what is solved now.
When creating a new Node from a hierarchy (i.e. a nested list of tokens), we search for a pivot element that we can use as the operator of the currently built Node. We choose the weakest binding operator, because we build the tree top-down, but it will be evaluated bottom-up. Hence, the operation that shall be performed last is the one we want to have in the upmost Node of our tree.
class Node(object):
def __init__(self, hierarchy, parent=None):
if len(hierarchy) == 1 and type(hierarchy[0]) is list:
hierarchy = hierarchy[0] # Bracketed descent
# Find position of operator that has the weakest binding priority and
# use it as pivot element to split the sequence at. The weakest binding
# is executed last, so it's the topmost node in the tree (which is
# evaluated bottom-up).
pivot = self._weakest_binding_position(hierarchy)
if pivot is not None:
self.left = Node(hierarchy[:pivot], parent=self)
self.op = hierarchy[pivot][1]
self.right = Node(hierarchy[pivot + 1:], parent=self)
else:
# There is no pivot element if there is no operator in our
# hierarchy. If so, we hit an atomic item and this node will be
# a leaf node.
self.value = hierarchy[0]
def _binding_order(self, operator):
'''Resolve operator to its binding order.'''
if operator in '+-':
return 1
elif operator in '*/':
return 2
raise Exception('Parsing error; operator binding cannot be assessed.')
def _weakest_binding_position(self, tokens):
'''Return position of operator with weakest binding (maintains LTR).'''
ops = sorted([
(i, self._binding_order(t[1]))
for i, t in enumerate(tokens)
if t[0] == 'OPERATOR'
], key=lambda e: e[1], reverse=True)
if len(ops) == 0:
if len(tokens) != 1:
raise Exception('Parsing error; found sequence w/o operator.')
return None
return ops[-1][0]
def isleaf(self):
if hasattr(self, 'value'):
return True
return False
def __str__(self):
if self.isleaf():
return str(self.value[1])
else:
return '({:s} {:s} {:s})'.format(self.left, self.op, self.right)
If you want to see how the tree is set up, just print(self) at the end of Node.__init__(). This will give you a bottom-up print of all nodes.
I added some parentheses in the Node.__str__() method to actually make a fully-bracketed expression from the input. You can verify with some samples like so:
if __name__ == '__main__':
expressions = [
'(3+15)*2+6-3',
'(a+15)*2+6/3'
]
for expr in expressions:
root = Node(parse(tokenize(expr)))
print(root)
... yields
>>> ((((3 + 15) * 2) + 6) - 3)
>>> (((a + 15) * 2) + (6 / 3))
So, if you want to print (or return) this in postfix notation now, you can just switch the operator and operands by changing this row in the Node.__str__() method:
<<<<<<<<
return '({:s} {:s} {:s})'.format(self.left, self.op, self.right)
======
return '({:s} {:s} {:s})'.format(self.left, self.right, self.op)
>>>>>>>>
If you want your postfix notation to be returned for further processing instead of just obtaining it as a string, just write another method like so (warning: pseudo-code):
def postfix(self):
if self.isleaf():
return self.value
else:
return (self.left.postfix(), self.right.postfix(), self.op)
and then invoke it from your root node:
pf = root.postfix()
Step 4: Evaluation
Finally, you can put a method into the Node class to evaluate the expression. This method checks whether or not we have a leaf node, and, if so, returns its value using the correct type. Otherwise, it evaluates its left and right child and applies the desired operator and then passes the result upwards the tree.
def eval(self, variables={}):
if self.isleaf():
ttype, value = self.value
if ttype == 'FLOAT':
return float(value)
elif ttype == 'INTEGER':
return int(value)
elif ttype == 'IDENTIFIER':
if value in variables.keys():
return variables[value]
else:
raise Exception('Unbound variable: {:s}'.format(value))
else:
raise Exception('Unknown type: {:s}'.format(ttype))
else:
left = self.left.eval(variables=variables)
right = self.right.eval(variables=variables)
if self.op == '+':
return left + right
elif self.op == '-':
return left - right
elif self.op == '*':
return left * right
elif self.op == '/':
return left / right
else:
raise Exception('Unknown operator: {:s}'.format(self.op))
Some special thing here is, that you can also use variables (like a in my example in Step 3), but you have to map them to actual (un-typed) values on evaluation:
if __name__ == '__main__':
expression = '(a+15)*2+6/3'
tokens = tokenize(expression)
hierarchy = parse(tokens)
root = Node(hierarchy)
print(root)
print(root.eval({'a': 7}))
... yields:
>>> (((a + 15) * 2) + (6 / 3))
>>> 46
Final Thoughts
As already stated, this is far from perfect. I even noticed, that it somehow fails to parse an expression, where a single operator connects two bracketed parts like (1-2)/(0+5) -- but I leave this to whoever wants to have a look at it ;)
Hope it helps somehow; and sorry for this huge response. I was just curious and had a little bit of spare time.

Recursion- removes duplicates from the list

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.

How to write a recursive function that returns a list made up of squares of the elements of lst?

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

Categories

Resources