読者です 読者をやめる 読者になる 読者になる

Knooooooooob

雑な自己満足を残していくブログ 年度によってテンションが違うっぽい

数学とプログラミングに弱い学生が論理パズルをPythonで解きたい話

これ楽しい

この本の名は?: 嘘つきと正直者をめぐる不思議な論理パズル

この本の名は?: 嘘つきと正直者をめぐる不思議な論理パズル

最近バイトでプログラム書いてない 

この本の名は?: 嘘つきと正直者をめぐる不思議な論理パズル

この本の名は?: 嘘つきと正直者をめぐる不思議な論理パズル

この問題をプログラミングで解こう!

てなわけで1問だけ挑戦する.

4人の被告 A,B,C,Dが関与していて次の事実が明らかになった.

  • (1) AとBが有罪ともに有罪なら,Cは共犯者だ.
  • (2) Aが有罪ならば,BかCの少なくとも一人が共犯者だ.
  • (3) Cが有罪ならば,Dは共犯者だ.
  • (4) Aが潔白ならば,Dは有罪だ.

確実に有罪なのは誰で,有罪かどうかを決められないのは誰か.

なるほど,さっぱりわからん.

とりあえず,考えてみると(1)~(4)の条件を回して矛盾が発生した場合の時そのパターンを取り除くみたいな感じが良さそう.

てなわけでソースコードを考える.

(1) AとBが有罪ともに有罪なら,Cは共犯者だ.

AとBが有罪なら,Cも有罪らしい. つまり,

if A.isGuilty && B.isGuilty:
    C.isGuilty = True

うーんなんかおかしい.これ矛盾が発生したときじゃなくて条件を満たしたときだよね.

こう直したほうが良さそう.

def jugge1(*args,**args)
    if A.isGuilty && B.isGuilty:
        if not C.isGuilty:
            break

これなら無視できそう.

以下(2)~(4)を同様の手順で考えると,

(2) Aが有罪ならば,BかCの少なくとも一人が共犯者だ.
def jugge2(*args,**args)
    if A.isGuilty:
        if not C.isGuilty or B.isGuilty:
            break
(3) Cが有罪ならば,Dは共犯者だ.
def jugge3(*args,**args)
    if C.isGuilty:
        if not D.isGuilty:
            break
(4) Aが潔白ならば,Dは有罪だ.
def jugge4(*args,**args)
    if not A.isGuilty:
        if not D.isGuilty:
            break

レッツコーディング

<被告>.isGuiltyって書いたけど普通に2進数でやったほうが早そう.

def jugge1(a,b,c):
    if a == 1 and b == 1:
        if c == 0:
            return True
def judge2(a,b,c):
    if a == 1:
        if b == 0 or c == 0:
            return True

def judge3(c,d):
    if c == 1:
        if d == 0:
            return True

def judge4(a,d):
    if a == 0:
        if d == 0:
            return True
ans = []
for i in range(16):
    beIgonored = [] #この中にTrueが無ければセーフ
    binary = "{0:0>4}".format(bin(i)).replace("b","0") #0000が 0b0ってなるのを変えてる
    binary = list(binary)
    while len(binary) < 4:
        binary.insert(0,"0") #0000が 0b0ってなるのを変えてる

    while len(binary) > 4:
        binary.pop(0)
    a,b,c,d = int(binary[-1]),int(binary[-2]),int(binary[-3]),int(binary[-4])
    beIgonored.append(jugge1(a,b,c))
    beIgonored.append(judge2(a,b,c))
    beIgonored.append(judge3(c,d))
    beIgonored.append(judge4(a,d))
    if not True in beIgonored:
        ans.append("".join(binary))

print(" _______________")
print("| D | C | B | A |")
print(" ───────────────")

for a in ans:
    print("| {} | {} | {} | {} |".format(a[0],a[1],a[2],a[3],))
print(" ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾")

クソコードすぎて辛いな??????????

結果

D C B A
1 0 0 0
1 0 1 0
1 1 0 0
1 1 1 0
1 1 1 1

真理値表

A~Dの中で有罪を1,潔白を0とする.

Zは矛盾が生じてない時に1,生じている時を0とする.

Mは条件(1)~(4)の中で条件を満たしたもの.

Nは条件(1)~(4)の中で矛盾が起きたものとする.

D C B A Z M N
0 0 0 0 0 ✖️ (4)
0 0 0 1 0 ✖️ (2)
0 0 1 0 0 ✖️ (4)
0 0 1 1 0 (2) (1)
0 1 0 0 0 ✖️ (3),(4)
0 1 0 1 0 (2) (3)
0 1 1 0 0 ✖️ (3)
0 1 1 1 0 (1),(2) (3)
1 0 0 0 1 (4) ✖️
1 0 0 1 0 ✖️ (2)
1 0 1 0 1 (4) ✖️
1 0 1 1 0 (1) (2)
1 1 0 0 1 (3),(4) ✖️
1 1 0 1 0 (2),(3) (1)
1 1 1 0 1 (3),(4) ✖️
1 1 1 1 1 (1),(2),(3) ✖️

あっなんかあってそう

つまり確実に有罪なのはDっぽい

コード書くより真理値表書くのが一番早いぞ!!!!!

クソコード書くの楽しかったおやすみなさい.