Kod golf: İngilizce çözümleyerek bir Şövalyeler ve Knaves mantık problemini çözün


16

Arka fon

İki kişi var, Bill ve John. Bunlardan biri her zaman gerçeği söyleyen bir şövalye, diğeri ise her zaman yalan söyleyen bir knave. Şövalyenin kim olduğunu ve dizlerin kim olduğunu bilmiyorsun. Daha sonra her kişi kimin knave kimin şövalye olduğu hakkında birkaç açıklama yapar. Bu bilgileri kullanarak şövalyenin kim ve kimin knave olduğu hakkında bir sonuca varmalısınız.

Şövalyeler ve Knaves mantık problemi Booleen cebir dayanmaktadır. Bir kişinin söylediği kelimeler Boole memnuniyeti sorunudur. Knave'nin ifadeleri her zaman yanlış olmalı ve diğer şövalyenin ifadeleri her zaman doğru olmalıdır.

John, "Hem ben de knave'yim, Bill de knave" diyor. Eğer John şövalye olsaydı, bu ifade yanlış olurdu, bu yüzden şövalye olamaz. Eğer knave olsaydı ve Bill şövalye olsaydı, ilk kısım doğru olsa bile, bu ifade hala yanlış olurdu. Yani, John knave.

Meydan okuma

Zorluğunuz, her bir kişi tarafından yapılan açıklamaların bir listesini alacak ve kimin knave kimin şövalye olduğunu anlayabilecek en kısa programı yazmaktır. Ele alınacak çok fazla ayrıntı var, bu nedenle bu sorun üç bölümde açıklanmıştır.

Giriş

Girdi iki satırdan sonra bir satırsonu olacaktır. Her satır, karakterlerden birinin adını, ardından iki nokta üst üste işaretini ve o kişi tarafından söylenen birkaç cümleyi verecektir. Eğer bir kişi şövalye ise, o zaman tüm cümleleri doğru olur ve tüm knave cümleleri yanlış olur. Bir cümlenin ilk harfi daima büyük harfle yazılır ve her cümle bir nokta ile biter. İşte bir örnek:

Joe: Both I am a knight and neither Steve is a knave nor I am a knave.
Steve: Joe is a knave. Either Joe is a knight or I am a knight.

ayrıştırma

Her cümle en az bir maddeden oluşur. Her fıkra birkaç şeyden birini içerir (umarım gösterimi anlayabilirsiniz):

both [clause] and [clause]
either [clause] or [clause]
neither [clause] nor [clause]
[I am | (other person's name) is] a [knight | knave]

Bu, Polonyalı gösterime benzer bir şekilde anlaşılabildiğinden, dinsizdir. İşte bir cümle örneği:

Both I am a knight and neither Steve is a knave nor I am a knave.

Booleen cebirine çeviri kolaydır. "Her ikisi de" ifadeleri AND, "iki" ifadesi XOR ve "hiçbiri" ifadesi NOR'dur.

(I am a knight) AND ((Steve is a knave) NOR (I am a knave))

Çıktı

Çıktı iki satırdan oluşacaktır. Her satır bir kişinin isminden (sırayla) oluşur ve daha sonra şövalye mi yoksa knave mi olduğunu söyler. Her zaman bir şövalye ve bir knave olacak. Yukarıdaki örnek için çıktı:

Joe is the knave.
Steve is the knight.

Sorun çözülemiyorsa (ya kimin ne olduğunu söyleyemezsiniz ya da çözüm yoktur), o zaman programınız geçerli bir çıktı üretmek DIŞINDA her şeyi yapabilir.

Daha fazla örnek

Giriş

Sir Lancelot: Either both I am a knight and Merlin is a knave or both I am a knave and Merlin is a knight.
Merlin: Either both I am a knight and Sir Lancelot is a knight or both I am a knave and Sir Lancelot is a knave.

Çıktı

Sir Lancelot is the knight.
Merlin is the knave.

Giriş

David: Neither I am a knave nor Patrick is a knight. Either I am a knight or Patrick is a knave.
Patrick: Either I am a knight or both I am a knight and David is a knight.

Çıktı

David is the knave.
Patrick is the knight.

Giriş

Lizard: I am a knight.
Spock: I am a knave.

Bir olası çıktı

Rock Paper Scissors

Kurallar, Yönetmelikler ve Notlar

  1. Standart kod golf kuralları geçerlidir
  2. Programınız yalnızca yazdırılabilir ASCII'den oluşmalıdır
  3. Tüm giriş ve çıkışlar STDIN ve STDOUT'tan olacaktır

Vaka duyarlılığı ne olacak? Sözdizimi açıklamanız küçük harf, örnekleriniz büyük harf. Büyük / küçük harf duyarsızlığı bir gereklilik mi?
ugoren

Her sentasyonun ilk harfi büyük yazılır, ancak bunun dışında yalnızca isimler büyük harfle yazılır. Hangi spesifik sorunu görüyorsunuz?
PhiNotPi

Doğru İngilizce büyük harf kullandığınız için, her ikisinde de / her ikisinde de ilk harf bağlama bağlıdır. Sanırım büyük / küçük harfe duyarsız olmak bununla başa çıkmanın kolay yoludur.
ugoren

Yanıtlar:


6

Python, 491 karakter

Her satırı bir Python ifadesine dönüştürerek ve değerlendirerek çalışır.
Knave ve şövalye 0 ve 1 olarak değerlendirilir. İki kişi için her iki seçeneği de deneriz.
Örneğin, Joe: Steve is a knaveolur Joe==(Steve==knave). Bu şekilde, eğer Joebir knave ise, sonuç sadece yalan söylerse doğrudur.
İmkansız veya kararsız olduğunda çirkin hatalar alırsınız. İmkansızsa, r[0]bir dizin hatasıdır, çünkü rboştur. Kararsızsanız, r[1:]bir dize listesine birleştirmek soruna neden olur.

import sys
def p():
    a=s.pop(0)
    try:return{"both":"(%s*%s)","either":"(%s|%s)","neither":"(1-(%s|%s))"}[a.lower()]%(p(),p())
    except KeyError:r=s[2];del s[:4];return"(%s==%s)"%((a,m)[a=="I"],r)
x=[];w=[]
for l in sys.stdin:
    m,l=l.split(":");w+=[m]
    for s in l.split("."):
        s=s.split()
        while s:x+=["%s==%s"%(m,p())]
k=("knave","knight")
r=[a for a in[{w[0]:z,w[1]:1-z}for z in(0,1)]if all(eval(l,{k[0]:0,k[1]:1},a)for l in x)]
print"\n".join(x+" is the "+k[r[0][x]]+"."for x in w+r[1:])

3

Ruby, 352 karakter

Çözüm oldukça uzadı, bu yüzden hala golf için bir yer olabilir. Girdinin iyi biçimlendirilmesini gerektirir (yukarıdaki tüm örnekler olduğu gibi - ancak bir kişiye "Her ikisi de" ... adını vermeye çalışmayın).

q=->{gets.split /: |\.\s/}
C,*E=q[]
D,*F=q[]
r=->c,m{t=c.shift;t[1]?(x=r[c,m];c.shift;y=r[c,m];t[0]==?B?x&y :t[0]==?E?x^y :1-(x|y)):(c.shift(2);h=c.shift[2]==?I?m : 1-m;t==?I?h :1-h)}
s=->u,v,b{u.map{|c|r[c.gsub(v,?J).upcase.split,b]==b}.all?}
t=->b{s[E,D,b]&&s[F,C,1-b]}
u=->v,b{v+" is the kn#{b ?:ight: :ave}."}
puts t[1]^t[0]&&u[C,t[1]]+$/+u[D,t[0]]

Çıktıdaki dönemleri bırakmış gibi görünüyorsunuz, ancak iki karakterli bir düzeltme gibi görünüyor.
PhiNotPi

1
@PhiNotPi Tamamlandı. Sıfır karakter düzeltmesi yapıldı ...
Howard

0

Perl - 483 bayt

(($a,$b),($c,$d))=map{split':'}@ARGV;$h='y';$i='x';$s=' is the kn';$g='ight.';$v='ave.';for($b,$d){$_.=' 1';s/ am a | is a /==/g;s/knight/1)/g;s/knave/0)/g;s/I=/(\$$i=/g;s/($a|$c)=/(\$$h=/g;s/([^.]+)\./($1)and/g;s/ or / xor /g;s/ nor / or /g;while(s/(?<= )(\w+ \((?:[^()]+|(?1))\) \w+ \((?:[^()]+|(?1))\))/($1)/g){}s/neither/!/gi;s/both|either//gi;$h=$i++}$x=0;$y=1;$k=!eval($b)&&eval($d);$x=$y--;$n=!eval($d)&&eval($b);print"$a$s$v
$c$s$g"if($k&&!$n);print"$a$s$g
$c$s$v"if($n&&!$k)

Python çözümüne benzer. Cümleleri Perl koduna indirir ve sonra evalbunları s. Giriş garip ise neredeyse geçerli çıktı yazdırabilir, ancak kararsızsa hiçbir şey yazdırmaz. İyi biçimlendirilmiş girdi beklendiği gibi çalışır. Cümleler komut satırında tırnak içine alınır ve özel bayrak gerekmez.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.