開発環境
- 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 コメント:
コメントを投稿