โค้ดกอล์ฟ: แก้ปัญหาตรรกะของ Knights and Knaves โดยการแยกวิเคราะห์ภาษาอังกฤษ


16

พื้นหลัง

มีสองคนคือบิลและจอห์น หนึ่งในนั้นคืออัศวินที่มักพูดความจริงเสมอและอีกคนหนึ่งเป็นอัศวินซึ่งมักพูดโกหก คุณไม่รู้ว่าใครเป็นอัศวินและใครเป็นอัศวิน จากนั้นแต่ละคนก็พูดหลายประโยคว่าใครเป็นคนอัศวินและใครเป็นอัศวิน การใช้ข้อมูลนี้คุณจะต้องสรุปว่าใครเป็นอัศวินและผู้ที่เป็นอัศวิน

อัศวินและคนพาลปัญหาตรรกะจะขึ้นอยู่กับ Booleen พีชคณิต คำที่คนพูดว่าก่อให้เกิดปัญหาความพึงพอใจ Booleen แถลงการณ์ของผู้พิพากษาต้องเป็นเท็จเสมอและข้อความของอัศวินอื่น ๆ จะต้องเป็นจริงเสมอ

จอห์นบอกว่า "ทั้งฉันเป็นคนคุกเข่าและบิลก็เป็นคนคุกเข่า" หากจอห์นเป็นอัศวินแล้วคำพูดนี้จะเป็นเท็จดังนั้นเขาจึงไม่สามารถเป็นอัศวิน หากเขาเป็นผู้คุกและ Bill เป็นอัศวินแถลงการณ์นี้จะยังคงเป็นเท็จแม้แต่คิดว่าส่วนแรกเป็นจริง ดังนั้นจอห์นเป็นคนคุกเข่า

ความท้าทาย

ความท้าทายของคุณคือการเขียนโปรแกรมที่สั้นที่สุดเท่าที่จะเป็นไปได้ซึ่งจะเขียนรายการคำแถลงของแต่ละคนและจะคิดออกว่าใครคือผู้เป็นอัศวินและใครเป็นอัศวิน มีรายละเอียดมากมายที่จะครอบคลุมดังนั้นปัญหานี้ได้อธิบายไว้ในสามส่วน

อินพุต

อินพุตจะเป็นสองบรรทัดตามด้วยขึ้นบรรทัดใหม่ แต่ละบรรทัดจะให้ชื่อของตัวละครหนึ่งตัวตามด้วยเครื่องหมายจุดคู่ตามด้วยประโยคหลายประโยคที่บุคคลนั้นพูด ถ้าคนคนหนึ่งเป็นอัศวินแล้วประโยคทั้งหมดของเขาจะเป็นจริงและประโยคทั้งหมดของอัศวินจะเป็นเท็จ อักษรตัวแรกของประโยคจะเป็นตัวพิมพ์ใหญ่เสมอและทุกประโยคจะลงท้ายด้วยจุด นี่คือตัวอย่าง:

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.

วจีวิภาค

แต่ละประโยคประกอบด้วยประโยคอย่างน้อยหนึ่งประโยค แต่ละประโยคมีหนึ่งในหลาย ๆ สิ่ง (หวังว่าคุณจะเข้าใจสัญลักษณ์ของฉัน):

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

นี่เป็นเรื่องที่ไม่น่าเชื่อเพราะสามารถเข้าใจได้ในลักษณะที่คล้ายคลึงกับสัญกรณ์โปแลนด์ นี่คือตัวอย่างของประโยค:

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

การแปลเป็นพีชคณิตแบบบูลนั้นตรงไปตรงมา คำสั่ง "ทั้งสอง" เป็น ANDs คำสั่ง "ทั้ง" เป็น XOR และคำสั่ง "ไม่ใช่" เป็น NOR

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

เอาท์พุต

เอาต์พุตจะประกอบด้วยสองบรรทัด แต่ละบรรทัดประกอบด้วยชื่อของบุคคล (เรียงตามลำดับ) จากนั้นบอกว่าเขาเป็นอัศวินหรือผู้กล้า จะมีหนึ่งอัศวินและหนึ่งอัศวินเสมอ นี่คือผลลัพธ์สำหรับตัวอย่างข้างต้น:

Joe is the knave.
Steve is the knight.

หากปัญหาไม่สามารถแก้ไขได้ (คุณไม่สามารถบอกได้ว่าใครเป็นใครหรือไม่มีวิธีแก้ไข) จากนั้นโปรแกรมของคุณสามารถทำทุกอย่างยกเว้นสร้างผลลัพธ์ที่ถูกต้อง

ตัวอย่างเพิ่มเติม

อินพุต

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.

เอาท์พุต

Sir Lancelot is the knight.
Merlin is the knave.

อินพุต

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.

เอาท์พุต

David is the knave.
Patrick is the knight.

อินพุต

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

เอาต์พุตหนึ่งรายการที่เป็นไปได้

Rock Paper Scissors

กฎระเบียบและบันทึก

  1. บังคับใช้กฎกอล์ฟมาตรฐาน
  2. โปรแกรมของคุณต้องประกอบด้วย ASCII ที่พิมพ์ได้เท่านั้น
  3. อินพุตและเอาต์พุตทั้งหมดมาจาก STDIN และ STDOUT

สิ่งที่เกี่ยวกับความไวกรณี? คำอธิบายไวยากรณ์ของคุณเป็นตัวพิมพ์เล็กตัวอย่างของคุณเป็นตัวพิมพ์ใหญ่ กรณีไม่ตอบสนองความต้องการหรือไม่?
ugoren

อักษรตัวแรกของแต่ละประโยคจะเป็นตัวพิมพ์ใหญ่ แต่จะใช้ตัวพิมพ์ใหญ่เท่านั้น คุณเห็นปัญหาอะไรเป็นพิเศษ
PhiNotPi

เนื่องจากคุณใช้การใช้อักษรตัวพิมพ์ใหญ่ภาษาอังกฤษที่เหมาะสมตัวอักษรตัวแรกในทั้ง / / / ไม่ขึ้นกับบริบท ฉันคิดว่าการใช้ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่เป็นวิธีที่ง่ายในการจัดการกับมัน
ugoren

คำตอบ:


6

Python 491 ตัวอักษร

ทำงานโดยแปลงแต่ละบรรทัดเป็นนิพจน์ Python และสร้างความแปลกใหม่
อัศวินและอัศวินได้รับการประเมินเป็น 0 และ 1 สำหรับคนสองคนเราลองทั้งสองตัวเลือก
ยกตัวอย่างเช่นจะกลายเป็นJoe: Steve is a knave Joe==(Steve==knave)ด้วยวิธีนี้ถ้าJoeเป็นคนคุกเข่าผลที่ได้จะเป็นจริงก็ต่อเมื่อเขาโกหก
คุณได้รับข้อผิดพลาดที่น่าเกลียดเมื่อเป็นไปไม่ได้หรือไม่แน่ใจ หากเป็นไปไม่ได้r[0]เป็นข้อผิดพลาดของดัชนีเนื่องจากrไม่มีข้อมูล หากไม่สามารถตัดสินใจได้การต่อr[1:]กับรายการสตริงจะทำให้เกิดปัญหา

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 ตัวอักษร

วิธีแก้ปัญหาค่อนข้างยาวดังนั้นอาจมีบางสถานที่สำหรับเล่นกอล์ฟ ต้องป้อนข้อมูลให้มีรูปแบบที่ดี (ตามตัวอย่างข้างต้นทั้งหมด - แต่อย่าพยายามตั้งชื่อบุคคล "ทั้งสอง" ... )

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]]

ดูเหมือนว่าคุณจะออกจากช่วงเวลาในผลลัพธ์ แต่ดูเหมือนว่าการแก้ไขอักขระสองตัว
PhiNotPi

1
@PhiNotPi เรียบร้อยแล้ว เป็นการแก้ไขที่ไม่มีอักขระ ...
โฮเวิร์ด

0

Perl - 483 ไบต์

(($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 จะช่วยลดประโยคให้กับรหัส Perl แล้วevalพวกเขา มันสามารถพิมพ์เอาต์พุตเกือบจะใช้ได้ถ้าอินพุตแปลก แต่ไม่พิมพ์อะไรเลยถ้ามันไม่สามารถตัดสินใจได้ อินพุตที่มีรูปแบบที่ดีทำงานตามที่คาดไว้ ประโยคถูกส่งผ่านไปในบรรทัดคำสั่งภายในเครื่องหมายคำพูดและไม่จำเป็นต้องมีการตั้งค่าสถานะพิเศษ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.