Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Python]challenge_[11,12](Unreviewed) #395

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions challenge_10/python/shaowen/solution.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
41 changes: 41 additions & 0 deletions challenge_11/python/shaowen/READE.md
Original file line number Diff line number Diff line change
@@ -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
189 changes: 189 additions & 0 deletions challenge_11/python/shaowen/bst.py
Original file line number Diff line number Diff line change
@@ -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())
54 changes: 54 additions & 0 deletions challenge_11/python/shaowen/unit_test.py
Original file line number Diff line number Diff line change
@@ -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()
14 changes: 14 additions & 0 deletions challenge_12/python/shaowen/READE.md
Original file line number Diff line number Diff line change
@@ -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.)
37 changes: 37 additions & 0 deletions challenge_12/python/shaowen/compress.py
Original file line number Diff line number Diff line change
@@ -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