Paired Delimeter Matching - python

I would like to write a class that will return true if and only if the expression entered contains only correctly matching delimiters such as " (), <>, [], {} " What I have written thus far will do exactly that.
delim_openers = '{([<'
delim_closers = '})]>'
def check_delimiters(expr):
val = Stack()
for c in expr:
if c == (any(x) for x in delim_openers):
val.push(c)
elif c == (any(y) for y in delim_closers):
try:
val.pop()
except:
return False
return val.empty()
I am a little confused however if I were test this case against specific cases such as the one below, it'll return true when I assumed it would return False, my stack shouldn't be popping the delimiter in this case. Test case:
from unittest import TestCase
tc = TestCase()
tc.assertFalse(check_delimiters('[ ( ] )'))
tc.assertFalse(check_delimiters('((((((( ))))))'))
How might I edit the `check_delimiters' method to correctly return False in these scenarios? The stacks first-in-last-out capability tends to confuse me. Also here's the stack class code in case anything else is confusing.
class Stack:
class Node:
def __init__(self, val, next=None):
self.val = val
self.next = next
def __init__(self):
self.top = None
def push(self, val):
self.top = Stack.Node(val, self.top)
def pop(self):
assert self.top, 'Stack is empty'
val = self.top.val
self.top = self.top.next
return val
def peek(self):
return self.top.val if self.top else None
def empty(self):
return self.top == None
def __bool__(self):
return not self.empty()
def __repr__(self):
if not self.top:
return ''
return '--> ' + ', '.join(str(x) for x in self)
def __iter__(self):
n = self.top
while n:
yield n.val
n = n.next

No need for any, a simple contains-check will suffice. Then you have to check whether the closer matches the opener, otherwise you are just checking whether closers and openers are equal in numbers and that the closers never take the lead count-wise:
class Stack(list):
push = list.append
def peek(self):
return self[-1] if self else None
# ...
match = dict(zip('{([<', '})]>')) # dict makes the matching check faster
delim_openers = set(match.keys()) # set makes the 'in' check faster
delim_closers = set(match.values())
def check_delimiters(expr):
val = Stack()
for c in expr:
if c in delim_openers:
val.push(c)
elif c in delim_closers:
try:
assert match[val.pop()] == c
# fails if stack is empty or brackets don't match
except:
return False
return not val
> check_delimiters('[ ( ] )')
False
> check_delimiters('[ ( ) ]')
True

Related

Why is my helper method not activating recursively?

I have a Binary Search Tree and I am trying to trace recursively in order through the tree and append each key,value to a list. It is only appending the first key,value to the list and not going through the list in order. I pasted my code below, along with the test code I used at the bottom. Any help on how to get past this issue is super appreciated!
class TreeMap:
class Node:
def __init__(self, key, value):
self.key = key
self.value = value
self.left = None
self.right = None
def __init__(self):
self.root = None
self.numsearches = 0
self.numcomparisons = 0
def add(self, newkey, newvalue):
newkey = newkey.lower()
if self.root == None:
self.root = TreeMap.Node(newkey, newvalue)
else:
TreeMap.add_helper(self.root, newkey, newvalue)
def add_helper(thisnode, newkey, newvalue):
if newkey <= thisnode.key:
if thisnode.left == None:
thisnode.left = TreeMap.Node(newkey, newvalue)
else:
TreeMap.add_helper(thisnode.left, newkey, newvalue)
else:
if thisnode.right == None:
thisnode.right = TreeMap.Node(newkey, newvalue)
else:
TreeMap.add_helper(thisnode.right, newkey, newvalue)
def print(self):
TreeMap.print_helper(self.root, 0)
def print_helper(somenode, indentlevel):
if somenode == None:
print(" "*(indentlevel),"---")
return
if not TreeMap.isleaf(somenode):
TreeMap.print_helper(somenode.right, indentlevel + 5)
print(" "*indentlevel + str(somenode.key) + ": " +str(somenode.value))
if not TreeMap.isleaf(somenode):
TreeMap.print_helper(somenode.left, indentlevel + 5)
def isleaf(anode):
return anode.left == None and anode.right == None
def listify(self, whichorder="in"):
'''
Returns a list consisting of all the payloads of the tree. (This returns a plain old Python List.)
The order of the payloads is determined by whichorder, which defaults to inorder.
The other possibilities are "pre" and "post".
If the tree is empty, return the empty list.
'''
assert type(whichorder) is str,"Whichorder is a string, and can only be pre, in or post"
assert whichorder in ["pre","in","post"],"Whichorder is a string, and can only be pre, in or post"
return TreeMap.listify_helper(self.root, whichorder)
def listify_helper(somenode, whichorder):
order_list = []
if somenode == None:
return order_list
elif somenode != None and whichorder == 'in':
TreeMap.listify_helper(somenode.left, 'in')
order_list.append(somenode.key+ '='+somenode.value)
TreeMap.listify_helper(somenode.right, 'in')
return order_list
TEST CODE:
import treemap
translator = treemap.TreeMap()
translator.add("cat", "Katze")
translator.add("bird", "Vogel")
translator.add("dog", "Hund")
translator.add("snake", "IDK")
translator.add("bear", "IDK")
translator.add("octopus", "Tintenfisch")
translator.add("horse", "Pferd")
translator.add("zebra", "IDK")
translator.print()
print("---------------------------------------------------")
print (translator.listify())
The problem is here:
def listify_helper(somenode, whichorder):
order_list = []
This function initialises its own local order_list every time it is invoked. Pass order_list as a parameter instead so that the same list is appended to by each recursive invocation.
Alternatively, append each element of the result of the recursive calls of listify_helper to order_list, although this approach could result in unneeded copying.

How do you find the first string from a list of strings using recursion?

I need to create a function that returns the first string of the string list recursively (found from Python comparison tests, e.g. 'agf' < 'bcd').
class Node:
def __init__(self, value, rest):
self.value = value
self.rest = rest
def __eq__(self, other):
return ((type(other) == Node)
and self.value == other.value
and self.rest == other.rest
)
def __repr__(self):
return ("Node({!r}, {!r})".format(self.value, self.rest))
# a StrList is one of None or Node(string, StrList)
def first_string(strlist):
if strlist is None:
return None
res = first_string(strlist.rest)
if strlist.value != res:
return res
Whenever I test the function, the main error I have is that I only return None whenever I pass a node.
Function example:
strlist = Node("xyz", Node("Abc", Node("49ers", None)))
self.assertEqual(first_string(strlist),"49ers")
Output:
None
I appreciate it if someone can help me out.
def first_string(strlist):
if strlist is None:
return None
min_rest = first_string(strlist.rest)
if min_rest is None or strlist.value < min_rest:
return strlist.value
return min_rest

Recursive Alternative/Merge Linked List Function with Multiple Linked List as Arguments?

I'm having trouble working with recursive linked list function with multiple linked list arguments.
So far I have came up with below, with a single linked list and works fine.
def recursive_ll(ll):
if ll == None:
return None
elif ll.next == None:
return LN(ll.value)
else:
return_ll = LN(ll.value, recursive_ll(ll.next))
if return_ll.value == return_ll.next.value:
return_ll = return_ll.next
return return_ll
Result will be:
ll = list_to_ll(['x','g','f','n'])
print(str_ll(recursive_ll(ll)))
x->g->f->n->None
But I am really confused with how I can create recursive linked list function with multiple linked lists as arguments.
For example, def recursive_ll(ll): will be def recursive_ll(ll, ll2):
And returned result would be
ll = recursive_ll(['a','x','b','e'])
ll2 = recursive_ll(['d','f','m'])
a->d->x->f->b->m->e->None
Again, desired result below, combined from two linked list:
a->d->x->f->b->m->e->None
Any help/suggestions will be much appreciated!
You should use classes instead of simple functions as helpers. And accept any iterable as the source for a linked list. If you implement iterators on the linked list class, that would allow trivial conversion between any iterable and a linked list.
The linked list class could be:
class LL:
class iter:
def __init__(self, ll):
self.cur = ll.front
def __iter__(self):
return self
def __next__(self):
if self.cur is None:
raise StopIteration()
val = self.cur.value
self.cur = self.cur.next
return val
def __init__(self, l):
self.front = last = None
for v in l:
ln = LN(v)
if last is None:
self.front = ln
else:
last.next = ln
last = ln
def __str__(self):
answer = ''
for val in self.iter_elt():
answer += str(val) + '->'
return answer + 'None'
def __repr__(self):
return str(self.__class__) + ':' + str(self)
def __iter__(self):
return LL.iter(self)
This immediately allows:
>>> print(LL('abcd'))
a->b->c->d->None
>>> list(LL('abcd'))
['a', 'b', 'c', 'd']
Once this is done, you can declare a Recursive Linked List as a subclass of a Linked List which allows to extract the elements in a merge order if it contains Linked Lists.
You should first add a new method iter_elt in LL class that just calls iter and use that in __str__ to ease the subclassing:
class LL:
...
def __str__(self):
answer = ''
for val in self.iter_elt():
answer += str(val) + '->'
return answer + 'None'
...
def iter_elt(self):
return self.__iter__()
Because now, it is enough to override iter_elt in RLL, and build an iterator that will scan its sublists repeatedly calling iter_elt on them if possible else iter, until all are exhausted. Code could be:
class RLL(LL):
class iter:
def __init__(self, rll):
self.iters = LL(i.iter_elt() if hasattr(i, 'iter_elt') else iter(i)
for i in rll)
self.cur = self.iters.front
self.prev = None
def __iter__(self):
return self
def __next__(self):
try:
elt = next(self.cur.value)
self.prev = self.cur
self.cur = self.cur.next
if self.cur is None:
self.cur = self.iters.front
self.prev = None
except StopIteration:
self.cur = self.cur.next
if self.cur is None:
if self.prev is None:
raise
self.cur = self.iters.front
self.prev = None
else:
if self.prev is None:
self.iters.front = self.cur
else:
self.prev.next = self.cur
elt = self.__next__()
return elt
def iter_elt(self):
return RLL.iter(self)
I totally agree with #Serge Ballesta that you should create a LinkedList class to do this, here's how it could be done the procedural way you're doing things.
Also note that it's not done recursively—but rather "pythonically".
from itertools import chain, zip_longest
class LN:
def __init__(self, value, next=None):
self.value = value
self.next = next
def list_to_ll(l):
if l == []:
return None
front = rear = LN(l[0])
for v in l[1:]:
rear.next = LN(v)
rear = rear.next
return front
def iterate(ll):
while ll is not None:
yield ll.value
ll = ll.next
def str_ll(ll):
return '->'.join(str(v) for v in iterate(ll)) + '->None'
def alternate(ll_1, ll_2):
_NULL = object()
chained = chain.from_iterable(zip_longest(iterate(ll_1), iterate(ll_2),
fillvalue=_NULL))
return list_to_ll(list(v for v in chained if v is not _NULL))
if __name__ == '__main__':
ll_1 = list_to_ll(['a','x','b','e'])
ll_2 = list_to_ll(['d','f','m'])
print(str_ll(alternate(ll_1, ll_2))) # -> a->d->x->f->b->m->e->None

How do I use __str__() and __repr__() for a singly linked list in Python 3.6?

everyone. I've got a bit of a problem I need to sort out, and I was hoping for some assistance on what to do. So, I have this Python 3.6 assignment I've been working on, regarding Singly Linked Lists. Most of my test cases for appending/prepending, removing from front and back, and deleting nodes altogether are going well so far. However, I have some issues with a few of my test cases. The issues revolve around my use of the __str__(self) and __repr__(self) functions.
Down below is the code I'm providing. (EDIT: I left only the test codes that has the faults that need fixing. All the other test cases are fine):
class LinkedList(object):
class Node(object):
# pylint: disable=too-few-public-methods
''' no need for get or set, we only access the values inside the
LinkedList class. and really: never have setters. '''
def __init__(self, value, next = None):
self.value = value
self.next = next
def __repr__(self):
return repr(self.value)
def __str__(self):
return str(self.value) + "; "
def __init__(self, initial=None):
self.front = self.back = self.current = None
def empty(self):
return self.front == self.back == None
def __iter__(self):
self.current = self.front
return self
def __str__(self):
string = 'List[ '
curr_node = self.front
while curr_node != None:
string += str(curr_node)
curr_node = curr_node.next()
string += ']'
return string
def __repr__(self):
nodes = []
curr = self.front
while curr:
nodes.append(repr(curr))
curr = curr.next
return '[' +', '.join(nodes) + ']'
def __next__(self):
if self.current:
tmp = self.current.value
self.current = self.current.next
return tmp
else:
raise StopIteration()
def push_front(self, value):
x = self.Node(value, self.front)
if self.empty():
self.front = self.back = x
else:
self.front = x
#you need to(at least) implement the following three methods
def pop_front(self):
if self.empty():
raise RuntimeError("Empty List")
x = self.front.value
self.front = self.front.next
if not self.front:
self.back = None
return x
def push_back(self, value):
if self.empty():
self.front = self.back = self.Node(value, None)
else:
x = self.Node(value, None)
self.back.next = x
self.back = x
def pop_back(self):
if self.empty():
raise RuntimeError("Empty List")
y = self.back.value
if not self.front.next:
self.front = self.back = None
else:
x = self.front
while x.next is not self.back:
x = x.next
x.next = None
self.back = x
return y
class TestInitialization(unittest.TestCase):
def test(self):
linked_list = LinkedList(("one", 2, 3.141592))
self.assertEqual(linked_list.pop_back(), "one")
self.assertEqual(linked_list.pop_back(), 2)
self.assertEqual(linked_list.pop_back(), 3.141592)
class TestStr(unittest.TestCase):
def test(self):
linked_list = LinkedList((1, 2, 3))
self.assertEqual(linked_list.__str__(), '1, 2, 3')
class TestRepr(unittest.TestCase):
def test(self):
linked_list = LinkedList((1, 2, 3))
self.assertEqual(linked_list.__repr__(), 'LinkedList((1, 2, 3))')
if '__main__' == __name__:
unittest.main()
Now, with the code out of the way, I'm going to provide the problems I'm getting in the console:
1) Error at TestInitialization. RuntimeError("Empty List")
2) Failure at TestRepr. AssertionError: '[]' != 'LinkedList((1, 2, 3))'
- []
+ LinkedList((1, 2, 3))
3) Failure at TestStr. AssertionError: 'List[ ]' != '1, 2, 3'
- List[ ]
+ 1, 2, 3
I hate to be a bother, but I'd like to ask for any advice or hints to help me correct my two failures and prevent the one error. So, is there any way I can use to try and do so? I would greatly appreciate it.
To make TestInitialization work, your init function hat to provide a linkage of
3.141592 -> 2 -> "one"
if init(...)ed with ("one", 2, 3.141592) - you can see that by inspecting the testcase, it pops from back and you need to match the values provided.
You can solve it by pushing each one onto the front in init:
def __init__(self, initial=None):
self.front = self.back = self.current = None
for i in initial:
self.push_front(i)
# I find this counterintuitive, blame your teacher.
To make TestStr work, you init it with (1,2,3) and have to provide an output of '(1,2,3)' - due to the way __init__ now works you need to collect all nodes into a list, and return it reverse-joined (or go from back to front through list):
def __str__(self):
elem = []
curr_node = self.front
while curr_node != None:
elem.append(str(curr_node.value)) # collect node values, not the "7; " str
curr_node = curr_node.next()
# join reversed list
return ', '.join(elem[::-1]) # need to reverse the list due to how __init__ works
To make TestRepr work, you need the __str__ output and prefix/postfix it with 'LinkedList((' and '))'
def __repr__(self):
return 'LinkedList(('+ str(self) + '))'
I can't test myself, as NameError: name 'unittest' is not defined.

Use a function built outside the class on an object in Python?

I have a class
class List:
def __init__(self,head,tail):
self.head = head
self.tail = tail
def cons(self,item):
return List(item,self)
def isEmpty(self):
return self.head == None
def display(self):
s = "["
first = True
list = self
while not list.isEmpty():
if not first:
s=s+","
first = False
s=s+str(list.head)
list = list.tail
s=s+"]"
return s`
which creates a List object. I have a function (not sure if it works yet);
def sorted(list):
sort = False
i = 0
while i < range(len(list))+1:
if list[i] < list[i+1]:
sort = True
return sort
else:
return sort
and I want to run this function on the List object without adding another method to the class. I know if this was in the class it would just be List.sorted() but how can I run this function on the object without it being the objects method?
sorted(List) doesn't seem to work either. Help please.
Please, please, PLEASE: don't use sorted as a function name. There is a standard (built-in) function sorted() already, that returns a sorted version of an iterable.
Given that your code just checks to see if the List is in order, perhaps you could call it in_order or ordered or is_ascending instead?
That said, let's try to get your code working:
class Node:
def __init__(self, data=None, next=None):
self.data = data
self.next = next
def __str__(self):
return str(self.data)
class List:
def __init__(self, head:Node=None, tail:Node=None):
self.head = tail if head is None else head
self.tail = head if tail is None else tail
def cons(self, node:Node):
node.next = self.head
return List(node, self.tail)
def isEmpty(self):
return self.head == None
def display(self):
return str(self)
def __str__(self):
result = "["
first = True
n = self.head
while n is not None:
if not first:
result += ", "
result += str(n)
if n == self.tail:
break
n = n.next
first = False
result += "]"
return result
def ascendingp(self) -> bool:
n = self.head
last = None
while last != self.tail:
if last is not None and not last.data < n.data:
return False
last = n
n = n.next
return True
tests = (
(1,2,3),
(1,3,2),
(),
)
for t in tests:
last = None
first = None
for i in reversed(t):
n = Node(data=i)
first = n if first is None else first
n.next = last
last = n
l = List(head=last, tail=first)
print(str(l), "Ascending?", l.ascendingp())

Categories