開発環境
- macOS Mojave - Apple (OS)
- Emacs (Text Editor)
- Windows 10 Pro (OS)
- Visual Studio Code (Text Editor)
- Python 3.7 (プログラミング言語)
問題解決のPythonプログラミング ―数学パズルで鍛えるアルゴリズム的思考 (Srini Devadas (著)、黒川 利明 (翻訳)、オライリージャパン)の8章(招かれざる客)、練習問題(問題1)を取り組んでみる。
コード(Emacs)
Python 3
#!/usr/bin/env python3 dislike_pairs = [['Alice', 'Bob'], ['Bob', 'Eve']] guests = [('Alice', 2), ('Bob', 6), ('Cleo', 3), ('Don', 10), ('Eve', 3)] def combinations(n: int, guests: list) -> list: all_combinations = [] for i in range(2 ** n): num = i combinations = [] for j in range(n): if num % 2 == 1: combinations = [guests[n - 1 - j]] + combinations num //= 2 all_combinations.append(combinations) return all_combinations def is_good(combination: list, name1: str, name2: str) -> bool: names = [name for name, _ in combination] return not (name1 in names and name2 in names) def remove_bad_combinations( all_combinations: list, dislike_pairs: list) -> list: all_good_combinations = [] for combination in all_combinations: good = True for a, b in dislike_pairs: if not is_good(combination, a, b): good = False break if good: all_good_combinations.append(combination) return all_good_combinations def get_weight(combination: list) -> int: return sum([weight for _, weight in combination]) def invite_dinner(guests: list, dislike_pairs: list) -> None: ''' メモリーの使用量を最適化していない版 >>> invite_dinner(guests, dislike_pairs) Optimum Solution: [('Bob', 6), ('Cleo', 3), ('Don', 10)] ''' all_combinations = combinations(len(guests), guests) all_good_combinations = remove_bad_combinations( all_combinations, dislike_pairs) invite = max(all_good_combinations, key=get_weight) print(f'Optimum Solution: {invite}') def invite_dinner_optimized(guests: list, dislike_pairs: list) -> None: ''' メモリーの使用量を最適化した版 >>> invite_dinner_optimized(guests, dislike_pairs) Optimum Solution: [('Bob', 6), ('Cleo', 3), ('Don', 10)] ''' n = len(guests) invite = [] invite_weight = 0 for i in range(2 ** n): num = i combination = [] for j in range(n): if num % 2 == 1: combination = [guests[n - 1 - j]] + combination num //= 2 good = True for a, b in dislike_pairs: if not is_good(combination, a, b): good = False break if good: weight = get_weight(combination) if weight > invite_weight: invite = combination invite_weight = weight print(f'Optimum Solution: {invite}') if __name__ == '__main__': import doctest doctest.testmod()
入出力結果(Terminal, cmd(コマンドプロンプト), Jupyter(IPython))
$ ./sample1.py -v Trying: invite_dinner(guests, dislike_pairs) Expecting: Optimum Solution: [('Bob', 6), ('Cleo', 3), ('Don', 10)] ok Trying: invite_dinner_optimized(guests, dislike_pairs) Expecting: Optimum Solution: [('Bob', 6), ('Cleo', 3), ('Don', 10)] ok 5 items had no tests: __main__ __main__.combinations __main__.get_weight __main__.is_good __main__.remove_bad_combinations 2 items passed all tests: 1 tests in __main__.invite_dinner 1 tests in __main__.invite_dinner_optimized 2 tests in 7 items. 2 passed and 0 failed. Test passed. $
0 コメント:
コメントを投稿