Mercurial > public > think_complexity
comparison ch3ex4.py @ 12:b75bf8bfa2cf
Adding author's Map.py as ch3ex4.py to represent the original version before
working on the exercise.
author | Brian Neal <bgneal@gmail.com> |
---|---|
date | Mon, 10 Dec 2012 19:36:47 -0600 |
parents | |
children | be7f2cd15faf |
comparison
equal
deleted
inserted
replaced
11:0f98bcb5bd3f | 12:b75bf8bfa2cf |
---|---|
1 """ Code example from Complexity and Computation, a book about | |
2 exploring complexity science with Python. Available free from | |
3 | |
4 http://greenteapress.com/complexity | |
5 | |
6 Copyright 2011 Allen B. Downey. | |
7 Distributed under the GNU General Public License at gnu.org/licenses/gpl.html. | |
8 """ | |
9 | |
10 import string | |
11 | |
12 | |
13 class LinearMap(object): | |
14 """A simple implementation of a map using a list of tuples | |
15 where each tuple is a key-value pair.""" | |
16 | |
17 def __init__(self): | |
18 self.items = [] | |
19 | |
20 def add(self, k, v): | |
21 """Adds a new item that maps from key (k) to value (v). | |
22 Assumes that they keys are unique.""" | |
23 self.items.append((k, v)) | |
24 | |
25 def get(self, k): | |
26 """Looks up the key (k) and returns the corresponding value, | |
27 or raises KeyError if the key is not found.""" | |
28 for key, val in self.items: | |
29 if key == k: | |
30 return val | |
31 raise KeyError | |
32 | |
33 | |
34 class BetterMap(object): | |
35 """A faster implementation of a map using a list of LinearMaps | |
36 and the built-in function hash() to determine which LinearMap | |
37 to put each key into.""" | |
38 | |
39 def __init__(self, n=100): | |
40 """Appends (n) LinearMaps onto (self).""" | |
41 self.maps = [] | |
42 for i in range(n): | |
43 self.maps.append(LinearMap()) | |
44 | |
45 def find_map(self, k): | |
46 """Finds the right LinearMap for key (k).""" | |
47 index = hash(k) % len(self.maps) | |
48 return self.maps[index] | |
49 | |
50 def add(self, k, v): | |
51 """Adds a new item to the appropriate LinearMap for key (k).""" | |
52 m = self.find_map(k) | |
53 m.add(k, v) | |
54 | |
55 def get(self, k): | |
56 """Finds the right LinearMap for key (k) and looks up (k) in it.""" | |
57 m = self.find_map(k) | |
58 return m.get(k) | |
59 | |
60 | |
61 class HashMap(object): | |
62 """An implementation of a hashtable using a BetterMap | |
63 that grows so that the number of items never exceeds the number | |
64 of LinearMaps. | |
65 | |
66 The amortized cost of add should be O(1) provided that the | |
67 implementation of sum in resize is linear.""" | |
68 | |
69 def __init__(self): | |
70 """Starts with 2 LinearMaps and 0 items.""" | |
71 self.maps = BetterMap(2) | |
72 self.num = 0 | |
73 | |
74 def get(self, k): | |
75 """Looks up the key (k) and returns the corresponding value, | |
76 or raises KeyError if the key is not found.""" | |
77 return self.maps.get(k) | |
78 | |
79 def add(self, k, v): | |
80 """Resize the map if necessary and adds the new item.""" | |
81 if self.num == len(self.maps.maps): | |
82 self.resize() | |
83 | |
84 self.maps.add(k, v) | |
85 self.num += 1 | |
86 | |
87 def resize(self): | |
88 """Makes a new map, twice as big, and rehashes the items.""" | |
89 new_maps = BetterMap(self.num * 2) | |
90 | |
91 for m in self.maps.maps: | |
92 for k, v in m.items: | |
93 new_maps.add(k, v) | |
94 | |
95 self.maps = new_maps | |
96 | |
97 | |
98 def main(script): | |
99 m = HashMap() | |
100 s = string.ascii_lowercase | |
101 | |
102 for k, v in enumerate(s): | |
103 m.add(k, v) | |
104 | |
105 for k in range(len(s)): | |
106 print k, m.get(k) | |
107 | |
108 | |
109 if __name__ == '__main__': | |
110 import sys | |
111 main(*sys.argv) |