論理的思考パラドックス「天国への道」で天国へ行くためのプログラム

Youtubeでおもしろい論理的思考パラドックス(論理的思考パズル)を紹介している動画があったので、プログラムにしてみました。

確実に天国に行く方法を考えるというものです。
ジョジョプッチ神父みたいですね。

問題はこんな感じです。

あなたは死にました。

そして天国と地獄への道の分岐点にいます。
問題はどちらが天国への道かわからないということです。
一度進めば引き返せません。

二つの道にはそれぞれ天使がいます。
片方は正直天使、常に正直に答えます。
片方は嘘つき天使、常に嘘を答えます。
この天使たちもどちらが正直天使かはわかりません。

あなたは片方の天使にだけ一度のみ質問をすることができます。
質問は「はい」か「いいえ」で答えられるものでなければなりません。

この条件であなたは確実に天国への道を見つけられるでしょうか?

動画でも解説してくれています。

噓つき天使を悪魔とするパターンもあるようですが、動画では天使です。
理由は悪魔なら気まぐれに嘘をつくから。
なるほど。

youtu.be

答えを書いてしまうと、







「この道は天国への道ですか?」と聞かれたら「はい」と答えますか?

この質問をすれば天使が正直だろうが嘘つきだろうが、天国への道がわかります。

なぜそうなるかをプログラムにしてみました。
いや正直に言うとプログラムにして初めて理屈が理解できました。

Python 3.9~

from abc import abstractmethod

class Angel:
    @abstractmethod
    def answer(self, question: bool) -> bool:
        pass
    
class HonestyAngel(Angel):
    ''' 正直天使は常に正直 '''
    def answer(self, question: bool) -> bool:
        return question

class LierAngel(Angel):
    ''' 嘘つき天使は常に嘘つき '''
    def answer(self, question: bool) -> bool:
        return not question

def ask_the_question(angel: Angel, question: bool) -> bool:
    ''' 「この道は天国への道ですか?」と聞かれたら「はい」と答えますか? '''\
    first_answer = is_this_the_road_to_heaven(angel, question)
    return would_you_say_yes(angel, first_answer)

def is_this_the_road_to_heaven(angel: Angel, question: bool) -> bool:
    ''' 「この道は天国への道ですか?」 '''
    return angel.answer(question)

def would_you_say_yes(angel: Angel, question: bool) -> bool:
    ''' と聞かれたら「はい」と答えますか? '''
    return angel.answer(question)

def yes():
    print('はい')

def no():
    print('いいえ')
    

on_the_heaven_side = True # 天国
on_the_hell_side = False # 地獄

honesty_angel = HonestyAngel() # 正直天使
lier_angel = LierAngel() # 嘘つき天使

print('「この道は天国への道ですか?」と聞かれたら「はい」と答えますか?', end='\n\n')

print('天国側にいる正直天使に質問')
if ask_the_question(honesty_angel, on_the_heaven_side):
    yes()
else:
    no()

print('天国側にいる噓つき天使に質問')
if ask_the_question(lier_angel, on_the_heaven_side):
    yes()
else:
    no()

print('地獄側にいる正直天使に質問')
if ask_the_question(honesty_angel, on_the_hell_side):
    yes()
else:
    no()

print('地獄側にいる噓つき天使に質問')
if ask_the_question(lier_angel, on_the_hell_side):
    yes()
else:
    no()

「この道は天国への道ですか?」と聞かれたら「はい」と答えますか?
は実質的には2つの質問が合わさったものであり、嘘つき天使に2重の否定が入るのがポイントです。

正直天使の答えはずっと正直なので、何度質問されようと影響を受けません。

実行結果は

「この道は天国への道ですか?」と聞かれたら「はい」と答えますか? 

天国側にいる正直天使に質問
はい
天国側にいる噓つき天使に質問
はい
地獄側にいる正直天使に質問
いいえ
地獄側にいる噓つき天使に質問
いいえ

これで死後は確実に天国へ行けます!
プッチ神父くらいには確実に...