├── README.md ├── ch1 ├── C1_13.py ├── C1_14.py ├── C1_15.py ├── C1_18.py ├── C1_19.py ├── C1_20.py ├── C1_21.py ├── C1_22.py ├── C1_23.py ├── C1_24.py ├── C1_25.py ├── C1_26.py ├── C1_27.py ├── C1_28.py ├── P1_29.py ├── P1_30.py ├── P1_35.py ├── P1_36.py ├── R1_1.py ├── R1_10.py ├── R1_11.py ├── R1_12.py ├── R1_2.py ├── R1_3.py ├── R1_4.py ├── R1_5.py ├── R1_7.py ├── R1_9.py └── __pycache__ │ ├── C1_15.cpython-33.pyc │ └── C1_15.cpython-34.pyc ├── ch2 ├── .range.py.swp ├── C2_26.py ├── C2_27.py ├── C2_31.py ├── P2_33.py ├── P2_34.py ├── R2_10.py ├── R2_11.py ├── R2_12.py ├── R2_14.py ├── R2_18.py ├── R2_4.py ├── R2_5.py ├── R2_6.py ├── R2_7.py ├── R2_9.py ├── __pycache__ │ ├── progressions.cpython-33.pyc │ ├── progressions.cpython-34.pyc │ ├── range.cpython-34.pyc │ └── sequence_iterator.cpython-34.pyc ├── credit_card.py ├── predatory_credit_card.py ├── progressions.py ├── progressions.pyc ├── range.py ├── range.pyc ├── sequence_abc.py ├── sequence_iterator.py ├── sequence_iterator.pyc └── vector.py ├── ch4 ├── C4_10.py ├── C4_12.py ├── C4_15.py ├── C4_16.py ├── C4_17.py ├── C4_9.py └── P4_23.py ├── ch5 ├── C5_14.py ├── C5_16.py ├── R5_10.py ├── R5_11.py ├── R5_12.py ├── R5_2.py ├── R5_3.py ├── R5_4.py ├── R5_6.py ├── R5_8.py ├── __pycache__ │ ├── caesar.cpython-34.pyc │ └── dynamic_array.cpython-34.pyc ├── caesar.py ├── dynamic_array.py └── dynamic_array.pyc └── ch6 ├── C6_15.py ├── C6_16.py ├── C6_17.py ├── R6_11.py ├── R6_13.py ├── R6_14.py ├── R6_3.py ├── R6_4.py ├── R6_5.py ├── __pycache__ ├── array_queue.cpython-34.pyc └── array_stack.cpython-34.pyc ├── array_queue.py ├── array_queue.pyc ├── array_stack.py └── array_stack.pyc /README.md: -------------------------------------------------------------------------------- 1 | Data-Structures-and-Algorithms-in-Python 2 | ====================================== 3 | 4 | My solutions to the exercises in book Data Structures and Algorithms in Python 5 | -------------------------------------------------------------------------------- /ch1/C1_13.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Author: TianJun 3 | # Mail: find_my_way@foxmail.com 4 | # Created Time: 2013/12/16 11:00:31 5 | def myRevers(data): 6 | return [data[-(i+1)] for i in range(len(data))] 7 | 8 | if __name__ == '__main__': 9 | print(myRevers([1, 2, 3, 4, 5])) 10 | -------------------------------------------------------------------------------- /ch1/C1_14.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: C1_14.py 8 | # Description: 9 | # calculate determines if there is a distinct pair of numbers in the 10 | # sequence whose product is odd. 11 | # 12 | # Last Modified: 13 | # 2014-06-10 11:42:15 14 | 15 | 16 | def is_product_odd_in(s): 17 | """just count the num of odd in a sequence""" 18 | result = False 19 | for d in s: 20 | if d % 2 == 1: 21 | result = True 22 | break 23 | return result 24 | 25 | if __name__ == '__main__': 26 | s = input("input integers, seperate by blank(at least 2 numbers):") 27 | s = [int(a) for a in s.split()] 28 | print("is there a pair of numbers whose product is odd?\n", 29 | is_product_odd_in(s)) 30 | -------------------------------------------------------------------------------- /ch1/C1_15.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Author: TianJun 3 | # Mail: find_my_way@foxmail.com 4 | # Created Time: 2013/12/16 11:12:02 5 | def is_distinct(dataList): 6 | lenList = len(dataList) 7 | setList = len(set(dataList)) 8 | if lenList == setList: 9 | return True 10 | else: 11 | return False 12 | if __name__ == '__main__': 13 | print(is_distinct([1, 2, 3, 3])) 14 | print(is_distinct([1, 2, 3])) 15 | -------------------------------------------------------------------------------- /ch1/C1_18.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Author: TianJun 3 | # Mail: find_my_way@foxmail.com 4 | # Created Time: 2013/12/16 11:21:02 5 | 6 | if __name__ == '__main__': 7 | print([a * (a + 1) for a in range(10)]) 8 | -------------------------------------------------------------------------------- /ch1/C1_19.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Author: TianJun 3 | # Mail: find_my_way@foxmail.com 4 | # Created Time: 2013/12/16 11:34:52 5 | 6 | if __name__ == '__main__': 7 | print([chr(a) for a in range(ord('a'), ord('z') + 1)]) 8 | -------------------------------------------------------------------------------- /ch1/C1_20.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: C1_20.py 8 | # Description: 9 | # shuffle a list 10 | # 11 | # Last Modified: 12 | # 2014-06-10 12:31:43 13 | 14 | 15 | def my_shuffle(data): 16 | """each time, generate two random indexes, 17 | then exchange them, repeat n times 18 | n is the length of data 19 | """ 20 | from random import randint 21 | for i in range(len(data)): 22 | m = randint(0, len(data) - 1) 23 | n = randint(0, len(data) - 1) 24 | data[m], data[n] = data[n], data[m] 25 | 26 | if __name__ == '__main__': 27 | a = [i for i in range(10)] 28 | print("initial list:", a) 29 | for i in range(10): 30 | my_shuffle(a) 31 | print("shuffled:", a) 32 | -------------------------------------------------------------------------------- /ch1/C1_21.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Author: TianJun 3 | # Mail: find_my_way@foxmail.com 4 | # Created Time: 2013/12/16 11:43:06 5 | 6 | if __name__ == '__main__': 7 | s = [] 8 | print("input anything you want, end with ctrl-d") 9 | try: 10 | while True: 11 | a = input() 12 | s.append(a) 13 | except EOFError: 14 | s.reverse() 15 | print("the reversed input are:") 16 | for x in s: 17 | print(x) 18 | -------------------------------------------------------------------------------- /ch1/C1_22.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: C1_22.py 8 | # Description: 9 | # dot prodction 10 | # 11 | # Last Modified: 12 | # 2014-06-10 13:05:36 13 | 14 | 15 | def dot_product(a, b): 16 | assert len(a) == len(b) 17 | return [a[i] * b[i] for i in range(len(a))] 18 | 19 | if __name__ == '__main__': 20 | a = [i for i in range(5)] 21 | b = [i for i in range(5)] 22 | print("a = ", a) 23 | print("b = ", b) 24 | print("a dot b = ", dot_product(a, b)) 25 | -------------------------------------------------------------------------------- /ch1/C1_23.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Author: TianJun 3 | # Mail: find_my_way@foxmail.com 4 | # Created Time: 2013/12/16 19:33:25 5 | def rmPunctuation(string): 6 | returnString = str() 7 | for a in string: 8 | if a.isalpha() or a == ' ': 9 | returnString += a 10 | return returnString 11 | if __name__ == '__main__': 12 | print(rmPunctuation("Lets try, Mike.")) 13 | -------------------------------------------------------------------------------- /ch1/C1_24.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: C1_24.py 8 | # Description: 9 | # calculate number of vowels in a string 10 | # 11 | # Last Modified: 12 | # 2014-06-10 13:12:34 13 | 14 | 15 | def n_vowels(s): 16 | vowels = ['a', 'A', 'e', 'E', 'i', 'I', 'o', 'O', 'u', 'U'] 17 | n = 0 18 | for x in s: 19 | if x in vowels: 20 | n += 1 21 | return n 22 | -------------------------------------------------------------------------------- /ch1/C1_25.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: C1_25.py 8 | # Description: 9 | # remove punctuation in a string 10 | # 11 | # Last Modified: 12 | # 2014-06-10 13:19:26 13 | 14 | 15 | def remove_punctuation(s): 16 | return ''.join(x for x in s if x.isalnum() or x.isspace()) 17 | 18 | if __name__ == '__main__': 19 | s = input("input a string\n") 20 | print("removed string is:") 21 | print(remove_punctuation(s)) 22 | -------------------------------------------------------------------------------- /ch1/C1_26.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: C1_26.py 8 | # Description: 9 | # varify some expressions 10 | # 11 | # Last Modified: 12 | # 2014-06-10 13:28:47 13 | 14 | 15 | if __name__ == '__main__': 16 | s = input("input three integers:(seperate by blank)").split() 17 | a, b, c = (int(i) for i in s) 18 | print("Is {} + {} = {} ?".format(a, b, c), a + b == c) 19 | print("Is {} = {} - {} ?".format(a, b, c), a == b - c) 20 | print("Is {} = {} * {} ?".format(a, b, c), a == b * c) 21 | -------------------------------------------------------------------------------- /ch1/C1_27.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: C1_27.py 8 | # Description: 9 | # 10 | # 11 | # Last Modified: 12 | # 2014-06-10 13:53:29 13 | 14 | 15 | def factors(n): 16 | k = 1 17 | temp = [] 18 | while k * k < n: 19 | if n % k == 0: 20 | yield k 21 | temp.append(n // k) 22 | k += 1 23 | if k * k == n: 24 | yield k 25 | for i in reversed(temp): 26 | yield i 27 | -------------------------------------------------------------------------------- /ch1/C1_28.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Author: TianJun 3 | # Mail: find_my_way@foxmail.com 4 | # Created Time: 2013/12/16 19:46:32 5 | def pNorm(v, p): 6 | sum = 0 7 | for x in v: 8 | sum += x ** p 9 | norm = sum ** (1/p) 10 | return norm 11 | if __name__ == '__main__': 12 | test = pNorm([4, 3], 2) 13 | print(test) 14 | -------------------------------------------------------------------------------- /ch1/P1_29.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Author: TianJun 3 | # Mail: find_my_way@foxmail.com 4 | # Created Time: 2013/12/17 9:01:47 5 | if __name__ == '__main__': 6 | from itertools import permutations 7 | s = 'catdog' 8 | for i in range(len(s)): 9 | for x in permutations(s, i + 1): 10 | print(''.join(x)) 11 | -------------------------------------------------------------------------------- /ch1/P1_30.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: P1_30.py 8 | # Description: 9 | # 10 | # 11 | # Last Modified: 12 | # 2014-06-10 14:02:24 13 | from math import floor, log2 14 | 15 | 16 | if __name__ == '__main__': 17 | n = int(input("input an integer:")) 18 | assert n > 2 19 | print("Need {} times to divide".format(int(floor(log2(n))))) 20 | -------------------------------------------------------------------------------- /ch1/P1_35.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Author: TianJun 3 | # Mail: find_my_way@foxmail.com 4 | # Created Time: 2013/12/17 9:26:15 5 | 6 | 7 | def birthday_paradox(): 8 | from random import randint 9 | from C1_15 import is_distinct 10 | for pepNum in range(5, 101, 5): 11 | #each case test 1000 times 12 | nTimes = 0 13 | for i in range(1000): 14 | birthdays = [] 15 | for j in range(pepNum): 16 | birthdays.append(randint(1, 365)) 17 | if not is_distinct(birthdays): 18 | nTimes += 1 19 | print("When n=%d, the probability is %.3f" % (pepNum, nTimes / 1000)) 20 | 21 | 22 | if __name__ == '__main__': 23 | birthday_paradox() 24 | -------------------------------------------------------------------------------- /ch1/P1_36.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: P1_36.py 8 | # Description: 9 | # count 10 | # 11 | # Last Modified: 12 | # 2014-06-10 14:16:16 13 | 14 | 15 | def count(s): 16 | word_count = {} 17 | for word in s.split(): 18 | word_count[word] = 1 + word_count.get(word, 0) 19 | print(word_count) 20 | 21 | if __name__ == '__main__': 22 | s = input("input a sentance:\n") 23 | count(s) 24 | -------------------------------------------------------------------------------- /ch1/R1_1.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | def is_multiple(n, m): 5 | return n % m == 0 6 | 7 | if __name__ == "__main__": 8 | a, b = input("input 2 int, seperate with blank : ").split() 9 | print("is multiple ? ", is_multiple(int(a), int(b))) 10 | -------------------------------------------------------------------------------- /ch1/R1_10.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Author: TianJun 3 | # Mail: find_my_way@foxmail.com 4 | # Created Time: 2013/12/16 10:42:12 5 | 6 | if __name__ == '__main__': 7 | for x in range(8, -10, -2): 8 | print(x) 9 | -------------------------------------------------------------------------------- /ch1/R1_11.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Author: TianJun 3 | # Mail: find_my_way@foxmail.com 4 | # Created Time: 2013/12/16 10:43:55 5 | 6 | if __name__ == '__main__': 7 | print([2**a for a in range(9)]) 8 | -------------------------------------------------------------------------------- /ch1/R1_12.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Author: TianJun 3 | # Mail: find_my_way@foxmail.com 4 | # Created Time: 2013/12/16 10:50:00 5 | def myChoice(data): 6 | import random 7 | chosenIndex = random.randrange(len(data)) 8 | return data[chosenIndex] 9 | 10 | if __name__ == '__main__': 11 | print(myChoice([1, 2, 3, 4])) 12 | -------------------------------------------------------------------------------- /ch1/R1_2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R1_2.py 8 | # Description: 9 | # judge if an int is even 10 | # 11 | # Last Modified: 12 | # 2014-06-10 11:02:15 13 | 14 | 15 | def is_even(k): 16 | return not k & 1 17 | 18 | if __name__ == '__main__': 19 | k = input("input an int:") 20 | print("is even ?", is_even(int(k))) 21 | -------------------------------------------------------------------------------- /ch1/R1_3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R1_3.py 8 | # Description: 9 | # calculate min, max 10 | # 11 | # Last Modified: 12 | # 2014-06-10 11:08:44 13 | 14 | 15 | def minmax(data): 16 | d_min = d_max = data[0] 17 | for a in data[1:]: 18 | if a < d_min: 19 | d_min = a 20 | if a > d_max: 21 | d_max = a 22 | return d_min, d_max 23 | 24 | if __name__ == '__main__': 25 | in_str = input("input numbers, seprate with blank:") 26 | data = [float(d) for d in in_str.split()] 27 | data_minmax = minmax(data) 28 | print("min :{} max: {}".format(data_minmax[0], data_minmax[1])) 29 | -------------------------------------------------------------------------------- /ch1/R1_4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R1_4.py 8 | # Description: 9 | # sum square numbers less then given 10 | # 11 | # Last Modified: 12 | # 2014-06-10 11:18:08 13 | 14 | 15 | def sum_square(k): 16 | assert k > 0 17 | return sum(x ** 2 for x in range(k)) 18 | 19 | if __name__ == '__main__': 20 | k = input("input num:") 21 | print("sum of square numbers less then {} is {}". 22 | format(k, sum_square(int(k)))) 23 | -------------------------------------------------------------------------------- /ch1/R1_5.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Author: TianJun 3 | # Created Time: 2013/12/16 10:25:57 4 | 5 | def sum_list(n): 6 | return sum([a * a for a in range(n)]) 7 | 8 | if __name__ == "__main__": 9 | print(sum_list(3)) 10 | -------------------------------------------------------------------------------- /ch1/R1_7.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R1_7.py 8 | # Description: 9 | # the sum of the squares of all the odd positive integers smaller 10 | # than n. 11 | # 12 | # Last Modified: 13 | # 2014-06-10 11:24:51 14 | 15 | 16 | def sum_square(k): 17 | assert k > 0 18 | return sum(x ** 2 for x in range(k) if x & 1) 19 | 20 | if __name__ == '__main__': 21 | k = input("input num:") 22 | print("sum of squares of odd numbers less then {} is {}". 23 | format(k, sum_square(int(k)))) 24 | -------------------------------------------------------------------------------- /ch1/R1_9.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Author: TianJun 3 | # Mail: find_my_way@foxmail.com 4 | # Created Time: 2013/12/16 10:37:57 5 | 6 | if __name__ == '__main__': 7 | for x in range(50, 90, 10): 8 | print(x) 9 | -------------------------------------------------------------------------------- /ch1/__pycache__/C1_15.cpython-33.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch1/__pycache__/C1_15.cpython-33.pyc -------------------------------------------------------------------------------- /ch1/__pycache__/C1_15.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch1/__pycache__/C1_15.cpython-34.pyc -------------------------------------------------------------------------------- /ch2/.range.py.swp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch2/.range.py.swp -------------------------------------------------------------------------------- /ch2/C2_26.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Jun Tian 3 | # 4 | # tianjun.cpp@gmail.com 5 | # www.tianjun.ml 6 | # 7 | # reverse SequenceIterator 8 | # 9 | # Create time: 2014-06-10 16:07:23 10 | 11 | from sequence_iterator import SequenceIterator 12 | 13 | 14 | class ReversedSequenceIterator(SequenceIterator): 15 | """An reversed iterator for any of Python's sequence types.""" 16 | 17 | def __init__(self, sequence): 18 | """Create an iterator for the given sequence.""" 19 | super().__init__(sequence) 20 | self._k = 0 21 | 22 | def __next__(self): 23 | """Return the next element, or else raise StopIteration error.""" 24 | self._k -= 1 # advance to next index 25 | if -self._k <= len(self._seq): 26 | return(self._seq[self._k]) # return the data element 27 | else: 28 | raise StopIteration() # there are no more elements 29 | 30 | def __str__(self): 31 | return " ".join(str(next(self)) for i in self._seq) 32 | 33 | if __name__ == '__main__': 34 | s = ReversedSequenceIterator([1, 2, 3]) 35 | print(s) 36 | -------------------------------------------------------------------------------- /ch2/C2_27.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: C2_27.py 8 | # Description: 9 | # change the contain method of class Range 10 | # 11 | # Last Modified: 12 | # 2014-06-10 16:09:10 13 | 14 | from range import Range 15 | import timeit 16 | 17 | 18 | class MyRange(Range): 19 | 20 | def __init__(self, start, stop=None, step=1): 21 | super().__init__(start, stop, step) 22 | 23 | def __contains__(self, val): 24 | r = (val - self._start) % self._step 25 | if r == 0: 26 | return True 27 | else: 28 | return False 29 | 30 | if __name__ == '__main__': 31 | t1 = timeit.Timer("99999 in Range(1, 100000, 2)", 32 | "from range import Range") 33 | t2 = timeit.Timer("99999 in MyRange(1, 100000, 2)", 34 | "from __main__ import MyRange") 35 | print("original Range Class, time consumes :", t1.timeit(100)) 36 | print("MyRange Class, time consumes :", t2.timeit(100)) 37 | -------------------------------------------------------------------------------- /ch2/C2_31.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Jun Tian 3 | # 4 | # tianjun.cpp@gmail.com 5 | # www.tianjun.ml 6 | # 7 | # DESCRIPTION: 8 | # extend class progressions 9 | # 10 | # Create time: 2013-12-22 15:11:46 11 | 12 | from progressions import Progression 13 | 14 | 15 | class MinusProgression(Progression): 16 | """Minus the previous two number""" 17 | def __init__(self, first=2, second=200): 18 | """input two numbers""" 19 | super().__init__(first) 20 | self._second = second 21 | 22 | def _advance(self, ): 23 | self._current, self._second = self._second, abs(self._second - self._current) 24 | 25 | if __name__ == '__main__': 26 | MinusProgression().print_progression(10) 27 | -------------------------------------------------------------------------------- /ch2/P2_33.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Jun Tian 3 | # 4 | # tianjun.cpp@gmail.com 5 | # www.tianjun.ml 6 | # 7 | # DESCRIPTION: 8 | # 输入一个多项式的系数,阶数由高到低 9 | # 输出其一阶导 10 | # 11 | # Create time: 2013-12-22 15:35:15 12 | 13 | 14 | def first_polynomial(polynomial): 15 | result = [] 16 | try: 17 | lenth = len(polynomial) 18 | for k in reversed(range(lenth)): 19 | if not isinstance(polynomial[lenth-k-1], (int, float)): 20 | raise ValueError 21 | result.append(k * polynomial[lenth-k-1]) 22 | return result 23 | except: 24 | print("Check input ! ValueError!") 25 | return False 26 | 27 | if __name__ == '__main__': 28 | print(first_polynomial([3, 2, 1])) 29 | print(first_polynomial("fdfe")) 30 | -------------------------------------------------------------------------------- /ch2/P2_34.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Jun Tian 3 | # 4 | # tianjun.cpp@gmail.com 5 | # www.tianjun.ml 6 | # 7 | # DESCRIPTION: 8 | # plot the frequences of each alphabet 9 | # 10 | # Create time: 2013-12-22 15:56:19 11 | 12 | 13 | freqDic = {} 14 | with open('P2_34.py') as f: 15 | #Read source file and calculate the frequences 16 | for line in f: 17 | for char in line: 18 | if char.isalpha(): 19 | freqDic[char] = freqDic.get(char, 0) + 1 20 | #plot the frequences 21 | for alpha in range(ord('a'), ord('z')+1): 22 | alpha = chr(alpha) 23 | print("%s " % (alpha) + "-"*freqDic.get(alpha, 0)) 24 | for alpha in range(ord('A'), ord('Z')+1): 25 | alpha = chr(alpha) 26 | print("%s " % (alpha) + "-"*freqDic.get(alpha, 0)) 27 | -------------------------------------------------------------------------------- /ch2/R2_10.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | class Vector: 4 | """Represent a vector in a multidimensional space.""" 5 | 6 | def __init__(self, d): 7 | if isinstance(d, int): 8 | self._coords = [0] * d 9 | else: 10 | try: # we test if param is iterable 11 | self._coords = [val for val in d] 12 | except TypeError: 13 | raise TypeError('invalid parameter type') 14 | 15 | def __len__(self): 16 | """Return the dimension of the vector.""" 17 | return len(self._coords) 18 | 19 | def __getitem__(self, j): 20 | """Return jth coordinate of vector.""" 21 | return self._coords[j] 22 | 23 | def __setitem__(self, j, val): 24 | """Set jth coordinate of vector to given value.""" 25 | self._coords[j] = val 26 | 27 | def __add__(self, other): 28 | """Return sum of two vectors.""" 29 | if len(self) != len(other): # relies on __len__ method 30 | raise ValueError('dimensions must agree') 31 | result = Vector(len(self)) # start with vector of zeros 32 | for j in range(len(self)): 33 | result[j] = self[j] + other[j] 34 | return result 35 | 36 | def __sub__(self, b): 37 | """Return minus of two vectors""" 38 | if len(self) != len(b): 39 | raise ValueError('dimensions must agree') 40 | result = Vector(len(self)) 41 | for j in range(len(self)): 42 | result[j] = self[j] - b[j] 43 | return result 44 | 45 | def __neg__(self, ): 46 | """turn a vector into negtive""" 47 | result = Vector(len(self)) 48 | for j in range(len(self)): 49 | result[j] = -self[j] 50 | return result 51 | 52 | def __eq__(self, other): 53 | """Return True if vector has same coordinates as other.""" 54 | return self._coords == other._coords 55 | 56 | def __ne__(self, other): 57 | """Return True if vector differs from other.""" 58 | return not self == other # rely on existing __eq__ definition 59 | 60 | def __str__(self): 61 | """Produce string representation of vector.""" 62 | return '<' + str(self._coords)[1:-1] + '>' # adapt list representation 63 | 64 | def __neg__(self): 65 | """Return copy of vector with all coordinates negated.""" 66 | result = Vector(len(self)) # start with vector of zeros 67 | for j in range(len(self)): 68 | result[j] = -self[j] 69 | return result 70 | 71 | def __lt__(self, other): 72 | """Compare vectors based on lexicographical order.""" 73 | if len(self) != len(other): 74 | raise ValueError('dimensions must agree') 75 | return self._coords < other._coords 76 | 77 | def __le__(self, other): 78 | """Compare vectors based on lexicographical order.""" 79 | if len(self) != len(other): 80 | raise ValueError('dimensions must agree') 81 | return self._coords <= other._coords 82 | 83 | if __name__ == '__main__': 84 | # the following demonstrates usage of a few methods 85 | v = Vector(5) # construct five-dimensional <0, 0, 0, 0, 0> 86 | v[1] = 23 # <0, 23, 0, 0, 0> (based on use of __setitem__) 87 | v[-1] = 45 # <0, 23, 0, 0, 45> (also via __setitem__) 88 | print(v[4]) # print 45 (via __getitem__) 89 | u = v + v # <0, 46, 0, 0, 90> (via __add__) 90 | print(u) # print <0, 46, 0, 0, 90> 91 | u = -u 92 | print(u) 93 | u = v - v 94 | print(u) 95 | total = 0 96 | for entry in v: # implicit iteration via __len__ and __getitem__ 97 | total += entry 98 | -------------------------------------------------------------------------------- /ch2/R2_11.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | class Vector: 4 | """Represent a vector in a multidimensional space.""" 5 | 6 | def __init__(self, d): 7 | if isinstance(d, int): 8 | self._coords = [0] * d 9 | else: 10 | try: # we test if param is iterable 11 | self._coords = [val for val in d] 12 | except TypeError: 13 | raise TypeError('invalid parameter type') 14 | 15 | def __len__(self): 16 | """Return the dimension of the vector.""" 17 | return len(self._coords) 18 | 19 | def __getitem__(self, j): 20 | """Return jth coordinate of vector.""" 21 | return self._coords[j] 22 | 23 | def __setitem__(self, j, val): 24 | """Set jth coordinate of vector to given value.""" 25 | self._coords[j] = val 26 | 27 | def __add__(self, other): 28 | """Return sum of two vectors.""" 29 | if len(self) != len(other): # relies on __len__ method 30 | raise ValueError('dimensions must agree') 31 | result = Vector(len(self)) # start with vector of zeros 32 | for j in range(len(self)): 33 | result[j] = self[j] + other[j] 34 | return result 35 | 36 | def __radd__(self, other): 37 | """Return sum of two vectors.""" 38 | if len(self) != len(other): # relies on __len__ method 39 | raise ValueError('dimensions must agree') 40 | result = Vector(len(self)) # start with vector of zeros 41 | for j in range(len(self)): 42 | result[j] = self[j] + other[j] 43 | return result 44 | 45 | def __sub__(self, b): 46 | """Return minus of two vectors""" 47 | if len(self) != len(b): 48 | raise ValueError('dimensions must agree') 49 | result = Vector(len(self)) 50 | for j in range(len(self)): 51 | result[j] = self[j] - b[j] 52 | return result 53 | 54 | def __neg__(self, ): 55 | """turn a vector into negtive""" 56 | result = Vector(len(self)) 57 | for j in range(len(self)): 58 | result[j] = -self[j] 59 | return result 60 | 61 | def __eq__(self, other): 62 | """Return True if vector has same coordinates as other.""" 63 | return self._coords == other._coords 64 | 65 | def __ne__(self, other): 66 | """Return True if vector differs from other.""" 67 | return not self == other # rely on existing __eq__ definition 68 | 69 | def __str__(self): 70 | """Produce string representation of vector.""" 71 | return '<' + str(self._coords)[1:-1] + '>' # adapt list representation 72 | 73 | def __neg__(self): 74 | """Return copy of vector with all coordinates negated.""" 75 | result = Vector(len(self)) # start with vector of zeros 76 | for j in range(len(self)): 77 | result[j] = -self[j] 78 | return result 79 | 80 | def __lt__(self, other): 81 | """Compare vectors based on lexicographical order.""" 82 | if len(self) != len(other): 83 | raise ValueError('dimensions must agree') 84 | return self._coords < other._coords 85 | 86 | def __le__(self, other): 87 | """Compare vectors based on lexicographical order.""" 88 | if len(self) != len(other): 89 | raise ValueError('dimensions must agree') 90 | return self._coords <= other._coords 91 | 92 | if __name__ == '__main__': 93 | # the following demonstrates usage of a few methods 94 | v = Vector(5) # construct five-dimensional <0, 0, 0, 0, 0> 95 | v[1] = 23 # <0, 23, 0, 0, 0> (based on use of __setitem__) 96 | v[-1] = 45 # <0, 23, 0, 0, 45> (also via __setitem__) 97 | print(v[4]) # print 45 (via __getitem__) 98 | u = v + v # <0, 46, 0, 0, 90> (via __add__) 99 | print(u) # print <0, 46, 0, 0, 90> 100 | u = -u 101 | print(u) 102 | u = [1, 1, 1, 1, 1] + u 103 | print(u) 104 | u = u + [1, 1, 1, 1, 1] 105 | print(u) 106 | u = v - v 107 | print(u) 108 | total = 0 109 | for entry in v: # implicit iteration via __len__ and __getitem__ 110 | total += entry 111 | -------------------------------------------------------------------------------- /ch2/R2_12.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | class Vector: 4 | """Represent a vector in a multidimensional space.""" 5 | 6 | def __init__(self, d): 7 | if isinstance(d, int): 8 | self._coords = [0] * d 9 | else: 10 | try: # we test if param is iterable 11 | self._coords = [val for val in d] 12 | except TypeError: 13 | raise TypeError('invalid parameter type') 14 | 15 | def __len__(self): 16 | """Return the dimension of the vector.""" 17 | return len(self._coords) 18 | 19 | def __getitem__(self, j): 20 | """Return jth coordinate of vector.""" 21 | return self._coords[j] 22 | 23 | def __setitem__(self, j, val): 24 | """Set jth coordinate of vector to given value.""" 25 | self._coords[j] = val 26 | 27 | def __add__(self, other): 28 | """Return sum of two vectors.""" 29 | if len(self) != len(other): # relies on __len__ method 30 | raise ValueError('dimensions must agree') 31 | result = Vector(len(self)) # start with vector of zeros 32 | for j in range(len(self)): 33 | result[j] = self[j] + other[j] 34 | return result 35 | 36 | def __radd__(self, other): 37 | """Return sum of two vectors.""" 38 | if len(self) != len(other): # relies on __len__ method 39 | raise ValueError('dimensions must agree') 40 | result = Vector(len(self)) # start with vector of zeros 41 | for j in range(len(self)): 42 | result[j] = self[j] + other[j] 43 | return result 44 | 45 | def __sub__(self, b): 46 | """Return minus of two vectors""" 47 | if len(self) != len(b): 48 | raise ValueError('dimensions must agree') 49 | result = Vector(len(self)) 50 | for j in range(len(self)): 51 | result[j] = self[j] - b[j] 52 | return result 53 | 54 | def __rmul__(self, b): 55 | if not isinstance(b, (int, float)): 56 | raise TypeError('int or float') 57 | result = Vector(len(self)) 58 | for j in range(len(self)): 59 | result[j] = self[j] * b 60 | return result 61 | 62 | def __mul__(self, b): 63 | if not isinstance(b, (int, float)): 64 | raise TypeError('int or float') 65 | result = Vector(len(self)) 66 | for j in range(len(self)): 67 | result[j] = self[j] * b 68 | return result 69 | 70 | def __neg__(self, ): 71 | """turn a vector into negtive""" 72 | result = Vector(len(self)) 73 | for j in range(len(self)): 74 | result[j] = -self[j] 75 | return result 76 | 77 | def __eq__(self, other): 78 | """Return True if vector has same coordinates as other.""" 79 | return self._coords == other._coords 80 | 81 | def __ne__(self, other): 82 | """Return True if vector differs from other.""" 83 | return not self == other # rely on existing __eq__ definition 84 | 85 | def __str__(self): 86 | """Produce string representation of vector.""" 87 | return '<' + str(self._coords)[1:-1] + '>' # adapt list representation 88 | 89 | def __neg__(self): 90 | """Return copy of vector with all coordinates negated.""" 91 | result = Vector(len(self)) # start with vector of zeros 92 | for j in range(len(self)): 93 | result[j] = -self[j] 94 | return result 95 | 96 | def __lt__(self, other): 97 | """Compare vectors based on lexicographical order.""" 98 | if len(self) != len(other): 99 | raise ValueError('dimensions must agree') 100 | return self._coords < other._coords 101 | 102 | def __le__(self, other): 103 | """Compare vectors based on lexicographical order.""" 104 | if len(self) != len(other): 105 | raise ValueError('dimensions must agree') 106 | return self._coords <= other._coords 107 | 108 | if __name__ == '__main__': 109 | # the following demonstrates usage of a few methods 110 | v = Vector(5) # construct five-dimensional <0, 0, 0, 0, 0> 111 | v[1] = 23 # <0, 23, 0, 0, 0> (based on use of __setitem__) 112 | v[-1] = 45 # <0, 23, 0, 0, 45> (also via __setitem__) 113 | print(v[4]) # print 45 (via __getitem__) 114 | u = v + v # <0, 46, 0, 0, 90> (via __add__) 115 | print(u) # print <0, 46, 0, 0, 90> 116 | u = -u 117 | print(u) 118 | u = [1, 1, 1, 1, 1] + u 119 | print(u) 120 | u = u + [1, 1, 1, 1, 1] 121 | print(u) 122 | u = u * 2 123 | print(u) 124 | u = 0.5 * u 125 | print(u) 126 | u = v - v 127 | print(u) 128 | total = 0 129 | for entry in v: # implicit iteration via __len__ and __getitem__ 130 | total += entry 131 | -------------------------------------------------------------------------------- /ch2/R2_14.py: -------------------------------------------------------------------------------- 1 | import collections 2 | 3 | class Vector: 4 | """Represent a vector in a multidimensional space.""" 5 | 6 | def __init__(self, d): 7 | if isinstance(d, int): 8 | self._coords = [0] * d 9 | else: 10 | try: # we test if param is iterable 11 | self._coords = [val for val in d] 12 | except TypeError: 13 | raise TypeError('invalid parameter type') 14 | 15 | def __len__(self): 16 | """Return the dimension of the vector.""" 17 | return len(self._coords) 18 | 19 | def __getitem__(self, j): 20 | """Return jth coordinate of vector.""" 21 | return self._coords[j] 22 | 23 | def __setitem__(self, j, val): 24 | """Set jth coordinate of vector to given value.""" 25 | self._coords[j] = val 26 | 27 | def __add__(self, other): 28 | """Return sum of two vectors.""" 29 | if len(self) != len(other): # relies on __len__ method 30 | raise ValueError('dimensions must agree') 31 | result = Vector(len(self)) # start with vector of zeros 32 | for j in range(len(self)): 33 | result[j] = self[j] + other[j] 34 | return result 35 | 36 | def __radd__(self, other): 37 | """Return sum of two vectors.""" 38 | if len(self) != len(other): # relies on __len__ method 39 | raise ValueError('dimensions must agree') 40 | result = Vector(len(self)) # start with vector of zeros 41 | for j in range(len(self)): 42 | result[j] = self[j] + other[j] 43 | return result 44 | 45 | def __sub__(self, b): 46 | """Return minus of two vectors""" 47 | if len(self) != len(b): 48 | raise ValueError('dimensions must agree') 49 | result = Vector(len(self)) 50 | for j in range(len(self)): 51 | result[j] = self[j] - b[j] 52 | return result 53 | 54 | def __rmul__(self, b): 55 | if isinstance(b, (int, float)): 56 | result = Vector(len(self)) 57 | for j in range(len(self)): 58 | result[j] = self[j] * b 59 | return result 60 | elif isinstance(b,Vector): 61 | if len(self) != len(b): 62 | raise ValueError('dimensions must agree') 63 | result = Vector(len(self)) 64 | for j in range(len(self)): 65 | result[j] = self[j] * b[j] 66 | return result 67 | 68 | def __mul__(self, b): 69 | if isinstance(b, (int, float)): 70 | result = Vector(len(self)) 71 | for j in range(len(self)): 72 | result[j] = self[j] * b 73 | return result 74 | elif isinstance(b,Vector): 75 | if len(self) != len(b): 76 | raise ValueError('dimensions must agree') 77 | result = Vector(len(self)) 78 | for j in range(len(self)): 79 | result[j] = self[j] * b[j] 80 | return result 81 | 82 | def __neg__(self, ): 83 | """turn a vector into negtive""" 84 | result = Vector(len(self)) 85 | for j in range(len(self)): 86 | result[j] = -self[j] 87 | return result 88 | 89 | def __eq__(self, other): 90 | """Return True if vector has same coordinates as other.""" 91 | return self._coords == other._coords 92 | 93 | def __ne__(self, other): 94 | """Return True if vector differs from other.""" 95 | return not self == other # rely on existing __eq__ definition 96 | 97 | def __str__(self): 98 | """Produce string representation of vector.""" 99 | return '<' + str(self._coords)[1:-1] + '>' # adapt list representation 100 | 101 | def __neg__(self): 102 | """Return copy of vector with all coordinates negated.""" 103 | result = Vector(len(self)) # start with vector of zeros 104 | for j in range(len(self)): 105 | result[j] = -self[j] 106 | return result 107 | 108 | def __lt__(self, other): 109 | """Compare vectors based on lexicographical order.""" 110 | if len(self) != len(other): 111 | raise ValueError('dimensions must agree') 112 | return self._coords < other._coords 113 | 114 | def __le__(self, other): 115 | """Compare vectors based on lexicographical order.""" 116 | if len(self) != len(other): 117 | raise ValueError('dimensions must agree') 118 | return self._coords <= other._coords 119 | 120 | if __name__ == '__main__': 121 | # the following demonstrates usage of a few methods 122 | v = Vector(5) # construct five-dimensional <0, 0, 0, 0, 0> 123 | v[1] = 23 # <0, 23, 0, 0, 0> (based on use of __setitem__) 124 | v[-1] = 45 # <0, 23, 0, 0, 45> (also via __setitem__) 125 | print(v[4]) # print 45 (via __getitem__) 126 | u = v + v # <0, 46, 0, 0, 90> (via __add__) 127 | print(u) # print <0, 46, 0, 0, 90> 128 | u = -u 129 | print(u) 130 | u = [1, 1, 1, 1, 1] + u 131 | print(u) 132 | u = u + [1, 1, 1, 1, 1] 133 | print(u) 134 | u = u * 2 135 | print(u) 136 | u = 0.5 * u 137 | print(u) 138 | u = u * u 139 | print(u) 140 | total = 0 141 | for entry in v: # implicit iteration via __len__ and __getitem__ 142 | total += entry 143 | -------------------------------------------------------------------------------- /ch2/R2_18.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from progressions import FibonacciProgression 4 | f = FibonacciProgression(2, 2) 5 | f.print_progression(8) 6 | -------------------------------------------------------------------------------- /ch2/R2_4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | 4 | class Flower(): 5 | """a class descripe flower""" 6 | def __init__(self, name, petals, price): 7 | self._name = name 8 | self._petals = petals 9 | self._price = price 10 | 11 | def set_name(self, name): 12 | self._name = name 13 | 14 | def set_petals(self, petals): 15 | self._petals = petals 16 | 17 | def set_price(self, price): 18 | self._price = price 19 | 20 | def name(self, ): 21 | return self._name 22 | 23 | def petals(self, ): 24 | return self._petals 25 | 26 | def price(self, ): 27 | return self._price 28 | 29 | def descripe(self, ): 30 | print(""" 31 | name: {0} 32 | petals: {1} 33 | price: {2} 34 | """.format(self._name, self._petals, self._price)) 35 | 36 | if __name__ == '__main__': 37 | print("initial a Flower with name=rose petals=9 price=10") 38 | a = Flower('rose', 9, 10) 39 | a.descripe() 40 | print("set name = gardenia") 41 | a.set_name('gardenia') 42 | print(a.name()) 43 | print("set_price = 5") 44 | a.set_price(5) 45 | print(a.price()) 46 | print("set petals = 1") 47 | a.set_petals(1) 48 | print(a.petals()) 49 | a.descripe() 50 | -------------------------------------------------------------------------------- /ch2/R2_5.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Michael H. Goldwasser 3 | # 4 | # Developed for use with the book: 5 | # 6 | # Data Structures and Algorithms in Python 7 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | # John Wiley & Sons, 2013 9 | # 10 | # This program is free software: you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program. If not, see . 22 | 23 | class CreditCard: 24 | """A consumer credit card.""" 25 | 26 | def __init__(self, customer, bank, acnt, limit): 27 | """Create a new credit card instance. 28 | 29 | The initial balance is zero. 30 | 31 | customer the name of the customer (e.g., 'John Bowman') 32 | bank the name of the bank (e.g., 'California Savings') 33 | acnt the acount identifier (e.g., '5391 0375 9387 5309') 34 | limit credit limit (measured in dollars) 35 | """ 36 | self._customer = customer 37 | self._bank = bank 38 | self._account = acnt 39 | self._limit = limit 40 | self._balance = 0 41 | 42 | def get_customer(self): 43 | """Return name of the customer.""" 44 | return self._customer 45 | 46 | def get_bank(self): 47 | """Return the bank's name.""" 48 | return self._bank 49 | 50 | def get_account(self): 51 | """Return the card identifying number (typically stored as a string).""" 52 | return self._account 53 | 54 | def get_limit(self): 55 | """Return current credit limit.""" 56 | return self._limit 57 | 58 | def get_balance(self): 59 | """Return current balance.""" 60 | return self._balance 61 | 62 | def charge(self, price): 63 | """Charge given price to the card, assuming sufficient credit limit. 64 | 65 | Return True if charge was processed; False if charge was denied. 66 | """ 67 | try: 68 | if price + self._balance > self._limit: # if charge would exceed limit, 69 | return False # cannot accept charge 70 | else: 71 | self._balance += price 72 | return True 73 | except TypeError: 74 | return False 75 | 76 | def make_payment(self, amount): 77 | """Process customer payment that reduces balance.""" 78 | try: 79 | self._balance -= amount 80 | except TypeError: 81 | print("check again ! TypeError") 82 | 83 | if __name__ == '__main__': 84 | a = CreditCard('John Bowman', 'California Savings', '5391 0375 9387 5309', 2500) 85 | print(a.charge(10)) 86 | print(a.charge('df')) 87 | a.make_payment(5) 88 | a.make_payment("dfs") 89 | -------------------------------------------------------------------------------- /ch2/R2_6.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Michael H. Goldwasser 3 | # 4 | # Developed for use with the book: 5 | # 6 | # Data Structures and Algorithms in Python 7 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | # John Wiley & Sons, 2013 9 | # 10 | # This program is free software: you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program. If not, see . 22 | 23 | class CreditCard: 24 | """A consumer credit card.""" 25 | 26 | def __init__(self, customer, bank, acnt, limit): 27 | """Create a new credit card instance. 28 | 29 | The initial balance is zero. 30 | 31 | customer the name of the customer (e.g., 'John Bowman') 32 | bank the name of the bank (e.g., 'California Savings') 33 | acnt the acount identifier (e.g., '5391 0375 9387 5309') 34 | limit credit limit (measured in dollars) 35 | """ 36 | self._customer = customer 37 | self._bank = bank 38 | self._account = acnt 39 | self._limit = limit 40 | self._balance = 0 41 | 42 | def get_customer(self): 43 | """Return name of the customer.""" 44 | return self._customer 45 | 46 | def get_bank(self): 47 | """Return the bank's name.""" 48 | return self._bank 49 | 50 | def get_account(self): 51 | """Return the card identifying number (typically stored as a string).""" 52 | return self._account 53 | 54 | def get_limit(self): 55 | """Return current credit limit.""" 56 | return self._limit 57 | 58 | def get_balance(self): 59 | """Return current balance.""" 60 | return self._balance 61 | 62 | def charge(self, price): 63 | """Charge given price to the card, assuming sufficient credit limit. 64 | 65 | Return True if charge was processed; False if charge was denied. 66 | """ 67 | try: 68 | if price + self._balance > self._limit: # if charge would exceed limit, 69 | return False # cannot accept charge 70 | else: 71 | self._balance += price 72 | return True 73 | except TypeError: 74 | return False 75 | 76 | def make_payment(self, amount): 77 | """Process customer payment that reduces balance.""" 78 | try: 79 | self._balance -= amount 80 | if amount < 0: 81 | raise ValueError("check again ! ValueError ! amount must >= 0") 82 | except TypeError: 83 | print("check again ! TypeError") 84 | except ValueError as ve: 85 | print(ve) 86 | 87 | if __name__ == '__main__': 88 | a = CreditCard('John Bowman', 'California Savings', '5391 0375 9387 5309', 2500) 89 | print(a.charge(10)) 90 | print(a.charge('df')) 91 | a.make_payment(5) 92 | a.make_payment(-5) 93 | a.make_payment("dfs") 94 | -------------------------------------------------------------------------------- /ch2/R2_7.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Michael H. Goldwasser 3 | # 4 | # Developed for use with the book: 5 | # 6 | # Data Structures and Algorithms in Python 7 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | # John Wiley & Sons, 2013 9 | # 10 | # This program is free software: you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program. If not, see . 22 | 23 | class CreditCard: 24 | """A consumer credit card.""" 25 | 26 | def __init__(self, customer, bank, acnt, limit, balance=0): 27 | """Create a new credit card instance. 28 | 29 | The initial balance is zero. 30 | 31 | customer the name of the customer (e.g., 'John Bowman') 32 | bank the name of the bank (e.g., 'California Savings') 33 | acnt the acount identifier (e.g., '5391 0375 9387 5309') 34 | limit credit limit (measured in dollars) 35 | """ 36 | self._customer = customer 37 | self._bank = bank 38 | self._account = acnt 39 | self._limit = limit 40 | self._balance = balance 41 | 42 | def get_customer(self): 43 | """Return name of the customer.""" 44 | return self._customer 45 | 46 | def get_bank(self): 47 | """Return the bank's name.""" 48 | return self._bank 49 | 50 | def get_account(self): 51 | """Return the card identifying number (typically stored as a string).""" 52 | return self._account 53 | 54 | def get_limit(self): 55 | """Return current credit limit.""" 56 | return self._limit 57 | 58 | def get_balance(self): 59 | """Return current balance.""" 60 | return self._balance 61 | 62 | def charge(self, price): 63 | """Charge given price to the card, assuming sufficient credit limit. 64 | 65 | Return True if charge was processed; False if charge was denied. 66 | """ 67 | try: 68 | if price + self._balance > self._limit: # if charge would exceed limit, 69 | return False # cannot accept charge 70 | else: 71 | self._balance += price 72 | return True 73 | except TypeError: 74 | return False 75 | 76 | def make_payment(self, amount): 77 | """Process customer payment that reduces balance.""" 78 | try: 79 | self._balance -= amount 80 | if amount < 0: 81 | raise ValueError("check again ! ValueError ! amount must >= 0") 82 | except TypeError: 83 | print("check again ! TypeError") 84 | except ValueError as ve: 85 | print(ve) 86 | 87 | if __name__ == '__main__': 88 | a = CreditCard('John Bowman', 'California Savings', '5391 0375 9387 5309', 2500) 89 | print(a.charge(10)) 90 | print(a.charge('df')) 91 | a.make_payment(5) 92 | a.make_payment(-5) 93 | a.make_payment("dfs") 94 | -------------------------------------------------------------------------------- /ch2/R2_9.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013, Michael H. Goldwasser 2 | # 3 | # Developed for use with the book: 4 | # 5 | # Data Structures and Algorithms in Python 6 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 7 | # John Wiley & Sons, 2013 8 | # 9 | # This program is free software: you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | import collections 23 | 24 | class Vector: 25 | """Represent a vector in a multidimensional space.""" 26 | 27 | def __init__(self, d): 28 | if isinstance(d, int): 29 | self._coords = [0] * d 30 | else: 31 | try: # we test if param is iterable 32 | self._coords = [val for val in d] 33 | except TypeError: 34 | raise TypeError('invalid parameter type') 35 | 36 | def __len__(self): 37 | """Return the dimension of the vector.""" 38 | return len(self._coords) 39 | 40 | def __getitem__(self, j): 41 | """Return jth coordinate of vector.""" 42 | return self._coords[j] 43 | 44 | def __setitem__(self, j, val): 45 | """Set jth coordinate of vector to given value.""" 46 | self._coords[j] = val 47 | 48 | def __add__(self, other): 49 | """Return sum of two vectors.""" 50 | if len(self) != len(other): # relies on __len__ method 51 | raise ValueError('dimensions must agree') 52 | result = Vector(len(self)) # start with vector of zeros 53 | for j in range(len(self)): 54 | result[j] = self[j] + other[j] 55 | return result 56 | 57 | def __sub__(self, b): 58 | """Return minus of two vectors""" 59 | if len(self) != len(b): 60 | raise ValueError('dimensions must agree') 61 | result = Vector(len(self)) 62 | for j in range(len(self)): 63 | result[j] = self[j] - b[j] 64 | return result 65 | 66 | def __eq__(self, other): 67 | """Return True if vector has same coordinates as other.""" 68 | return self._coords == other._coords 69 | 70 | def __ne__(self, other): 71 | """Return True if vector differs from other.""" 72 | return not self == other # rely on existing __eq__ definition 73 | 74 | def __str__(self): 75 | """Produce string representation of vector.""" 76 | return '<' + str(self._coords)[1:-1] + '>' # adapt list representation 77 | 78 | def __neg__(self): 79 | """Return copy of vector with all coordinates negated.""" 80 | result = Vector(len(self)) # start with vector of zeros 81 | for j in range(len(self)): 82 | result[j] = -self[j] 83 | return result 84 | 85 | def __lt__(self, other): 86 | """Compare vectors based on lexicographical order.""" 87 | if len(self) != len(other): 88 | raise ValueError('dimensions must agree') 89 | return self._coords < other._coords 90 | 91 | def __le__(self, other): 92 | """Compare vectors based on lexicographical order.""" 93 | if len(self) != len(other): 94 | raise ValueError('dimensions must agree') 95 | return self._coords <= other._coords 96 | 97 | if __name__ == '__main__': 98 | # the following demonstrates usage of a few methods 99 | v = Vector(5) # construct five-dimensional <0, 0, 0, 0, 0> 100 | v[1] = 23 # <0, 23, 0, 0, 0> (based on use of __setitem__) 101 | v[-1] = 45 # <0, 23, 0, 0, 45> (also via __setitem__) 102 | print(v[4]) # print 45 (via __getitem__) 103 | u = v + v # <0, 46, 0, 0, 90> (via __add__) 104 | print(u) # print <0, 46, 0, 0, 90> 105 | u = v - v 106 | print(u) 107 | total = 0 108 | for entry in v: # implicit iteration via __len__ and __getitem__ 109 | total += entry 110 | x = Vector(3) 111 | x[0] = -100 112 | y = -x 113 | print(y) 114 | -------------------------------------------------------------------------------- /ch2/__pycache__/progressions.cpython-33.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch2/__pycache__/progressions.cpython-33.pyc -------------------------------------------------------------------------------- /ch2/__pycache__/progressions.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch2/__pycache__/progressions.cpython-34.pyc -------------------------------------------------------------------------------- /ch2/__pycache__/range.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch2/__pycache__/range.cpython-34.pyc -------------------------------------------------------------------------------- /ch2/__pycache__/sequence_iterator.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch2/__pycache__/sequence_iterator.cpython-34.pyc -------------------------------------------------------------------------------- /ch2/credit_card.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Michael H. Goldwasser 3 | # 4 | # Developed for use with the book: 5 | # 6 | # Data Structures and Algorithms in Python 7 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 8 | # John Wiley & Sons, 2013 9 | # 10 | # This program is free software: you can redistribute it and/or modify 11 | # it under the terms of the GNU General Public License as published by 12 | # the Free Software Foundation, either version 3 of the License, or 13 | # (at your option) any later version. 14 | # 15 | # This program is distributed in the hope that it will be useful, 16 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | # GNU General Public License for more details. 19 | # 20 | # You should have received a copy of the GNU General Public License 21 | # along with this program. If not, see . 22 | 23 | class CreditCard: 24 | """A consumer credit card.""" 25 | 26 | def __init__(self, customer, bank, acnt, limit): 27 | """Create a new credit card instance. 28 | 29 | The initial balance is zero. 30 | 31 | customer the name of the customer (e.g., 'John Bowman') 32 | bank the name of the bank (e.g., 'California Savings') 33 | acnt the acount identifier (e.g., '5391 0375 9387 5309') 34 | limit credit limit (measured in dollars) 35 | """ 36 | self._customer = customer 37 | self._bank = bank 38 | self._account = acnt 39 | self._limit = limit 40 | self._balance = 0 41 | 42 | def get_customer(self): 43 | """Return name of the customer.""" 44 | return self._customer 45 | 46 | def get_bank(self): 47 | """Return the bank's name.""" 48 | return self._bank 49 | 50 | def get_account(self): 51 | """Return the card identifying number (typically stored as a string).""" 52 | return self._account 53 | 54 | def get_limit(self): 55 | """Return current credit limit.""" 56 | return self._limit 57 | 58 | def get_balance(self): 59 | """Return current balance.""" 60 | return self._balance 61 | 62 | def charge(self, price): 63 | """Charge given price to the card, assuming sufficient credit limit. 64 | 65 | Return True if charge was processed; False if charge was denied. 66 | """ 67 | if price + self._balance > self._limit: # if charge would exceed limit, 68 | return False # cannot accept charge 69 | else: 70 | self._balance += price 71 | return True 72 | 73 | def make_payment(self, amount): 74 | """Process customer payment that reduces balance.""" 75 | self._balance -= amount 76 | 77 | if __name__ == '__main__': 78 | wallet = [] 79 | wallet.append(CreditCard('John Bowman', 'California Savings', 80 | '5391 0375 9387 5309', 2500)) 81 | wallet.append(CreditCard('John Bowman', 'California Federal', 82 | '3485 0399 3395 1954', 3500)) 83 | wallet.append(CreditCard('John Bowman', 'California Finance', 84 | '5391 0375 9387 5309', 5000)) 85 | 86 | for val in range(1, 17): 87 | wallet[0].charge(val) 88 | wallet[1].charge(2*val) 89 | wallet[2].charge(3*val) 90 | 91 | for c in range(3): 92 | print('Customer =', wallet[c].get_customer()) 93 | print('Bank =', wallet[c].get_bank()) 94 | print('Account =', wallet[c].get_account()) 95 | print('Limit =', wallet[c].get_limit()) 96 | print('Balance =', wallet[c].get_balance()) 97 | while wallet[c].get_balance() > 100: 98 | wallet[c].make_payment(100) 99 | print('New balance =', wallet[c].get_balance()) 100 | print() 101 | -------------------------------------------------------------------------------- /ch2/predatory_credit_card.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013, Michael H. Goldwasser 2 | # 3 | # Developed for use with the book: 4 | # 5 | # Data Structures and Algorithms in Python 6 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 7 | # John Wiley & Sons, 2013 8 | # 9 | # This program is free software: you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | from credit_card import CreditCard 23 | 24 | class PredatoryCreditCard(CreditCard): 25 | """An extension to CreditCard that compounds interest and fees.""" 26 | 27 | def __init__(self, customer, bank, acnt, limit, apr): 28 | """Create a new predatory credit card instance. 29 | 30 | The initial balance is zero. 31 | 32 | customer the name of the customer (e.g., 'John Bowman') 33 | bank the name of the bank (e.g., 'California Savings') 34 | acnt the acount identifier (e.g., '5391 0375 9387 5309') 35 | limit credit limit (measured in dollars) 36 | apr annual percentage rate (e.g., 0.0825 for 8.25% APR) 37 | """ 38 | super().__init__(customer, bank, acnt, limit) # call super constructor 39 | self._apr = apr 40 | 41 | def charge(self, price): 42 | """Charge given price to the card, assuming sufficient credit limit. 43 | 44 | Return True if charge was processed. 45 | Return False and assess $5 fee if charge is denied. 46 | """ 47 | success = super().charge(price) # call inherited method 48 | if not success: 49 | self._balance += 5 # assess penalty 50 | return success # caller expects return value 51 | 52 | def process_month(self): 53 | """Assess monthly interest on outstanding balance.""" 54 | if self._balance > 0: 55 | # if positive balance, convert APR to monthly multiplicative factor 56 | monthly_factor = pow(1 + self._apr, 1/12) 57 | self._balance *= monthly_factor 58 | -------------------------------------------------------------------------------- /ch2/progressions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013, Michael H. Goldwasser 2 | # 3 | # Developed for use with the book: 4 | # 5 | # Data Structures and Algorithms in Python 6 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 7 | # John Wiley & Sons, 2013 8 | # 9 | # This program is free software: you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | class Progression: 23 | """Iterator producing a generic progression. 24 | 25 | Default iterator produces the whole numbers 0, 1, 2, ... 26 | """ 27 | 28 | def __init__(self, start=0): 29 | """Initialize current to the first value of the progression.""" 30 | self._current = start 31 | 32 | def _advance(self): 33 | """Update self._current to a new value. 34 | 35 | This should be overridden by a subclass to customize progression. 36 | 37 | By convention, if current is set to None, this designates the 38 | end of a finite progression. 39 | """ 40 | self._current += 1 41 | 42 | def __next__(self): 43 | """Return the next element, or else raise StopIteration error.""" 44 | if self._current is None: # our convention to end a progression 45 | raise StopIteration() 46 | else: 47 | answer = self._current # record current value to return 48 | self._advance() # advance to prepare for next time 49 | return answer # return the answer 50 | 51 | def __iter__(self): 52 | """By convention, an iterator must return itself as an iterator.""" 53 | return self 54 | 55 | def print_progression(self, n): 56 | """Print next n values of the progression.""" 57 | print(' '.join(str(next(self)) for j in range(n))) 58 | 59 | class ArithmeticProgression(Progression): # inherit from Progression 60 | """Iterator producing an arithmetic progression.""" 61 | 62 | def __init__(self, increment=1, start=0): 63 | """Create a new arithmetic progression. 64 | 65 | increment the fixed constant to add to each term (default 1) 66 | start the first term of the progression (default 0) 67 | """ 68 | super().__init__(start) # initialize base class 69 | self._increment = increment 70 | 71 | def _advance(self): # override inherited version 72 | """Update current value by adding the fixed increment.""" 73 | self._current += self._increment 74 | 75 | 76 | class GeometricProgression(Progression): # inherit from Progression 77 | """Iterator producing a geometric progression.""" 78 | 79 | def __init__(self, base=2, start=1): 80 | """Create a new geometric progression. 81 | 82 | base the fixed constant multiplied to each term (default 2) 83 | start the first term of the progression (default 1) 84 | """ 85 | super().__init__(start) 86 | self._base = base 87 | 88 | def _advance(self): # override inherited version 89 | """Update current value by multiplying it by the base value.""" 90 | self._current *= self._base 91 | 92 | 93 | class FibonacciProgression(Progression): 94 | """Iterator producing a generalized Fibonacci progression.""" 95 | 96 | def __init__(self, first=0, second=1): 97 | """Create a new fibonacci progression. 98 | 99 | first the first term of the progression (default 0) 100 | second the second term of the progression (default 1) 101 | """ 102 | super().__init__(first) # start progression at first 103 | self._prev = second - first # fictitious value preceding the first 104 | 105 | def _advance(self): 106 | """Update current value by taking sum of previous two.""" 107 | self._prev, self._current = self._current, self._prev + self._current 108 | 109 | 110 | if __name__ == '__main__': 111 | print('Default progression:') 112 | Progression().print_progression(10) 113 | 114 | print('Arithmetic progression with increment 5:') 115 | ArithmeticProgression(5).print_progression(10) 116 | 117 | print('Arithmetic progression with increment 5 and start 2:') 118 | ArithmeticProgression(5, 2).print_progression(10) 119 | 120 | print('Geometric progression with default base:') 121 | GeometricProgression().print_progression(10) 122 | 123 | print('Geometric progression with base 3:') 124 | GeometricProgression(3).print_progression(10) 125 | 126 | print('Fibonacci progression with default start values:') 127 | FibonacciProgression().print_progression(10) 128 | 129 | print('Fibonacci progression with start values 4 and 6:') 130 | FibonacciProgression(4, 6).print_progression(10) 131 | -------------------------------------------------------------------------------- /ch2/progressions.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch2/progressions.pyc -------------------------------------------------------------------------------- /ch2/range.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013, Michael H. Goldwasser 2 | # 3 | # Developed for use with the book: 4 | # 5 | # Data Structures and Algorithms in Python 6 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 7 | # John Wiley & Sons, 2013 8 | # 9 | # This program is free software: you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | class Range: 23 | """A class that mimic's the built-in range class.""" 24 | 25 | def __init__(self, start, stop=None, step=1): 26 | """Initialize a Range instance. 27 | 28 | Semantics is similar to built-in range class. 29 | """ 30 | if step == 0: 31 | raise ValueError('step cannot be 0') 32 | 33 | if stop is None: # special case of range(n) 34 | start, stop = 0, start # should be treated as if range(0,n) 35 | 36 | # calculate the effective length once 37 | self._length = max(0, (stop - start + step - 1) // step) 38 | 39 | # need knowledge of start and step (but not stop) to support __getitem__ 40 | self._start = start 41 | self._step = step 42 | 43 | def __len__(self): 44 | """Return number of entries in the range.""" 45 | return self._length 46 | 47 | def __getitem__(self, k): 48 | """Return entry at index k (using standard interpretation if negative).""" 49 | if k < 0: 50 | k += len(self) # attempt to convert negative index 51 | 52 | if not 0 <= k < self._length: 53 | raise IndexError('index out of range') 54 | 55 | return self._start + k * self._step 56 | -------------------------------------------------------------------------------- /ch2/range.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch2/range.pyc -------------------------------------------------------------------------------- /ch2/sequence_abc.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013, Michael H. Goldwasser 2 | # 3 | # Developed for use with the book: 4 | # 5 | # Data Structures and Algorithms in Python 6 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 7 | # John Wiley & Sons, 2013 8 | # 9 | # This program is free software: you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | from abc import ABCMeta, abstractmethod # need these definitions 23 | 24 | class Sequence(metaclass=ABCMeta): 25 | """Our own version of collections.Sequence abstract base class.""" 26 | 27 | @abstractmethod 28 | def __len__(self): 29 | """Return the length of the sequence.""" 30 | 31 | @abstractmethod 32 | def __getitem__(self, j): 33 | """Return the element at index j of the sequence.""" 34 | 35 | def __contains__(self, val): 36 | """Return True if val found in the sequence; False otherwise.""" 37 | for j in range(len(self)): 38 | if self[j] == val: # found match 39 | return True 40 | return False 41 | 42 | def index(self, val): 43 | """Return leftmost index at which val is found (or raise ValueError).""" 44 | for j in range(len(self)): 45 | if self[j] == val: # leftmost match 46 | return j 47 | raise ValueError('value not in sequence') # never found a match 48 | 49 | def count(self, val): 50 | """Return the number of elements equal to given value.""" 51 | k = 0 52 | for j in range(len(self)): 53 | if self[j] == val: # found a match 54 | k += 1 55 | return k 56 | -------------------------------------------------------------------------------- /ch2/sequence_iterator.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013, Michael H. Goldwasser 2 | # 3 | # Developed for use with the book: 4 | # 5 | # Data Structures and Algorithms in Python 6 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 7 | # John Wiley & Sons, 2013 8 | # 9 | # This program is free software: you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | class SequenceIterator: 23 | """An iterator for any of Python's sequence types.""" 24 | 25 | def __init__(self, sequence): 26 | """Create an iterator for the given sequence.""" 27 | self._seq = sequence # keep a reference to the underlying data 28 | self._k = -1 # will increment to 0 on first call to next 29 | 30 | def __next__(self): 31 | """Return the next element, or else raise StopIteration error.""" 32 | self._k += 1 # advance to next index 33 | if self._k < len(self._seq): 34 | return(self._seq[self._k]) # return the data element 35 | else: 36 | raise StopIteration() # there are no more elements 37 | 38 | def __iter__(self): 39 | """By convention, an iterator must return itself as an iterator.""" 40 | return self 41 | -------------------------------------------------------------------------------- /ch2/sequence_iterator.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch2/sequence_iterator.pyc -------------------------------------------------------------------------------- /ch2/vector.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013, Michael H. Goldwasser 2 | # 3 | # Developed for use with the book: 4 | # 5 | # Data Structures and Algorithms in Python 6 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 7 | # John Wiley & Sons, 2013 8 | # 9 | # This program is free software: you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | import collections 23 | 24 | class Vector: 25 | """Represent a vector in a multidimensional space.""" 26 | 27 | def __init__(self, d): 28 | if isinstance(d, int): 29 | self._coords = [0] * d 30 | else: 31 | try: # we test if param is iterable 32 | self._coords = [val for val in d] 33 | except TypeError: 34 | raise TypeError('invalid parameter type') 35 | 36 | def __len__(self): 37 | """Return the dimension of the vector.""" 38 | return len(self._coords) 39 | 40 | def __getitem__(self, j): 41 | """Return jth coordinate of vector.""" 42 | return self._coords[j] 43 | 44 | def __setitem__(self, j, val): 45 | """Set jth coordinate of vector to given value.""" 46 | self._coords[j] = val 47 | 48 | def __add__(self, other): 49 | """Return sum of two vectors.""" 50 | if len(self) != len(other): # relies on __len__ method 51 | raise ValueError('dimensions must agree') 52 | result = Vector(len(self)) # start with vector of zeros 53 | for j in range(len(self)): 54 | result[j] = self[j] + other[j] 55 | return result 56 | 57 | def __eq__(self, other): 58 | """Return True if vector has same coordinates as other.""" 59 | return self._coords == other._coords 60 | 61 | def __ne__(self, other): 62 | """Return True if vector differs from other.""" 63 | return not self == other # rely on existing __eq__ definition 64 | 65 | def __str__(self): 66 | """Produce string representation of vector.""" 67 | return '<' + str(self._coords)[1:-1] + '>' # adapt list representation 68 | 69 | def __neg__(self): 70 | """Return copy of vector with all coordinates negated.""" 71 | result = Vector(len(self)) # start with vector of zeros 72 | for j in range(len(self)): 73 | result[j] = -self[j] 74 | return result 75 | 76 | def __lt__(self, other): 77 | """Compare vectors based on lexicographical order.""" 78 | if len(self) != len(other): 79 | raise ValueError('dimensions must agree') 80 | return self._coords < other._coords 81 | 82 | def __le__(self, other): 83 | """Compare vectors based on lexicographical order.""" 84 | if len(self) != len(other): 85 | raise ValueError('dimensions must agree') 86 | return self._coords <= other._coords 87 | 88 | if __name__ == '__main__': 89 | # the following demonstrates usage of a few methods 90 | v = Vector(5) # construct five-dimensional <0, 0, 0, 0, 0> 91 | v[1] = 23 # <0, 23, 0, 0, 0> (based on use of __setitem__) 92 | v[-1] = 45 # <0, 23, 0, 0, 45> (also via __setitem__) 93 | print(v[4]) # print 45 (via __getitem__) 94 | u = v + v # <0, 46, 0, 0, 90> (via __add__) 95 | print(u) # print <0, 46, 0, 0, 90> 96 | total = 0 97 | for entry in v: # implicit iteration via __len__ and __getitem__ 98 | total += entry 99 | -------------------------------------------------------------------------------- /ch4/C4_10.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Jun Tian 3 | # 4 | # tianjun.cpp@gmail.com 5 | # www.tianjun.ml 6 | # 7 | # DESCRIPTION: 8 | # calculate the integer part of the base-two logarithm of n 9 | # 10 | # Create time: 2013-12-28 19:24:41 11 | 12 | 13 | def log2_int(n): 14 | if n <= 0: 15 | raise ValueError('Input must greater than 0') 16 | elif 0 < n/2 < 1: 17 | return 0 18 | else: 19 | x = 1 20 | x += log2_int(n/2) 21 | return x 22 | 23 | if __name__ == '__main__': 24 | for n in range(10): 25 | print('the integer part of the base-two logarithm of {0} is {1}' 26 | .format(2**n, log2_int(2**n))) 27 | -------------------------------------------------------------------------------- /ch4/C4_12.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Jun Tian 3 | # 4 | # tianjun.cpp@gmail.com 5 | # www.tianjun.ml 6 | # 7 | # DESCRIPTION: 8 | # algorithm to compute the product of two positive integers, 9 | # m and n, using only addition and subtraction. 10 | # 11 | # Create time: 2013-12-28 19:40:48 12 | 13 | 14 | def product(m, n): 15 | sign = (n >= 0) 16 | n = abs(n) 17 | if n > 0: 18 | result = m + product(m, n-1) 19 | else: 20 | result = 0 21 | return result if sign else -result 22 | 23 | if __name__ == '__main__': 24 | for x in range(5): 25 | print('the product of {0} and {1} is {2}' 26 | .format(x, x+1, product(x, x+1))) 27 | print('the product of {0} and {1} is {2}' 28 | .format(-x, x+1, product(-x, x+1))) 29 | -------------------------------------------------------------------------------- /ch4/C4_15.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Jun Tian 3 | # 4 | # tianjun.cpp@gmail.com 5 | # www.tianjun.ml 6 | # 7 | # DESCRIPTION: 8 | # print all subsets 9 | # 10 | # Create time: 2013-12-23 11:43:58 11 | 12 | 13 | def subsets(inS): 14 | outS = [] 15 | if len(inS) > 0: 16 | c = inS[0] 17 | for x in subsets(inS[1::]): 18 | outS.append(x + [c]) 19 | outS.append(x) 20 | return outS 21 | else: 22 | outS.append([]) 23 | return outS 24 | 25 | 26 | def gen_subsets(inS): 27 | """use yield """ 28 | if len(inS) > 0: 29 | head = inS[0] 30 | for tail in gen_subsets(inS[1:]): 31 | yield tail 32 | yield [head] + tail 33 | else: 34 | yield [] 35 | 36 | if __name__ == '__main__': 37 | inS = list('abc') 38 | # test function 39 | result = subsets(inS) 40 | print(result) 41 | print(len(result)) 42 | # test generator 43 | for s in gen_subsets(inS): 44 | print(s) 45 | -------------------------------------------------------------------------------- /ch4/C4_16.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Jun Tian 3 | # 4 | # tianjun.cpp@gmail.com 5 | # www.tianjun.ml 6 | # 7 | # DESCRIPTION: 8 | # string reverse 9 | # 10 | # Create time: 2013-12-28 20:04:26 11 | 12 | 13 | def reverse_str(s): 14 | if len(s) >= 2: 15 | innerReversed = reverse_str(s[1:-1]) 16 | innerReversed.append(s[0]) 17 | innerReversed.insert(0, s[-1]) 18 | return innerReversed 19 | else: 20 | return list(s) 21 | 22 | if __name__ == '__main__': 23 | print(''.join(reverse_str('pots&pans'))) 24 | -------------------------------------------------------------------------------- /ch4/C4_17.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Jun Tian 3 | # 4 | # tianjun.cpp@gmail.com 5 | # www.tianjun.ml 6 | # 7 | # DESCRIPTION: 8 | # if a stringsis a palindrome 9 | # 10 | # Create time: 2013-12-28 20:39:18 11 | 12 | 13 | def palindrome(s): 14 | if len(s) > 1: 15 | if s[0] != s[-1]: 16 | return False 17 | else: 18 | return palindrome(s[1:-1]) 19 | else: 20 | return True 21 | 22 | if __name__ == '__main__': 23 | print(palindrome('racecar')) 24 | print(palindrome('gohangasalamiimalasagnahog')) 25 | -------------------------------------------------------------------------------- /ch4/C4_9.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Jun Tian 3 | # 4 | # tianjun.cpp@gmail.com 5 | # www.tianjun.ml 6 | # 7 | # DESCRIPTION: 8 | # find max min value using recursion 9 | # 10 | # Create time: 2013-12-23 10:54:50 11 | 12 | 13 | def find_MaxMin(data, l, r): 14 | mid = (l + r) // 2 15 | if l == mid: 16 | return min(data[l], data[r]), max(data[l], data[r]) 17 | else: 18 | lmin, lmax = find_MaxMin(data, l, mid) 19 | rmin, rmax = find_MaxMin(data, mid, r) 20 | return min(lmin, rmin), max(lmax, rmax) 21 | 22 | if __name__ == '__main__': 23 | a, b = find_MaxMin([3, 8, 10, 0, 7], 0, 4) 24 | print("min is {0} \ 25 | max is {1}".format(a, b)) 26 | -------------------------------------------------------------------------------- /ch4/P4_23.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Jun Tian 3 | # 4 | # tianjun.cpp@gmail.com 5 | # www.tianjun.ml 6 | # 7 | # DESCRIPTION: 8 | # find file in a given path 9 | # 10 | # Create time: 2013-12-28 20:51:13 11 | import os 12 | 13 | 14 | def find_file(path, filename): 15 | for x in os.listdir(path): 16 | try: 17 | if os.path.isdir(path + os.sep + x): 18 | if find_file(path + os.sep + x, filename): 19 | #如果该目录下找到了文件就返回True,否则继续查找 20 | return True 21 | else: 22 | if x == filename: 23 | return True 24 | except: 25 | #当遇到以 .开头的隐藏文件夹时回报错,忽略 26 | pass 27 | #如果遍历了所有文件和目录都没找到,则返回False 28 | return False 29 | 30 | if __name__ == '__main__': 31 | path = os.path.abspath('..') 32 | print('If P4_23.py in parrent dir? {0}' 33 | .format(find_file(path, 'P4_23.py'))) 34 | print('If P4_23.py in current dir? {0}' 35 | .format(find_file('.', 'P4_23.py'))) 36 | -------------------------------------------------------------------------------- /ch5/C5_14.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R5_14.py 8 | # Description: 9 | # my shuffle 10 | # 11 | # Last Modified: 12 | # 2014-06-26 19:23:54 13 | from random import randrange 14 | 15 | 16 | def my_shuffle(d): 17 | a = [] 18 | for k in range(len(d)): 19 | i = randrange(len(d)) 20 | a.append(d.pop(i)) 21 | return a 22 | 23 | 24 | if __name__ == '__main__': 25 | d = [i for i in range(10)] 26 | print("origin data:", d) 27 | a = my_shuffle(d) 28 | print("shuffled data:", a) 29 | -------------------------------------------------------------------------------- /ch5/C5_16.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: C5_16.py 8 | # Description: 9 | # update pop method of DynamicArray 10 | # 11 | # Last Modified: 12 | # 2014-06-26 19:33:46 13 | from dynamic_array import DynamicArray 14 | 15 | 16 | class MyArray(DynamicArray): 17 | def __init__(self): 18 | super().__init__() 19 | 20 | def pop(self): 21 | self._n -= 1 22 | if self._n <= 0: 23 | raise IndexError 24 | if self._n < self._capacity / 4: 25 | self._capacity = self._capacity // 2 26 | return self._A[self._n - 1] 27 | 28 | def __str__(self): 29 | a = [] 30 | for i in range(self._n): 31 | a.append(self._A[i]) 32 | return '[' + ','.join(str(x) for x in a) + ']' 33 | 34 | if __name__ == '__main__': 35 | a = MyArray() 36 | for i in range(100): 37 | a.append(i) 38 | print(a) 39 | for i in range(100): 40 | x = a.pop() 41 | print("len:{},capacity:{}".format(a._n, a._capacity)) 42 | -------------------------------------------------------------------------------- /ch5/R5_10.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R5_10.py 8 | # Description: 9 | # change init 10 | # 11 | # Last Modified: 12 | # 2014-06-26 17:08:36 13 | 14 | 15 | from caesar import CaesarCipher 16 | 17 | 18 | class NewCaesar(CaesarCipher): 19 | def __init__(self, shift): 20 | self._forward = ''.join(chr((i + shift) % 26 + ord('A')) 21 | for i in range(26)) 22 | self._backward = ''.join(chr((i - shift) % 26 + ord('A')) 23 | for i in range(26)) 24 | if __name__ == '__main__': 25 | cipher = NewCaesar(3) 26 | message = "THE EAGLE IS IN PLAY; MEET AT JOE'S." 27 | coded = cipher.encrypt(message) 28 | print('Secret: ', coded) 29 | answer = cipher.decrypt(coded) 30 | print('Message:', answer) 31 | -------------------------------------------------------------------------------- /ch5/R5_11.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R5_11.py 8 | # Description: 9 | # sum two dim data 10 | # 11 | # Last Modified: 12 | # 2014-06-26 19:12:21 13 | 14 | 15 | from pprint import pprint 16 | data = [[i for i in range(10)] for j in range(10)] 17 | pprint(data) 18 | sum = 0 19 | for i in range(len(data)): 20 | for j in range(len(data[i])): 21 | sum += data[i][j] 22 | print("sum of data:", sum) 23 | -------------------------------------------------------------------------------- /ch5/R5_12.py: -------------------------------------------------------------------------------- 1 | from pprint import pprint 2 | data = [[i for i in range(10)] for j in range(10)] 3 | pprint(data) 4 | 5 | print("sum of data:", sum(sum(x) for x in data)) 6 | -------------------------------------------------------------------------------- /ch5/R5_2.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Jun Tian 3 | # 4 | # tianjun.cpp@gmail.com 5 | # www.tianjun.ml 6 | # 7 | # DESCRIPTION: 8 | # 9 | # 10 | # Create time: 2014-01-06 19:54:50 11 | 12 | import sys 13 | data = [] 14 | cur = 0 15 | for k in range(30): 16 | a = len(data) 17 | b = sys.getsizeof(data) 18 | if b > cur and a > 0: 19 | cur = b 20 | print('''Exausted when lenth = {0}'''.format(a - 1)) 21 | data.append(None) 22 | -------------------------------------------------------------------------------- /ch5/R5_3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2013, Jun Tian 3 | # 4 | # tianjun.cpp@gmail.com 5 | # www.tianjun.ml 6 | # 7 | # DESCRIPTION: 8 | # 9 | # 10 | # Create time: 2014-01-06 19:59:55 11 | 12 | import sys 13 | data = [] 14 | cur = 0 15 | for k in range(30): 16 | a = len(data) 17 | b = sys.getsizeof(data) 18 | print('length:{0:3d};size in bytes:{1:4d}'.format(a, b)) 19 | data.append(None) 20 | for k in range(30): 21 | a = len(data) 22 | b = sys.getsizeof(data) 23 | print('length:{0:3d};size in bytes:{1:4d}'.format(a, b)) 24 | data.pop() 25 | -------------------------------------------------------------------------------- /ch5/R5_4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R5_4.py 8 | # Description: 9 | # change getitem method 10 | # 11 | # Last Modified: 12 | # 2014-06-26 13:11:19 13 | 14 | 15 | from dynamic_array import DynamicArray 16 | 17 | 18 | class MyArray(DynamicArray): 19 | def __init__(self): 20 | super().__init__() 21 | 22 | def __getitem__(self, k): 23 | """Return element at index k.""" 24 | if k < 0: 25 | k += self._n 26 | if not 0 <= k < self._n: 27 | raise IndexError('invalid index') 28 | return self._A[k] # retrieve from array 29 | 30 | if __name__ == '__main__': 31 | a = MyArray() 32 | for i in range(5): 33 | a.append(i) 34 | for i in range(5): 35 | print(a[-i]) 36 | #test exception 37 | print(a[-10]) 38 | -------------------------------------------------------------------------------- /ch5/R5_6.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R5_6.py 8 | # Description: 9 | # change insert 10 | # 11 | # Last Modified: 12 | # 2014-06-26 13:35:25 13 | 14 | 15 | from dynamic_array import DynamicArray 16 | 17 | 18 | class MyArray(DynamicArray): 19 | def __init__(self): 20 | super().__init__() 21 | 22 | def insert(self, k, value): 23 | """Insert value at index k, shifting subsequent values rightward.""" 24 | # (for simplicity, we assume 0 <= k <= n in this verion) 25 | if self._n == self._capacity: # not enough room 26 | B = self._make_array(2 * self._capacity) # so double capacity 27 | for j in range(self._n, k, -1): # shift rightmost first 28 | B[j] = self._A[j - 1] 29 | B[k] = value # store newest element 30 | for j in range(0, k): 31 | B[j] = self._A[j] 32 | self._A = B 33 | self._n += 1 34 | self._capacity = 2 * self._capacity 35 | 36 | else: 37 | for j in range(self._n, k, -1): # shift rightmost first 38 | self._A[j] = self._A[j - 1] 39 | 40 | self._A[k] = value # store newest element 41 | self._n += 1 42 | 43 | def __str__(self): 44 | a = [] 45 | for i in range(self._n): 46 | a.append(self._A[i]) 47 | return '[' + ','.join(str(x) for x in a) + ']' 48 | 49 | if __name__ == '__main__': 50 | a = MyArray() 51 | for i in range(20): 52 | a.insert(0, i) 53 | print(a) 54 | -------------------------------------------------------------------------------- /ch5/R5_8.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R5_8.py 8 | # Description: 9 | # evalue pop of list 10 | # 11 | # Last Modified: 12 | # 2014-06-26 16:28:02 13 | 14 | import time 15 | L = 10 ** 6 16 | 17 | 18 | def pop_test(N, position): 19 | A = [None] * L 20 | t0 = time.time() 21 | for i in range(N): 22 | A.pop(len(A) // 2 if position == 1 else position) 23 | return time.time() - t0 24 | 25 | 26 | if __name__ == '__main__': 27 | print('\tN={}\tN={}\tN='.format('', 28 | str(10 ** 2), 29 | str(10 ** 3), 30 | str(10 ** 4), 31 | str(10 ** 5))) 32 | for p in [-1, 1, 0]: 33 | print('k = ', p, end='\t') 34 | for i in range(2, 6): 35 | N = 10 ** i 36 | print(pop_test(N, p), end='\t') 37 | print('') 38 | -------------------------------------------------------------------------------- /ch5/__pycache__/caesar.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch5/__pycache__/caesar.cpython-34.pyc -------------------------------------------------------------------------------- /ch5/__pycache__/dynamic_array.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch5/__pycache__/dynamic_array.cpython-34.pyc -------------------------------------------------------------------------------- /ch5/caesar.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013, Michael H. Goldwasser 2 | # 3 | # Developed for use with the book: 4 | # 5 | # Data Structures and Algorithms in Python 6 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 7 | # John Wiley & Sons, 2013 8 | # 9 | # This program is free software: you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | class CaesarCipher: 23 | """Class for doing encryption and decryption using a Caesar cipher.""" 24 | 25 | def __init__(self, shift): 26 | """Construct Caesar cipher using given integer shift for rotation.""" 27 | encoder = [None] * 26 # temp array for encryption 28 | decoder = [None] * 26 # temp array for decryption 29 | for k in range(26): 30 | encoder[k] = chr((k + shift) % 26 + ord('A')) 31 | decoder[k] = chr((k - shift) % 26 + ord('A')) 32 | self._forward = ''.join(encoder) # will store as string 33 | self._backward = ''.join(decoder) # since fixed 34 | 35 | def encrypt(self, message): 36 | """Return string representing encripted message.""" 37 | return self._transform(message, self._forward) 38 | 39 | def decrypt(self, secret): 40 | """Return decrypted message given encrypted secret.""" 41 | return self._transform(secret, self._backward) 42 | 43 | def _transform(self, original, code): 44 | """Utility to perform transformation based on given code string.""" 45 | msg = list(original) 46 | for k in range(len(msg)): 47 | if msg[k].isupper(): 48 | j = ord(msg[k]) - ord('A') # index from 0 to 25 49 | msg[k] = code[j] # replace this character 50 | return ''.join(msg) 51 | 52 | if __name__ == '__main__': 53 | cipher = CaesarCipher(3) 54 | message = "THE EAGLE IS IN PLAY; MEET AT JOE'S." 55 | coded = cipher.encrypt(message) 56 | print('Secret: ', coded) 57 | answer = cipher.decrypt(coded) 58 | print('Message:', answer) 59 | -------------------------------------------------------------------------------- /ch5/dynamic_array.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013, Michael H. Goldwasser 2 | # 3 | # Developed for use with the book: 4 | # 5 | # Data Structures and Algorithms in Python 6 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 7 | # John Wiley & Sons, 2013 8 | # 9 | # This program is free software: you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | import ctypes # provides low-level arrays 23 | 24 | class DynamicArray: 25 | """A dynamic array class akin to a simplified Python list.""" 26 | 27 | def __init__(self): 28 | """Create an empty array.""" 29 | self._n = 0 # count actual elements 30 | self._capacity = 1 # default array capacity 31 | self._A = self._make_array(self._capacity) # low-level array 32 | 33 | def __len__(self): 34 | """Return number of elements stored in the array.""" 35 | return self._n 36 | 37 | def __getitem__(self, k): 38 | """Return element at index k.""" 39 | if not 0 <= k < self._n: 40 | raise IndexError('invalid index') 41 | return self._A[k] # retrieve from array 42 | 43 | def append(self, obj): 44 | """Add object to end of the array.""" 45 | if self._n == self._capacity: # not enough room 46 | self._resize(2 * self._capacity) # so double capacity 47 | self._A[self._n] = obj 48 | self._n += 1 49 | 50 | def _resize(self, c): # nonpublic utitity 51 | """Resize internal array to capacity c.""" 52 | B = self._make_array(c) # new (bigger) array 53 | for k in range(self._n): # for each existing value 54 | B[k] = self._A[k] 55 | self._A = B # use the bigger array 56 | self._capacity = c 57 | 58 | def _make_array(self, c): # nonpublic utitity 59 | """Return new array with capacity c.""" 60 | return (c * ctypes.py_object)() # see ctypes documentation 61 | 62 | def insert(self, k, value): 63 | """Insert value at index k, shifting subsequent values rightward.""" 64 | # (for simplicity, we assume 0 <= k <= n in this verion) 65 | if self._n == self._capacity: # not enough room 66 | self._resize(2 * self._capacity) # so double capacity 67 | for j in range(self._n, k, -1): # shift rightmost first 68 | self._A[j] = self._A[j-1] 69 | self._A[k] = value # store newest element 70 | self._n += 1 71 | 72 | def remove(self, value): 73 | """Remove first occurrence of value (or raise ValueError).""" 74 | # note: we do not consider shrinking the dynamic array in this version 75 | for k in range(self._n): 76 | if self._A[k] == value: # found a match! 77 | for j in range(k, self._n - 1): # shift others to fill gap 78 | self._A[j] = self._A[j+1] 79 | self._A[self._n - 1] = None # help garbage collection 80 | self._n -= 1 # we have one less item 81 | return # exit immediately 82 | raise ValueError('value not found') # only reached if no match 83 | -------------------------------------------------------------------------------- /ch5/dynamic_array.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch5/dynamic_array.pyc -------------------------------------------------------------------------------- /ch6/C6_15.py: -------------------------------------------------------------------------------- 1 | # x = S.pop() 2 | # x > S.pop() ? x : S.pop() 3 | -------------------------------------------------------------------------------- /ch6/C6_16.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: C6_16.py 8 | # Description: 9 | # change the implementation of arraystack 10 | # 11 | # Last Modified: 12 | # 2014-07-04 12:46:09 13 | 14 | 15 | from array_stack import ArrayStack 16 | 17 | 18 | class Full(Exception): 19 | pass 20 | 21 | 22 | class MyStack(ArrayStack): 23 | def __init__(self, maxlen=None): 24 | self._maxlen = maxlen 25 | self._data = [] if maxlen is None else [None] * maxlen 26 | 27 | def push(self, e): 28 | """Add element e to the top of the stack.""" 29 | if len(self._data) >= self._maxlen: # Careful, when maxlen is None, 30 | # this comparision will raise an error 31 | raise Full("Stack is full!!!") 32 | self._data.append(e) # new item stored at end of list 33 | 34 | 35 | if __name__ == '__main__': 36 | S = MyStack() 37 | for i in range(10): 38 | try: 39 | S.push(i) 40 | except Exception as e: 41 | print(e) 42 | -------------------------------------------------------------------------------- /ch6/C6_17.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: C6_16.py 8 | # Description: 9 | # change the implementation of arraystack 10 | # 11 | # Last Modified: 12 | # 2014-07-04 12:46:09 13 | 14 | 15 | from array_stack import ArrayStack 16 | 17 | 18 | class Full(Exception): 19 | pass 20 | 21 | 22 | class MyStack(ArrayStack): 23 | def __init__(self, maxlen=None): 24 | super().__init__() 25 | self._maxlen = maxlen 26 | 27 | def push(self, e): 28 | """Add element e to the top of the stack.""" 29 | if self.__len__() >= self._maxlen: # Careful, when maxlen is None, 30 | # this comparision will raise an error 31 | raise Full("Stack is full!!!") 32 | self._data.append(e) # new item stored at end of list 33 | 34 | 35 | if __name__ == '__main__': 36 | S = MyStack(5) 37 | for i in range(10): 38 | try: 39 | S.push(i) 40 | except Exception as e: 41 | print(e) 42 | -------------------------------------------------------------------------------- /ch6/R6_11.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R6_11.py 8 | # Description: 9 | # use collections.deque to inplement queue 10 | # 11 | # Last Modified: 12 | # 2014-06-27 10:48:50 13 | from collections import deque 14 | 15 | 16 | class MyQueue(): 17 | def __init__(self): 18 | self._data = deque() 19 | 20 | def __len__(self): 21 | return len(self._data) 22 | 23 | def is_empty(self): 24 | return len(self._data) == 0 25 | 26 | def first(self): 27 | return self._data[0] 28 | 29 | def dequeue(self): 30 | self._data.popleft() 31 | 32 | def enqueue(self, v): 33 | self._data.append(v) 34 | -------------------------------------------------------------------------------- /ch6/R6_13.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R6_13.py 8 | # Description: 9 | # use queue to change [1,2,3,4,5,6,7,8] into 10 | # [1,2,3,5,4,6,7,8] 11 | # Last Modified: 12 | # 2014-06-27 11:08:05 13 | 14 | 15 | from array_queue import ArrayQueue 16 | 17 | if __name__ == '__main__': 18 | D = ArrayQueue() 19 | Q = ArrayQueue() 20 | #initial D 21 | for i in range(1, 9): 22 | D.enqueue(i) 23 | 24 | D.enqueue(D.dequeue()) 25 | D.enqueue(D.dequeue()) 26 | D.enqueue(D.dequeue()) # D = [4,5,6,7,8,1,2,3] 27 | 28 | Q.enqueue(D.dequeue()) # Q = [4], D = [5,6,7,8,1,2,3] 29 | D.enqueue(D.dequeue()) # Q = [4], D = [6,7,8,1,2,3,5] 30 | D.enqueue(Q.dequeue()) # Q = [], D = [6,7,8,1,2,3,5,4] 31 | 32 | D.enqueue(D.dequeue()) 33 | D.enqueue(D.dequeue()) 34 | D.enqueue(D.dequeue()) # D = [1,2,3,5,4,6,7,8] 35 | 36 | for i in range(8): 37 | print(D.dequeue(), end=',') 38 | -------------------------------------------------------------------------------- /ch6/R6_14.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R6_14.py 8 | # Description: 9 | # use deque to change [1,2,3,4,5,6,7,8] to 10 | # [1,2,3,5,4,6,7,8] 11 | # 12 | # Last Modified: 13 | # 2014-06-27 11:24:51 14 | 15 | 16 | from collections import deque 17 | 18 | if __name__ == '__main__': 19 | D = deque() 20 | S = deque() 21 | D.extend(i for i in range(1, 9)) 22 | print(D) 23 | 24 | S.append(D.popleft()) 25 | S.append(D.popleft()) 26 | S.append(D.popleft()) 27 | S.append(D.popleft()) 28 | D.append(D.popleft()) 29 | D.appendleft(S.pop()) 30 | D.appendleft(D.pop()) 31 | D.appendleft(S.pop()) 32 | D.appendleft(S.pop()) 33 | D.appendleft(S.pop()) 34 | 35 | print(D) 36 | -------------------------------------------------------------------------------- /ch6/R6_3.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R6_3.py 8 | # Description: 9 | # transfer stack 10 | # 11 | # Last Modified: 12 | # 2014-06-27 10:15:20 13 | 14 | 15 | from array_stack import ArrayStack, Empty 16 | 17 | 18 | def transfer(s, t): 19 | while(len(s)>0): 20 | t.push(s.pop()) 21 | 22 | if __name__ == '__main__': 23 | s = ArrayStack() 24 | t = ArrayStack() 25 | for i in range(10): 26 | s.push(i) 27 | transfer(s, t) 28 | for i in range(10): 29 | print(t.pop()) 30 | -------------------------------------------------------------------------------- /ch6/R6_4.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R6_4.py 8 | # Description: 9 | # recursively remove elements in stack 10 | # 11 | # Last Modified: 12 | # 2014-06-27 10:25:25 13 | 14 | 15 | from array_stack import ArrayStack, Empty 16 | 17 | 18 | def recursive_remove(s): 19 | if len(s) > 0: 20 | s.pop() 21 | recursive_remove(s) 22 | else: 23 | pass 24 | 25 | if __name__ == '__main__': 26 | s = ArrayStack() 27 | for i in range(100): 28 | s.push(i) 29 | recursive_remove(s) 30 | try: 31 | s.pop() 32 | except Empty as e: 33 | print(e) 34 | -------------------------------------------------------------------------------- /ch6/R6_5.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Author: TianJun 4 | # E-mail: tianjun.cpp@gmail.com 5 | # Website: www.tianjun.ml 6 | # 7 | # File Name: R6_5.py 8 | # Description: 9 | # reverse list use stack 10 | # 11 | # Last Modified: 12 | # 2014-06-27 10:33:45 13 | 14 | 15 | from array_stack import ArrayStack, Empty 16 | 17 | 18 | def reverse(L): 19 | s = ArrayStack() 20 | for i in range(len(L)): 21 | s.push(L[i]) 22 | for i in range(len(L)): 23 | L[i] = s.pop() 24 | 25 | if __name__ == '__main__': 26 | L = [i for i in range(10)] 27 | print(L) 28 | reverse(L) 29 | print('reversed L:\n', L) 30 | -------------------------------------------------------------------------------- /ch6/__pycache__/array_queue.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch6/__pycache__/array_queue.cpython-34.pyc -------------------------------------------------------------------------------- /ch6/__pycache__/array_stack.cpython-34.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch6/__pycache__/array_stack.cpython-34.pyc -------------------------------------------------------------------------------- /ch6/array_queue.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013, Michael H. Goldwasser 2 | # 3 | # Developed for use with the book: 4 | # 5 | # Data Structures and Algorithms in Python 6 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 7 | # John Wiley & Sons, 2013 8 | # 9 | # This program is free software: you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | #from ..exceptions import Empty 23 | class Empty(Exception): 24 | pass 25 | 26 | class ArrayQueue: 27 | """FIFO queue implementation using a Python list as underlying storage.""" 28 | DEFAULT_CAPACITY = 10 # moderate capacity for all new queues 29 | 30 | def __init__(self): 31 | """Create an empty queue.""" 32 | self._data = [None] * ArrayQueue.DEFAULT_CAPACITY 33 | self._size = 0 34 | self._front = 0 35 | 36 | def __len__(self): 37 | """Return the number of elements in the queue.""" 38 | return self._size 39 | 40 | def is_empty(self): 41 | """Return True if the queue is empty.""" 42 | return self._size == 0 43 | 44 | def first(self): 45 | """Return (but do not remove) the element at the front of the queue. 46 | 47 | Raise Empty exception if the queue is empty. 48 | """ 49 | if self.is_empty(): 50 | raise Empty('Queue is empty') 51 | return self._data[self._front] 52 | 53 | def dequeue(self): 54 | """Remove and return the first element of the queue (i.e., FIFO). 55 | 56 | Raise Empty exception if the queue is empty. 57 | """ 58 | if self.is_empty(): 59 | raise Empty('Queue is empty') 60 | answer = self._data[self._front] 61 | self._data[self._front] = None # help garbage collection 62 | self._front = (self._front + 1) % len(self._data) 63 | self._size -= 1 64 | return answer 65 | 66 | def enqueue(self, e): 67 | """Add an element to the back of queue.""" 68 | if self._size == len(self._data): 69 | self._resize(2 * len(self.data)) # double the array size 70 | avail = (self._front + self._size) % len(self._data) 71 | self._data[avail] = e 72 | self._size += 1 73 | 74 | def _resize(self, cap): # we assume cap >= len(self) 75 | """Resize to a new list of capacity >= len(self).""" 76 | old = self._data # keep track of existing list 77 | self._data = [None] * cap # allocate list with new capacity 78 | walk = self._front 79 | for k in range(self._size): # only consider existing elements 80 | self._data[k] = old[walk] # intentionally shift indices 81 | walk = (1 + walk) % len(old) # use old size as modulus 82 | self._front = 0 # front has been realigned 83 | -------------------------------------------------------------------------------- /ch6/array_queue.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch6/array_queue.pyc -------------------------------------------------------------------------------- /ch6/array_stack.py: -------------------------------------------------------------------------------- 1 | # Copyright 2013, Michael H. Goldwasser 2 | # 3 | # Developed for use with the book: 4 | # 5 | # Data Structures and Algorithms in Python 6 | # Michael T. Goodrich, Roberto Tamassia, and Michael H. Goldwasser 7 | # John Wiley & Sons, 2013 8 | # 9 | # This program is free software: you can redistribute it and/or modify 10 | # it under the terms of the GNU General Public License as published by 11 | # the Free Software Foundation, either version 3 of the License, or 12 | # (at your option) any later version. 13 | # 14 | # This program is distributed in the hope that it will be useful, 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 | # GNU General Public License for more details. 18 | # 19 | # You should have received a copy of the GNU General Public License 20 | # along with this program. If not, see . 21 | 22 | """Basic example of an adapter class to provide a stack interface to Python's list.""" 23 | 24 | #from ..exceptions import Empty 25 | class Empty(Exception): 26 | pass 27 | 28 | class ArrayStack: 29 | """LIFO Stack implementation using a Python list as underlying storage.""" 30 | 31 | def __init__(self): 32 | """Create an empty stack.""" 33 | self._data = [] # nonpublic list instance 34 | 35 | def __len__(self): 36 | """Return the number of elements in the stack.""" 37 | return len(self._data) 38 | 39 | def is_empty(self): 40 | """Return True if the stack is empty.""" 41 | return len(self._data) == 0 42 | 43 | def push(self, e): 44 | """Add element e to the top of the stack.""" 45 | self._data.append(e) # new item stored at end of list 46 | 47 | def top(self): 48 | """Return (but do not remove) the element at the top of the stack. 49 | 50 | Raise Empty exception if the stack is empty. 51 | """ 52 | if self.is_empty(): 53 | raise Empty('Stack is empty') 54 | return self._data[-1] # the last item in the list 55 | 56 | def pop(self): 57 | """Remove and return the element from the top of the stack (i.e., LIFO). 58 | 59 | Raise Empty exception if the stack is empty. 60 | """ 61 | if self.is_empty(): 62 | raise Empty('Stack is empty') 63 | return self._data.pop() # remove last item from list 64 | 65 | if __name__ == '__main__': 66 | S = ArrayStack() # contents: [ ] 67 | S.push(5) # contents: [5] 68 | S.push(3) # contents: [5, 3] 69 | print(len(S)) # contents: [5, 3]; outputs 2 70 | print(S.pop()) # contents: [5]; outputs 3 71 | print(S.is_empty()) # contents: [5]; outputs False 72 | print(S.pop()) # contents: [ ]; outputs 5 73 | print(S.is_empty()) # contents: [ ]; outputs True 74 | S.push(7) # contents: [7] 75 | S.push(9) # contents: [7, 9] 76 | print(S.top()) # contents: [7, 9]; outputs 9 77 | S.push(4) # contents: [7, 9, 4] 78 | print(len(S)) # contents: [7, 9, 4]; outputs 3 79 | print(S.pop()) # contents: [7, 9]; outputs 4 80 | S.push(6) # contents: [7, 9, 6] 81 | S.push(8) # contents: [7, 9, 6, 8] 82 | print(S.pop()) # contents: [7, 9, 6]; outputs 8 83 | -------------------------------------------------------------------------------- /ch6/array_stack.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/findmyway/Data-Structures-and-Algorithms-in-Python/11877f0256f3771a2814b76c7b260331a3df411c/ch6/array_stack.pyc --------------------------------------------------------------------------------