├── 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
--------------------------------------------------------------------------------