クレタ人が真実の情報を知っています。
簡単のために情報は2値(Boolean)で、情報の数は本質ではないので今回は1つだけとします。
クレタ人.それは正しい()メソッドを通じてクレタ人に情報をたずねることができます。
真(True)か偽(False)で返答が返ってきます。
ところが、クレタ人には正直者とうそつきがいます。事前にはわかりません。
正直者は情報が真なら真、偽なら偽と答えます。
うそつきは情報が真なら偽、偽なら真と答えます。#うそつきというよりひねくれものなのかも…
さて正しい情報を得るためにまず正直者かどうか確認しなければなりません。
「あなたは正直者ですか?」(それは正しい("私は正直である"))を使ってたずねると
もちろん常に「True」が返ってきてしまいます。
以下の「それは正しい」メソッドの引数をどのようにすれば、正直者かうそつきを見破れるのでしょうか?
※答え合わせ用の「正直者かどうかの正解」メソッドは本来無い物だと思ってください。
※正解は1通りではありません。
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
public class クレタ人
{
private static Random _random = new Random();
private bool _正直;
private bool[] _情報;
public static クレタ人 Create() {
クレタ人 ins = new クレタ人(
_random.Next(2) == 0,
new bool[] {
_random.Next(2) == 0 ,//簡単のため情報は1つだけ
});
return ins;
}
private クレタ人(bool 正直, bool[] 情報)
{
this._正直= 正直;
this._情報= 情報;
}
private bool 私は正直である()
{
return _正直;
}
private bool その情報は正しい(int index)
{
return _情報[index];
}
public bool それは正しい(string methodName, params object[] args)
{
return !_正直^ (bool)typeof(クレタ人).InvokeMember(methodName,
BindingFlags.NonPublic
| BindingFlags.Public
| BindingFlags.Instance
| BindingFlags.InvokeMethod
, null, this, args);
}
//答え合わせ用メソッド
public static string 正直者かどうかの正解(クレタ人 cretan)
{
return string.Format("実はこのクレタ人は{0}", cretan._正直? "正直者" : "うそつき");
}
}
class Program
{
static void Main(string[] args)
{
クレタ人 c1 = クレタ人.Create();
Console.WriteLine("情報[0]は正しい? → {0}", c1.それは正しい("その情報は正しい", 0));
Console.WriteLine("正直ものですか? → {0}", c1.それは正しい("私は正直である"));//必ずTrueが返ってきてしまう。
// Console.WriteLine("正直ものですか? → {0}", c1.それは正しい(????????????????????????????????));//どうすれば正直者かどうかの正しい答えが返ってくるか?
Console.WriteLine(クレタ人.正直者かどうかの正解(c1));//答え合わせ用
}
}
ネタ元↓
クレタ人のパラドックス(凪瀬さんの凪瀬 Blog)より
http://blogs.wankuma.com/nagise/archive/2007/08/07/89144.aspx
解答編↓
[思いつき論理クイズ]正直者、うそつきを見破るには?(解答編)
http://blogs.wankuma.com/iijimas/archive/2007/11/08/107089.aspx