目次
はじめに
こんにちは、Yukkinです。
先日、Chihiroが出した論理パズル「論理包含の6兄弟」、皆さんは解きましたでしょうか。まだ解いていない人は、面白い問題ですのでぜひ考えてみてください。
解説は下の記事にあります。
この問題、私も考えてみましたが難しい問題でした……。
解説はエレガントに解いていますが、私は気合いで解いてみようと思います。
思考
この問題を考えるにあたり感じたこと。それは、6人を順番に並べる通り数は 6!=720 通りしかないということです。
6人の性別の組み合わせは20通りありますが、それを加味しても 720×20=14400 通りしかありません。14400通りくらいであれば、すべて試せば答えに辿り着くのではないか。気合いで解くと書いたのはそういうことです。
このような方法を全探索(または、力任せ探索)と呼びます。
【参考】力まかせ探索(Wikipedia)
とは言え、私が14400通り試していれば日が暮れますので、プログラム化します。
(気合いを入れるのは私ではなくPCということですね)
実装
import itertools
brothers = ["アキラ", "カオル", "サツキ", "タクミ", "ナギサ", "ハルカ"]
# 兄弟の並び順(全720通り)
brother_patterns = set(itertools.permutations(brothers))
sexs = [0, 0, 0, 1, 1, 1]
# 性別の組合せ(全20通り、0が男性、1が女性)
sex_patterns = set(itertools.permutations(sexs))
# 解答保存用list
brother_ans = []
sex_ans = []
# 兄弟check関数
# 「aの兄(姉)ならばbです」
def check(a, b, sex, brother_pattern, sex_pattern):
# aが何番目に並んでいるかを確認
index = brother_pattern.index(a)
# aより前にb以外の兄(姉)がいないかを調べる
for i in range(index):
if sex_pattern[i] == sex and brother_pattern[i] != b:
return False
return True
# 全探索
for brother_pattern in brother_patterns:
for sex_pattern in sex_patterns:
# 問題文の条件を満たすかcheck
if check("アキラ", "カオル", 0, brother_pattern, sex_pattern) \
and check("カオル", "サツキ", 0, brother_pattern, sex_pattern) \
and check("サツキ", "タクミ", 1, brother_pattern, sex_pattern) \
and check("タクミ", "ナギサ", 1, brother_pattern, sex_pattern) \
and check("ナギサ", "ハルカ", 0, brother_pattern, sex_pattern):
# 条件を満たせば、解答保存用listに追加する
brother_ans.append(brother_pattern)
sex_ans.append(sex_pattern)
# 解答保存用listの中身を出力
print(brother_ans)
print(sex_ans)
プログラム実行!
無事、答えを得ることができました。
最後に
この解法はずるいですか?
論理パズルらしい解き方は、Chihiroのこちらの記事を参考にしてください。
では、また!
アキラ,カオル,サツキ,タクミ,ナギサ,ハルカは年齢が異なる男3人女3人の兄弟姉妹です。
アキラの兄ならばカオルです。
カオルの兄ならばサツキです。
サツキの姉ならばタクミです。
タクミの姉ならばナギサです。
ナギサの兄ならばハルカです。
このとき、6人を年上から順に並べてください。