数据结构与算法 Python语言实现 第四章练习

巩固

  1 # R-4.1
  2 def find_max(data):
  3     n = len(data)
  4     if n == 1:
  5         return data[0]
  6     elif data[0] > data[1]:
  7         data.pop(1)
  8     elif data[0] < data[1]:
  9         data.pop(0)
 10     return find_max(data)
 11 
 12 
 13 # print(find_max([1, 2, 3, 4, 6, 5]))
 14 # 时间:O(n)  空间:O(n)
 15 
 16 
 17 # R-4.2
 18 def power(x, n):
 19     if n == 0:
 20         return 1
 21     else:
 22         return x * power(x, n-1)
 23 
 24 
 25 # print(power(2, 5))
 26 
 27 
 28 # R-4.3
 29 def power(x, n):
 30     if n == 0:
 31         return 1
 32     else:
 33         partial = power(x, n // 2)
 34         result = partial * partial
 35         if n % 2 == 1:
 36             result *= x
 37         return result
 38 
 39 
 40 # print(power(2, 18))
 41 
 42 
 43 # R-4.4
 44 def reverse(S, start, stop):
 45     if start < stop - 1:
 46         S[start], S[stop-1] = S[stop-1], S[start]
 47         reverse(S, start+1, stop-1)
 48 
 49 
 50 S = [4, 3, 6, 2, 6]
 51 reverse(S, 0, 5)
 52 # print(S)
 53 
 54 
 55 # R-4.5
 56 # def puzzle_solve(k, S, U):
 57 #     for i in sorted(U):
 58 #         S.append(i)
 59 #         U.remove(i)
 60 #         if k == 1:
 61 #             print(S)
 62 #         else:
 63 #             puzzle_solve(k-1, S, U)
 64 #         S.remove(i)
 65 #         U.append(i)
 66 #
 67 #
 68 # puzzle_solve(3, [], ['a', 'b', 'c', 'd'])
 69 
 70 
 71 # --------------R4-5------------------------
 72 # Note that S is our attempt at solving the sequence and U is our set of all possible numbers that are unused
 73 def solves(S):
 74     # Note, this is a random solution to the pseudoproblem
 75     return S == ['d', 'b', 'c']
 76 
 77 
 78 def PuzzleSolver(k, S, U):
 79     for e in sorted(U).copy():
 80         S.append(e)
 81         U.remove(e)
 82         if k == 1:
 83             print(S)
 84             if solves(S):
 85                 print( f'Solution found: {S}')
 86         else:
 87             PuzzleSolver(k-1, S, U)
 88         U.add(S.pop())  #removes the last item of an array
 89 
 90 # PuzzleSolver(3, [], {'a','b','c','d'})
 91 
 92 
 93 # R-4.6
 94 def sum_harmonic(n):
 95     if n == 1:
 96         return 1
 97     else:
 98         return sum_harmonic(n-1) + 1/n
 99 
100 # print(sum_harmonic(4))
101 
102 
103 # R-4.7
104 def transform_to_num(S):
105     num_list = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
106     # s = list(S)
107     # for i in s:
108     #     if i not in num_list:
109     #         s.remove(i)
110     # return int(''.join(s))
111 
112 
113 # ----------R4-7---------------------
114 """
115 Note, we can solve this by knowing that a number can be decomposed into:
116 a*1e0 + a2*1e1 + a3*1e2, etc...
117 
118 So 123 is
119 1*1 + 2*10 + 3*100
120 
121 """
122 
123 
124 def str_2_int(string, index=0):
125     length = len(string)
126     if index == length - 1:
127         return int(string[index])
128     else:
129         return int(string[index]) * 10 ** (length - index - 1) + str_2_int(string, index + 1)
130 
131 
132 """
133 This runs in 0(n) time and space
134 
135 """
136 
137 # ans = str_2_int('12342543')
138 # print(ans, type(ans))
139 
140 
141 # R-4.8
142 import math
143 
144 
145 def isabel_method(data):
146     n = len(data)
147     try:
148         assert math.log(n, 2) % 1 == 0
149     except AssertionError:
150         return '数据需要为2的幂'
151     if n == 1:
152         return data[0]
153     else:
154         B = [None] * (n // 2)
155         for i in range(len(B)):
156             B[i] = data[2*i] + data[2*i + 1]
157         return isabel_method(B)
158 
159 
160 # print(isabel_method([1, 2, 3, 4, 5, 6, 7, 8]))
161 
162 
163 # ---------------R4-8---------------------
164 import math
165 
166 
167 # def isabel_method(A):
168     # assert math.log(len(A), 2) % 1 == 0, 'Your array must be a length that is a power of 2'
169     # if len(A) == 1:
170     #     return A[0]
171     # else:
172     #     B = [None] * (len(A) // 2)
173     #     for i in range(len(B)):
174     #         B[i] = A[2 * i] + A[2 * i - 1]
175     #     return isabel_method(B)
176 
177 
178 """
179 The recursion will be called log(n) times, since the array is divided in half each time
180 
181 
182 Each call will require you to access all of the remaining elements, which means it will be
183 n + n/2 + n/4 + ...
184 
185 This is equal to n* Sum(1/2**i), which is <2n
186 
187 Therefore, the running time is O(n), although a much slower implementation than just adding them up element by element
188 
189 """
190 
191 # print(isabel_method([1, 2, 3, 4, 5, 6, 7, 8]))
192 # try:
193 #     print(isabel_method([1, 2, 3, 4, 5, 6, 7]))
194 # except Exception as e:
195 #     print(e)
巩固部分代码参考

创新

  1 # C-4.9
  2 import os
  3 
  4 
  5 def find_max_min_num(S, index=0):
  6     if index == len(S) - 1:
  7         return S[index], S[index]
  8     else:
  9         max_value, min_value = find_max_min_num(S, index+1)
 10         return max(S[index], max_value), min(S[index], min_value)
 11 
 12 #
 13 # test_S = [1, 2, 3, 5, 4, 7, 3]
 14 # max_val = find_max_min_num(test_S)
 15 # print(max_val)
 16 
 17 
 18 # C-4.10
 19 def find_log_int(num):
 20     if num // 2 < 1:
 21         return 0
 22     if num // 2 >= 1:
 23         return 1 + find_log_int(num // 2)
 24 
 25 
 26 # print(find_log_int(7))
 27 
 28 
 29 # C-4.11
 30 def confirm_unique(data):
 31     if len(data) == 1:
 32         return True
 33     else:
 34         if data[0] in data[1:]:
 35             return False
 36         else:
 37             return confirm_unique(data[1:])
 38 
 39 
 40 # print(confirm_unique([1, 2, 3, 4, 5, 6, 3]))
 41 
 42 
 43 # C-4.12
 44 def calculate_multiplication(m, n):
 45     if m == 1:
 46         return n
 47     else:
 48         return n + calculate_multiplication(m-1, n)
 49 
 50 
 51 # print(calculate_multiplication(3, 5))
 52 
 53 
 54 # C-4.14
 55 def han_nuo_ta(n):
 56     if n == 1:
 57         return 1
 58     else:
 59         return han_nuo_ta(n-1) + 1 + han_nuo_ta(n-1)
 60 
 61 
 62 # print(han_nuo_ta(5))
 63 
 64 
 65 # ---------C4-14-----------------------
 66 import time
 67 from IPython.display import clear_output
 68 
 69 
 70 class TowerOfHanoi():
 71     def __init__(self, n=4):
 72         self._n = n
 73         self._array = [[], [], list(reversed(range(n)))]
 74         self._lengths = [0, 0, n]
 75 
 76     def draw_towers(self):
 77         rows = []
 78         rows.append(['\t  1\t', '\t  2\t', '\t  3\t'])
 79         rows.append(['\t_____\t', '\t_____\t', '\t_____\t'])
 80         for i in range(max(self._lengths)):
 81             row = []
 82             for j in range(3):
 83                 if i < self._lengths[j]:
 84                     row.append('\t  ' + str(self._array[j][i]) + '\t')
 85                 else:
 86                     row.append('\t  \t')
 87             rows.append(row)
 88 
 89         for r in reversed(rows):
 90             print(''.join(r))
 91 
 92     def __getitem__(self, index):
 93         return self._array[index]
 94 
 95     def pop(self, index):
 96         self._lengths[index] -= 1
 97         return self[index].pop()
 98 
 99     def getlen(self):
100         return self._lengths
101 
102     def __setitem__(self, index, value):
103         if self[index] and self[index][-1] < value:
104             raise ValueError(f'Illegal move.  Cannot place block with size {value} on block {self[index][-1]}')
105         else:
106             self[index].append(value)
107             self._lengths[index] += 1
108 
109     def _move_stack(self, n_disks, start_peg, help_peg, target_peg):
110         time.sleep(0.5)
111         clear_output()
112         self.draw_towers()
113 
114         if n_disks == 1:
115             self._count += 1
116             value = self.pop(start_peg)
117             try:
118                 self[target_peg] = value
119             except Exception as e:
120                 print(e)
121                 self[start_peg]
122 
123         else:
124             # Move the upper stack to the helper peg
125             self._move_stack(n_disks - 1, start_peg, target_peg, help_peg)
126             # Move the lowest item to the target peg
127             self._move_stack(1, start_peg, help_peg, target_peg)
128             # Move the upper stack to the target peg
129             self._move_stack(n_disks - 1, help_peg, start_peg, target_peg)
130 
131     def solve_hanoi(self):
132         self._count = 0
133         self._move_stack(self.getlen()[2], 2, 1, 0)
134 
135         time.sleep(0.5)
136         clear_output()
137         self.draw_towers()
138 
139         print(f'\nThis took a total of {self._count} moves!')
140 
141 
142 # t = TowerOfHanoi(5)
143 # t.solve_hanoi()
144 
145 # ---------------C4-15-----------------------------
146 """
147 Here, we want combinations, not permutations
148 
149 
150 We rely on the addition of an empty set value 'UNK'
151 
152 For each stage of the recursion, we add one more value from the sequence
153 and for each current item either add another UNK or that value
154 
155 The final layer of that tree will contain exactly one copy of each unique set
156 
157 """
158 UNK = chr(1000)
159 
160 
161 def sub_rec(U, S):
162     """
163     U is the current set
164     S is the remaining sequence
165     """
166     if len(S) == 0:
167         print('{', str([x for x in U if x != UNK])[1:-1], '}')
168 
169     else:
170         val = S.pop()
171         U.append(UNK)
172         sub_rec(U, S)
173         U.pop()
174 
175         U.append(val)
176         sub_rec(U, S)
177         U.pop()
178         S.append(val)
179 
180 
181 def print_subsets(U):
182     sub_rec([], list(U))
183 
184 
185 # print_subsets({1, 2, 3, 4, 5})
186 
187 
188 # C-4.16
189 def reverse_str(word, index=0):
190     if index == len(word) - 1:
191         return [word[index]]
192     else:
193         ans = reverse_str(word, index+1)
194         ans.append(word[index])
195         if index == 0:
196             ans = ''.join(ans)
197         return ans
198 
199 
200 # print(reverse_str('abc'))
201 
202 
203 # C-4.17
204 def confirm_hui_str(word):
205     if len(word) == 1:
206         return True
207     else:
208         if word[0] != word[len(word)-1]:
209             return False
210         return confirm_hui_str(word[1:-1])
211 
212 
213 # print(confirm_hui_str('abacaba'))
214 
215 
216 # C-4.18
217 def confirm_vowel(word):
218     vowel_list = ['a', 'e', 'i', 'o', 'u']
219     if len(word) == 1:
220         if word[0] in vowel_list:
221             return 1
222         else:
223             return -1
224     elif word[0] in vowel_list:
225         return 1 + confirm_vowel(word[1:])
226     else:
227         return -1 + confirm_vowel(word[1:])
228 
229 
230 # print(confirm_vowel('abcdeae'))
231 
232 
233 # C-4.19(没有独立完成哈哈)
234 # def realign_num(data):
235 #     if len(data) == 1:
236 #         return data
237 #     elif data[0] % 2 == 1:
238 #         data.append(data.pop(0))
239 #         return data[:1] + realign_num(data[:-1])
240 #     else:
241 #         return data[:1] + realign_num(data[:-1])
242 #
243 
244 # print(realign_num([1, 2, 3, 4]))
245 
246 
247 # --------------C4-18-----------------
248 """
249 Approaches:
250 1) Two lists that you join at the end
251 2) Add new even numbers to the front and odd ones to the back
252 
253 
254 """
255 
256 
257 def evenoddbylists(S, index=0):
258     if index == len(S) - 1:
259         if len(S) == 1:
260             return S
261         elif S[index] % 2 == 0:
262             return [S[index]], []
263         else:
264             return [], [S[index]]
265     else:
266         evens, odds = evenoddbylists(S, index + 1)
267         if S[index] % 2 == 0:
268             evens.append(S[index])
269         else:
270             odds.append(S[index])
271         if index == 0:
272             return evens + odds
273         else:
274             return evens, odds
275 
276 
277 def evenoddbyappending(S, index=0):
278     if index == len(S) - 1:
279         return [S[index]]
280 
281     else:
282         if S[index] % 2 == 1:  # If odd, we want to add it to the end of the list
283             return evenoddbyappending(S, index + 1) + [S[index]]
284         else:
285             return [S[index]] + evenoddbyappending(S, index + 1)
286 
287 
288 # sequences = [[1, 2, 3, 4, 5, 6, 7, 8], [4, 3, 65, 23, 5, 46, 765, 3, 45, 23], [1], [2, 2]]
289 # print('Two lists approach')
290 # for s in sequences:
291 #     print(evenoddbylists(s))
292 #
293 # print('\n\nAdding each element approach')
294 # for s in sequences:
295 #     print(evenoddbyappending(s))
296 
297 """
298 Final notes: the second approach is not desirable with lists because it is O(n) due to the fact that
299 appending an entire list of length m to another requires O(m) time.  This could be solved with Linked Lists when 
300 we get to that part of the book
301 
302 
303 Note also that both answers are correct, but the numbers are in a different order
304 """
305 
306 
307 # C-4.20
308 # def sort_by_k(S, k, index=0):
309 #     if index == len(S) - 1:
310 #         return [S[index]]
311 #     else:
312 #         if S[index] <= k:
313 #             return [S[index]] + sort_by_k(S, k, index+1)
314 #         else:
315 #             return sort_by_k(S, k, index+1) + [S[index]]
316 
317 
318 # test_s = [1, 6, 5, 2, 3, 5, 7, 9, 11]
319 # print(sort_by_k(test_s, 5.5))
320 
321 def add_lists(a, b):
322     if a and b:
323         return a + b
324     else:
325         return b or a
326 
327 
328 def split_by_k(S, k, index=0):
329     if len(S) == 1:
330         return S
331     elif index == len(S) - 1:
332         if S[index] < k:
333             return [S[index]], [], []
334         elif S[index] > k:
335             return [], [], [S[index]]
336         else:
337             return [], [S[index]], []
338     else:
339         low, mid, high = split_by_k(S, k, index+1)
340         if S[index] < k:
341             low = add_lists(low, [S[index]])
342         elif S[index] > k:
343             high = add_lists(high, [S[index]])
344         else:
345             mid = add_lists(mid, [S[index]])
346         if index == 0:
347             return low + mid + high
348         else:
349             return low, mid, high
350 
351 
352 S_test = [1, 2, 3, 5, 6, 7, 8, 10, 12]
353 # print(split_by_k(S_test, 6))
354 
355 
356 # C-4.21
357 def find_sum(S, k, index1=0, index2=1):
358     if S[index1] + S[index2] == k:
359         return S[index1], S[index2]
360     elif index2 == len(S) - 1:
361         index1 += 1
362         index2 = index1 + 1
363         return find_sum(S, k, index1, index2)
364     else:
365         return find_sum(S, k, index1, index2+1)
366 
367 
368 # S_test = [1, 2, 3, 5, 6, 7, 8, 10, 12]
369 # print(find_sum(S_test, 22))
370 
371 
372 # ----------------C4-21----------------------
373 """
374 Note: there is a brute force approach, but we will use the one with dictionaries instead
375 
376 
377 Additional Note: I learned an important thing about using mutable objects as defaults in python
378 Successive calls used the growing key_set, rather than initializing it as set() every time.
379 
380 """
381 
382 
383 # The following line is the wrong way to do the initialization...
384 # def find_pair(S, target, key_set = set(), index=0):
385 
386 def find_pair(S, k, key_set=None, index=0):
387     if key_set is None:
388         key_set = set()
389     key = k - S[index]
390     if len(S) <= 1:
391         return None
392     elif index == len(S) - 1:
393         if key in key_set:
394             return key, S[index]
395         else:
396             return None
397     else:
398         if key in key_set:
399             return key, S[index]
400         else:
401             key_set.add(S[index])
402             return find_pair(S, k, key_set, index+1)
403 
404 
405 sequence = [1, 2, 3, 4, 5, 6, 7, 8]
406 
407 # for i in range(20):
408 #     print(f'For the value {i}, the resulting pair is {find_pair(sequence, i)}')
409 
410 
411 # C-4.22
412 def power_loop(x, n):
413     factor = n
414     partial = 1
415 
416     counter = 0
417     while factor:
418         factor = factor >> 1
419         counter += 1
420 
421     while counter + 1:
422         partial *= partial
423         if n >> counter & 1:
424             partial *= x
425         counter -= 1
426     return partial
427 
428 
429 # combos = [(2, 13), (2, 15), (3, 15), (10, 7), (2, 5)]
430 # for b, p in combos:
431 #     print('\n', power_loop(b, p), b ** p)
创新部分代码参考

项目

  1 # P-4.23
  2 import os
  3 
  4 
  5 def find(path, filename):
  6     abspath = os.path.join(path, filename)
  7     if os.path.isdir(abspath):
  8         for sub_filename in os.listdir(abspath):
  9             if os.path.isdir(os.path.join(abspath, sub_filename)):
 10                 find(abspath, sub_filename)
 11             else:
 12                 print(os.path.join(abspath, sub_filename))
 13 
 14 
 15 # find("F:", "工作总结")
 16 
 17 
 18 # P-4.24
 19 
 20 
 21 # ------------P4-24------------------
 22 """The ones we want to ultimately solve are:
 23 pot + pan = bib
 24 dog + cat = pig
 25 boy+ girl = baby
 26 """
 27 
 28 
 29 class SummationSolver:
 30     def __init__(self, a, b, c):
 31         self._a = a
 32         self._b = b
 33         self._c = c
 34         self._max_len = len(c)  # c cannot be shorter than a or b under the rules
 35         self._count = 0
 36 
 37     def _t2i(self, text, lookup):  # text to int
 38         total = 0
 39         length = len(text)
 40         for i in range(length):
 41             total += int(lookup[text[i]]) * 10 ** (length - i - 1)
 42 
 43         return total
 44 
 45     def summation_check(self, a, b, c, U):
 46         """
 47         a + b = c using the keys, value pairs in U
 48         """
 49         if self._t2i(a, U) + self._t2i(b, U) == self._t2i(c, U):
 50             self._count += 1
 51             print(
 52                 f'One solution is: {self._t2i(a, U)} + {self._t2i(b, U)} = {self._t2i(c, U)}.  Check:{self._t2i(a, U) + self._t2i(b, U)}')
 53             print('Dictionary is :', U)
 54             print('\n')
 55             return True
 56         else:
 57             return False
 58 
 59     def _solver_r(self, a, b, c, S, index, U, nums):
 60         if index >= len(S):  # Note, this means we are past the final index
 61             # print(U)
 62             return self.summation_check(a, b, c, U)
 63         elif S[index] in U:  # If the next letter in the sequence is already in the dictionary, skip it
 64             return self._solver_r(a, b, c, S, index + 1, U, nums)
 65         else:
 66             for number in nums.copy():
 67                 U[S[index]] = number
 68                 nums.remove(number)
 69                 ans = self._solver_r(a, b, c, S, index + 1, U, nums)
 70                 nums.add(number)
 71                 del U[S[index]]
 72 
 73     def solve(self):
 74         U = {}
 75         nums = set(range(10))
 76         S = list(self._a) + list(self._b) + list(self._c)
 77         self._count = 0
 78 
 79         self._solver_r(self._a, self._b, self._c, S, 0, U, nums)
 80 
 81         if self._count == 0:
 82             print('Sorry, no solution found! :(')
 83 
 84         else:
 85             print(f'There are a total of {self._count} solutions')
 86 
 87 
 88 # a = SummationSolver('pot', 'pan', 'bib')
 89 a = SummationSolver('boy', 'girl', 'babys')
 90 # a = SummationSolver('boy', 'girl', 'babysda')
 91 a.solve()
 92 
 93 
 94 # P-4.25
 95 def draw_interval(c):
 96     print(c * '-')
 97     for i in range(2**c-1):
 98         sum_1 = 1
 99         for j in bin(i)[::-1]:
100             if j == '1':
101                 sum_1 += 1
102             else:
103                 break
104         print(sum_1 * '-')
105     print(c * '-')
106 
107 
108 # draw_interval(3)
109 
110 
111 # ------------P4-25-------------------
112 """
113 The hint is that we should use a loop from 0 to 2**c -2
114 and that the number of ticks should be one more than the number of consecutive 1s.
115 
116 That's a great hint!
117 
118 """
119 
120 
121 def english_ruler(n=3, repeats=10):
122     limit = repeats * (2 ** n - 2)
123     counter = 0
124     while counter <= limit:
125         dashes = 1
126         sub_counter = counter
127         while sub_counter & 1:
128             dashes += 1
129             sub_counter = sub_counter >> 1
130         dashes = min(dashes, n)
131         print('-' * dashes)
132         counter += 1
133 
134 
135 # english_ruler(4, 3)
136 
137 
138 # ----------------P4-26-----------------------
139 """
140 Note, this was solved in C4-14
141 
142 """
143 
144 # t = TowerOfHanoi(6)
145 # t.solve_hanoi()
146 
147 
148 # P-4.27
149 def my_walk(path):
150     dirpath = path
151     dir_path_list = []
152     sub_path_list = []
153     if os.path.isdir(path):
154         for filepath in os.listdir(path):
155             if os.path.isdir(os.path.join(path, filepath)):
156                 dir_path_list.append(filepath)
157             else:
158                 sub_path_list.append(filepath)
159     return dirpath, dir_path_list, sub_path_list
160 
161 
162 # print(my_walk('F:\工作总结'))
项目部分代码参考

猜你喜欢

转载自www.cnblogs.com/xiaomingyang/p/12554518.html
今日推荐