Qiita Teams that are logged in
You are not logged in to any team

Community
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What is going on with this article?
@ttatsf

# Python:嘘つき族と正直族をやってみた

More than 1 year has passed since last update.

``````import itertools

# プレーヤーとカードデッキと言い分から、矛盾のない答を返す
consistents = (
lambda players: lambda card_deck: lambda statements:
(
(hands, is_each_honest)
for hands in handss(card_deck)
for is_each_honest in is_each_honests
if  statements(hands) == is_each_honest
)
)
# それぞれのカードの手のタプルを返すジェネレータ
handss = lambda card_deck: itertools.permutations(card_deck)

# それぞれのプレーヤーが正直かどうか のタプルのタプル (決め打ち2)
is_each_honests = (
(True, False, False, True)
,(False, True, True, False)
)

# データ
players = (0, 1, 2, 3)
card_deck = (1, 2, 3, 4)

statements = lambda hands: (
hands[0] % 2 == 0
, hands[1] in (3, 4)
, hands[1] in (3, 4)    # (決め打ち1)
, hands[3] == 1
)

# 関数適用と表示
for e in consistents(players)(card_deck)(statements):
print(e)
``````
``````# 結果：
((1, 3, 2, 4), (False, True, True, False))
((1, 3, 4, 2), (False, True, True, False))
((1, 4, 2, 3), (False, True, True, False))
((1, 4, 3, 2), (False, True, True, False))
((3, 4, 1, 2), (False, True, True, False))
((4, 2, 3, 1), (True, False, False, True))
``````

### 決め打ち1：「Bは正直者」=>「Bの言ってることは正しい」=>Bの言ってること=>「Bのカードは3か4」 に変換

カードの手が決まればそれぞれの言い分の真偽が決まるので、問題がシンプルになります。

### 決め打ち2：嘘つき/正直は二人づつ=>BとCは同じ言い分=>BとCは同族=>AとDは逆の方の同族

``````>>> players = 0, 1, 2, 3
# 制約なし
>>> tuple( tuple( not e in liars for e in players ) for liars in itertools.combinations(players, 2))
((False, False, True, True), (False, True, False, True), (False, True, True, False), (True, False, False, True), (True, False, True, False), (True, True, False, False))    # 6 通り
>>> tuple( tuple( not e in liars for e in players ) for liars in itertools.combinations(players, 2) if liars in ((0,3),(1,2)))
((False, True, True, False), (True, False, False, True))    # 2 通り
``````

## もちょっと短く

してみます。

### 決め打ち1=>BとCをまとめる

BとCは 言い分 も 正直かどうか も一緒なので。

### 決め打ち2=>True/False にする

2通りしかないんだったら、タプルじゃなくて単純な論理値で表現できる。

``````import itertools

# プレーヤーとカードデッキと言い分から、矛盾のない答を返す
consistents = (
lambda players: lambda card_deck: lambda statements:
(
for hands in itertools.permutations(card_deck)
for is_AD_honest in (True, False)    # (決め打ち2)
)
)

# データ
players = (0, 1, 2, 3)
card_deck = (1, 2, 3, 4)

statements = lambda hands: (
hands[0] % 2 == 0
, hands[1] in (3, 4)    # (決め打ち1)
, hands[3] == 1
)

# 関数適用と表示
print(
)
``````

わかりやすいか はおいといて、ちょっと短くはなりました。

でも、そもそも...

# 決め打ちしすぎじゃない?

それぞれの言い分が違ったら(たとえば、Cが「Bは嘘つき」と言ったら)、決め打ちした部分は役に立たなくなります。いちからやりなおしです。

それぞれの言い分 `statements` の内容を書き換えても動きそうなものはこれです。

``````import itertools

# プレーヤーとカードデッキと言い分から、矛盾のない答を返す
consistents = (
lambda players: lambda card_deck: lambda statements:
(
(hands, is_each_honest)
for hands in handss(card_deck)
for is_each_honest in is_each_honests(players)
if  statements(hands) == is_each_honest
)
)
# それぞれのカードの手のタプルを返すジェネレータ
handss = lambda card_deck: itertools.permutations(card_deck)

# それぞれのプレーヤーが正直かどうか のタプルを返すジェネレータ
is_each_honests = lambda players:(
tuple( e in honests for e in players )
for honests in itertools.combinations(players, 2)
)

# データ
players = (0, 1, 2, 3)
card_deck = (1, 2, 3, 4)

statements = lambda hands: (
hands[0] % 2 == 0
, hands[1] in (3, 4)
, hands[1] in (3, 4)
, hands[3] == 1
)

# 関数適用と表示
for e in consistents(players)(card_deck)(statements):
print(e)
``````

ただし、決め打ち1 でやった 「人への言及 を カードの手に関する言い分に変換」するのは引き続き有効です。

2
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
1. We will deliver articles that match you
By following users and tags, you can catch up information on technical fields that you are interested in as a whole
2. you can read useful information later efficiently
By "stocking" the articles you like, you can search right away