diff --git a/challenge_10/python/shaowen/solution.py b/challenge_10/python/shaowen/solution.py index e7902ef6b..980ab96dd 100644 --- a/challenge_10/python/shaowen/solution.py +++ b/challenge_10/python/shaowen/solution.py @@ -6,16 +6,16 @@ def solution(strr): """check if all brackets closed properly""" closerof = {'{':'}', '[':']','(':')'} - Start = ('[','{','(') - Closer = (']','}',')') + START = ('[','{','(') + CLOSE = (']','}',')') stack = [] for i in strr: # push into stack, if new bracket found - if i in Start: + if i in START: stack.append(i) # pop out if proper closer found, else False - elif i in Closer: + elif i in CLOSE: if closerof[stack[-1]] == i: stack.pop() else: diff --git a/challenge_11/python/shaowen/READE.md b/challenge_11/python/shaowen/READE.md new file mode 100644 index 000000000..d8d5a14da --- /dev/null +++ b/challenge_11/python/shaowen/READE.md @@ -0,0 +1,41 @@ +###Challenge 11 + +Language Version: Python 2.7.12 + + +### Solution + +Algorithms ref: + +http://www.algolist.net/Data_structures/Binary_search_tree/Removal + +### How to run + +$ python bst.py + +Please type in a list of node integer, seperated by space. + +5 2 1 3 12 9 21 19 36 + +Original bst list: + +[5, 2, 1, 3, 12, 9, 21, 19, 36] + + +Please type in key(s) you want to delete: + +(you could type in one int, or a list of int like following, if the key is not in bst, you will also be notified.) + +5 7 2 19 + +key 7 not found. + +New bst list: + +[9, 3, 1, 12, 21, 36] + + + +###Testing + +$ python unit_test.py diff --git a/challenge_11/python/shaowen/bst.py b/challenge_11/python/shaowen/bst.py new file mode 100644 index 000000000..440c19dac --- /dev/null +++ b/challenge_11/python/shaowen/bst.py @@ -0,0 +1,189 @@ +# -*- coding: utf-8 -*- +# @author: Shaowen Liu + +class Node(): + + def __init__(self, key, left=None, right=None, parent=None): + self.key = key + self.left = left + self.right = right + self.parent = parent + + def __str__(self): + return str(self.key) + + def has_any_child(self): + return self.left or self.right + + def the_only_child(self): + """if the node has only one child, return the child + else, return False + """ + if self.left and (not self.right): + return self.left + elif self.right and (not self.left): + return self.right + else: + return False + + def is_left_child(self): + return bool(self.parent.left == self) + + def is_right_child(self): + return bool(self.parent.right == self) + +class BST(): + + def __init__(self, root = None, size = 0): + self.root = root + self.size = size + + def _insert(self, key, current_node): + + if key == current_node.key: + raise IndexError('Find duplicated key.') + elif key > current_node.key: + if current_node.right: + self._insert(key, current_node.right) + else: + current_node.right = Node(key, parent = current_node) + elif key < current_node.key: + if current_node.left: + self._insert(key, current_node.left) + else: + current_node.left = Node(key, parent = current_node) + + def insert(self, key): + """insert new key into bst""" + # if bst does not exist, make new node the root + if not self.root: + self.root = Node(key, parent = None) + # else insert the node into bst recercively + else: + self._insert(key, self.root) + self.size += 1 + + def _has_key(self, key, current_node): + + if key == current_node.key: + return current_node + # lookup right branch + elif key > current_node.key: + return self._has_key(key, current_node.right) + # lookup left branch + elif key < current_node.key: + return self._has_key(key, current_node.left) + + def has_key(self, key): + """lookup key in bst, + return node if key found, else False + """ + if not self.root: + return False + else: + return self._has_key(key, self.root) + + def smallest_key(self, current_node): + """start from current_node, + search the node with the minimum key in bst + """ + if not current_node: + raise IndexError('this is an empty (sub)tree') + + if current_node.left: + return self.smallest_key(current_node.left) + else: + return current_node + + def _delete(self, removed_node): + + # if removed_node has no child + if not removed_node.has_any_child(): + # removed node is a leaf + if removed_node.parent: + if removed_node.is_left_child(): + removed_node.parent.left = None + else: + removed_node.parent.right = None + self.size -= 1 + # removed node is root + else: + self.root = None + self.size = 0 + + # removed node has only one child + elif removed_node.the_only_child(): + if removed_node.parent: + if removed_node.is_left_child(): + removed_node.parent.left = removed_node.the_only_child() + removed_node.the_only_child().parent = removed_node.parent + else: + removed_node.parent.right = removed_node.the_only_child() + removed_node.the_only_child().parent = removed_node.parent + # removed node is root + else: + self.root = self.root.the_only_child() + + # removed node has two children + else: + min_node = self.smallest_key(removed_node.right) + removed_node.key = min_node.key + self._delete(min_node) + + def delete(self, key): + """delete key from bst""" + removed_node = self.has_key(key) + # if bst has the key, kick off delete process + if removed_node: + self._delete(removed_node) + else: + raise ValueError('key not found.') + + def _pre_order(self, current_node): + + arr = [] + arr.append(current_node.key) + if current_node.left: + arr += self._pre_order(current_node.left) + if current_node.right: + arr += self._pre_order(current_node.right) + return arr + + def pre_order_print(self): + """print the tree by pre_order traversal""" + if self.root: + return self._pre_order(self.root) + else: + return [] + +def build_bst(arr): + """build a bst from an array""" + bst = BST() + for i in arr: + bst.insert(i) + return bst + +if __name__ == '__main__': + #user input + node_arr = raw_input('Please type in a list of node integer, seperated by space.\n') + # insert nodes + bst = build_bst(map(int, node_arr.split())) + + # pre_order print + print 'Original bst list: \n %s\n' % str(bst.pre_order_print()) + erase_keys = raw_input('Please type in key(s) you want to delete:\n') + + # check whether input is valid + try: + keys = map(int, erase_keys.split()) + except ValueError: + raise ValueError('invalid input') + + # check if key exists. + for key in keys: + if bst.has_key(key): + bst.delete(key) + else: + print 'key %s not found.' % key + + print 'New bst list:\n%s\n' % str(bst.pre_order_print()) \ No newline at end of file diff --git a/challenge_11/python/shaowen/unit_test.py b/challenge_11/python/shaowen/unit_test.py new file mode 100644 index 000000000..dc5313f98 --- /dev/null +++ b/challenge_11/python/shaowen/unit_test.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +#@author: Shaowen Liu + + +import unittest +from bst import BST, build_bst + +class bst_test(unittest.TestCase): + + # build proper bst list + def test_bst_build_case1(self): + arr = [5, 2, 12, 9, 21, 3, -4, 19, 25] + bst = build_bst(arr) + self.assertEqual(bst.pre_order_print(), [5, 2, -4, 3, 12, 9, 21, 19, 25]) + + def test_bst_build_case2(self): + arr = [235, 100, 50, 700, 800, 900, 25, 75, 105, 236] + bst = build_bst(arr) + self.assertEqual(bst.pre_order_print(), [235,100,50,25,75,105,700,236,800,900]) + + + # test for delete method + def test_bst_delete_case1(self): + # delete the leaf node + arr = [5, 2, -4, 3, 12, 9, 21, 19, 25] + bst = build_bst(arr) + bst.delete(25) + self.assertEqual(bst.pre_order_print(), [5, 2, -4, 3, 12, 9, 21, 19]) + + def test_bst_delete_case2(self): + # delete the roof node + arr = [5, 2, -4, 3, 12, 9, 21, 19, 25] + bst = build_bst(arr) + bst.delete(5) + self.assertEqual(bst.pre_order_print(), [9, 2, -4, 3, 12, 21, 19, 25]) + + def test_bst_delete_case3(self): + # delete the node in the middle of the tree + bst_list = [5, 2, -4, 3, 12, 9, 21, 19, 25] + bst = build_bst(bst_list) + bst.delete(2) + self.assertEqual(bst.pre_order_print(), [5, 3, -4, 12, 9, 21, 19, 25]) + + def test_bst_delete_case4(self): + # delete the node in the middle of the tree + arr = [5, 2, -4, 3, 12, 9, 21, 19, 25] + bst = build_bst(arr) + bst.delete(12) + self.assertEqual(bst.pre_order_print(), [5, 2, -4, 3, 19, 9, 21, 25]) + + + +if __name__ == '__main__': + unittest.main() diff --git a/challenge_12/python/shaowen/READE.md b/challenge_12/python/shaowen/READE.md new file mode 100644 index 000000000..9d986b1b8 --- /dev/null +++ b/challenge_12/python/shaowen/READE.md @@ -0,0 +1,14 @@ +###Challenge 12 + +Language Version: Python 2.7.12 + + +### Solution + +Regex + +### How to run + +$ python compress.py + +(code will detect whether it's compressed or not, and output the opposite.) diff --git a/challenge_12/python/shaowen/compress.py b/challenge_12/python/shaowen/compress.py new file mode 100644 index 000000000..06b343db7 --- /dev/null +++ b/challenge_12/python/shaowen/compress.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +#@author: Shaowen Liu + +import re + +def replace_fun(match): + duplicated = match.group() + return '%s#%d' % (duplicated[0], len(duplicated)) + +def replace_fun2(match): + compressed = match.group() + return compressed[0] * int(compressed[2:]) + +def compress(astring): + """compress string""" + pattern = re.compile(r'(([a-zA-Z])\2{3,})') + + return pattern.sub(replace_fun, astring) + +def decompress(astring): + """decompress string""" + pattern = re.compile(r'(\w#\d+)') + + return pattern.sub(replace_fun2, astring) + +if __name__ == '__main__': + astring = raw_input('Input string:') + + if '#' in astring: + decompress_str = decompress(astring) + print 'Decopressed string:\n%s\n' % decompress_str + else: + compress_str = compress(astring) + print 'Compressed string: \n%s\n' % compress_str + + + \ No newline at end of file