Das ist Code-Golf .
In dieser Herausforderung werden wir Programme / Funktionen schreiben, die " Knights and Knaves " -Puzzles lösen .
Hintergrund
Sie befinden sich auf einer Insel ... usw. ... jeder Mensch auf der Insel außer Ihnen ist entweder ein Ritter oder ein Schurke .
Ritter können nur wahre Aussagen machen.
Messer können nur falsche Aussagen machen.
Ich möchte "Aussage" nicht rigoros definieren, aber wir werden sagen, dass eine Aussage alles ist, was entweder "wahr" oder "falsch" ist. Beachten Sie, dass dies paradoxe Sätze ausschließt.
Für diese Herausforderung werden Sie auf Gruppen von Inselbewohnern treffen. sie werden dir gegenüber aussagen machen.
Ihre Aufgabe ist es, festzustellen, wer ein Ritter und wer ein Schurke ist.
Eingang:
Sie erhalten (in einem angemessenen Format) die folgenden Informationen:
Eine Liste der anwesenden Personen. Sie werden mit Großbuchstaben "AZ" benannt. Die dadurch auferlegte Personenanzahl wird nicht überschritten.
Die Aussagen, die jede Person macht. Im Folgenden finden Sie wichtige Details dazu.
Ausgabe
Sie werden dann (in jedem vernünftigen Format) ausgeben, was jede Person ist. Wenn zum Beispiel Spieler da wären A B C D
und A
ein Ritter ist, der Rest aber ein Schurke, könnten Sie ausgeben
A: 1
B: 0
C: 0
D: 0
Wichtige Details:
Großbuchstaben von AZ beziehen sich auf Inselbewohner.
Die Zeichen
0
(Null) und1
(Eins) beziehen sich jeweils auf einen "Knave" und einen "Knight". (Sie können zwei beliebige andere Zeichen als AZ verwenden, sofern Sie dies angeben.)Jeder anwesende Insulaner kann eine natürliche Anzahl von Aussagen machen oder sich dafür entscheiden, nichts zu sagen.
Die normalen logischen Operatoren können in Anweisungen verwendet werden ( IS *, AND, OR, NOT ). Darüber hinaus können die Gesetze und Bedingungen von De Morgan angewendet werden. Die folgenden Beispiele zeigen, wie sie in einem gesprochenen Puzzle dargestellt werden und wie sie in Ihr Programm eingegeben werden können.
(* eher technisch. Der Operator "IS" wird wirklich als Containment verwendet (was kein logischer Operator ist). Wenn ich "A ist ein Ritter" sage, meine ich wirklich "A ist ein Mitglied der Menge von" Knights ". Der wahre Operator wäre 'ϵ'. Der Einfachheit halber werden wir stattdessen '=' verwenden.)
Ich verwende Folgendes (Sie können alles verwenden, solange es vernünftig und konsistent ist):
^
UNDv
ODER=
IST~
NICHT=>
IMPLIZIERTX:
Person X behauptet, dass ...
Person Z kann eine beliebige Kombination der folgenden Aussagen treffen:
Person Z sagt, dass ...
Person A ist ein Ritter.
Z: A = 1
Person Q ist ein Schurke.
Z: Q = 0
Ich bin ein Ritter.
Z: Z = 1
Person A ist ein Ritter ODER Person B ist ein Ritter.
Z: ( A = 1 ) v ( B = 1)
Person C ist ein Ritter und ich bin ein Schurke.
Z: ( C = 1 ) ^ ( Z = 0 )
Person R ist KEIN Ritter.
Z: ~( R = 1 )
Darüber hinaus können für die Eingabe auch die Gesetze von De Morgan verwendet werden
Es ist NICHT wahr, dass sowohl Person A als auch Person B Schurken sind
Z: ~( ( A = 0 ) ^ ( B = 0 ) )
Es ist falsch, dass entweder Person A oder Person B ein Ritter ist
Z: ~( ( A = 1 ) v ( B = 1) )
Schließlich können Bedingungen und deren Negationen verwendet werden
Wenn ich ein Ritter bin, ist Person B ein Schurke
Z: ( Z = 1 ) => ( B = 0 )
Es ist NICHT wahr, dass, wenn Person B ein Ritter ist, Person C ein Schurke ist.
Z: ~( ( B = 1 ) => ( C = 0 ) )
Hinweise zu Bedingungen
Check out Wikipedia für weitere Informationen.
Eine bedingte Anweisung hat die Form p => q , wobei p und q selbst Anweisungen sind. p ist die "Vorgeschichte" und q ist die "Konsequenz". Hier finden Sie einige nützliche Informationen
Die Negation einer Bedingung sieht folgendermaßen aus: ~ (p => q) entspricht p ^ ~ q
Eine falsche Prämisse impliziert alles. Das heißt: Wenn p falsch ist, dann ist jede Aussage p => q wahr, unabhängig davon, was q ist. Zum Beispiel: "Wenn 2 + 2 = 5, dann bin ich Spiderman" ist eine wahre Aussage.
Einige einfache Testfälle
In diesen Fällen wird folgendermaßen angegeben (1), wie wir das Problem in der Sprache darstellen würden (2), wie wir es dem Computer darstellen könnten (3), welche Ausgabe der Computer möglicherweise korrekt ausgibt.
Person A und Person B nähern sich Ihnen unterwegs und machen folgende Aussagen:
A: B ist ein Schurke oder ich bin ein Ritter.
B: A ist ein Ritter.
Antworten:
B ist ein Ritter und A ist ein Ritter.
Eingang:
A B # Cast of Characters
A: ( B = 0 ) v ( A = 1)
B: A = 1
Ausgabe:
A = 1 B = 1
Personen A, B und F nähern sich Ihnen auf der Straße und geben die folgenden Aussagen ab:
A: Wenn ich ein Ritter bin, dann ist B ein Schurke.
B: Wenn das wahr ist, dann ist F auch ein Schurke.
Antworten:
A ist ein Ritter, B ist ein Knave, F ist ein Ritter.
Eingang
A B F
A: ( A = 1 ) => ( B = 0 )
B: ( A = 1 ) => ( F = 0 )
Ausgabe:
A = 1 B = 0 F = 1
Q, X und W nähern sich Ihnen auf der Straße und machen die folgenden Aussagen:
W: Es ist nicht wahr, dass sowohl Q als auch X Ritter sind.
F: Das stimmt.
X: Wenn das, was W sagt, wahr ist, dann ist das, was Q sagt, falsch.
Antworten:
W und Q sind Ritter. X ist ein Schurke.
Eingang
Q X W
W: ~( ( Q = 1 ) ^ ( X = 1 ) )
Q: W = 1
X: ( W = 1 ) => ( Q = 0 )
Ausgabe
W = 1 Q = 1 X = 0
Es gibt eine ähnliche Herausforderung von vor 3 Jahren, die sich auf das Parsen konzentriert und keine Bedingungen oder De Morgans enthält. Ich würde daher argumentieren, dass Fokus und Implementierung unterschiedlich genug sind, um zu vermeiden, dass dies ein Betrug ist.
Diese Herausforderung wurde kurzzeitig als Betrug abgeschlossen. Es wurde seitdem wieder geöffnet.
Ich behaupte, dass diese Herausforderung zunächst einmal einen anderen Schwerpunkt hat. Die andere Herausforderung konzentriert sich auf das Parsen in Englisch, dies jedoch nicht. Zweitens werden nur UND und ODER verwendet, wohingegen Bedingungen verwendet werden und das Lösen vieler weiterer Rätsel ermöglicht wird. Letztendlich stellt sich die Frage, ob Antworten aus dieser Herausforderung trivial durch Antworten aus dieser Herausforderung ersetzt werden können, und ich glaube, dass die Einbeziehung von Bedingungen und bedingten Negationen eine ausreichende Komplexität mit sich bringt, die robustere Änderungen erforderlich macht um dieser Herausforderung gerecht zu werden.
(B=1)=>(C=0)
?~((B=1)=>(C=0))
oder(B=1)=>(C=1)
oder was anderes?OR
, könnte es sein,A:1 B:1
oderA:1 B:0
weil BB=1
falsch sein könnte, während A noch wahr wäre.(B=1)^(C=1)
wie mit Bedingungen normalerweise umgegangen wirdAntworten:
Python 3,
450342307 BytesEdit: es stellt sich heraus, dass ich einen Import vergessen habe ...
Meine erste Lösung nutzt die flexible Benennung von Abfragen
Sie können die obige mit anrufen
Das nächste hier verwendet das gleiche Format von Abfragen wie im OP. Es enthält auch keine der Änderungen, die ich am ersten vorgenommen habe. Es ist 417 Bytes, da es zwischen den beiden Formaten konvertiert.
Und es kann aufgerufen werden von:
Sie kehren beide zurück
Ungolfed Erklärung:
Auch die zweite Lösung benötigt aufgrund der Verwendung von PEP 448 3,5 (nicht 3,4)
quelle
Mathematica, 80 Bytes
Erläuterung
Die Funktion
F
akzeptiert zwei Argumente:c
ist eine Liste aller Charakternamen,s
ist eine Liste von Aussagen, von denen jede zwei Teile enthält - wer sagt was.Zum Beispiel gibt es drei Zeichen, Q, X und W.
Und sie sagen:
wo
True
undFalse
bedeutet Ritter bzw. Knaves. Dannwird geben
{{q->True, x->False, w->True}}
, was bedeutet, dass es nur eine Lösung gibt, dass Q und W Ritter sind, während X ein Knave ist. Wenn es mehr als eine Lösung gibt, sieht die Ausgabe so aus{{...},{...},...}
Der Algorithmus ist sehr einfach.
{True,False}~Tuples~Length@c
gibt alle möglichen Kombinationen von Knights und Knaves unter den Charakteren an. Erstellen Sie dannThread[c->#]&/@
ein Array von Regeln, die auf diesen Kombinationen basieren. Im Fall von zwei Zeichen A und B ist das ArrayWenn Sie die Anweisungen durch eine Zeile dieser Regeln ersetzen, erhalten Sie ein Array, das wie folgt aussieht
Die erste Spalte dieses Arrays gibt die Identität der Sprecher an, und die zweite Spalte gibt an, ob ihre Aussagen wahr oder falsch sind. Eine gültige Lösung erfordert die Übereinstimmung der Identität der Sprecher mit ihren Aussagen. Das obige Array bedeutet, dass diese Kombination keine Lösung ist, da der zweite Sprecher, ein Ritter, eine falsche Aussage macht.
führt die Ersetzungen durch und wählt die Kombinationen aus, die die Bedingung erfüllen.
quelle
Rubin, 128
Dies ist der gleiche Algorithmus wie für alle anderen, probieren Sie alle möglichen Kombinationen von Schurken und Rittern und sehen Sie, welche Stöcke. Ich habe eine andere, an der ich arbeite, aber ich denke, sie wird länger dauern (wenn auch interessanter).
Die Anweisungseingaben müssen sein:
&
UND|
ODER==
IST!
NICHT>
IMPLIZIERTX:
Person X behauptet, dass ...Ich fordere auch, dass jede Anweisung und jede Unteranweisung in Klammern steht. Das einzige Problem bei dieser Version ist, dass sie höchstens 2 ^ 26 Iterationen durchläuft, und wenn sie nicht alle Knappen sind, mindestens 2 ^ (26-n) Iterationen ! In der Perspektive bedeutet dies, dass bei zwei Personen und mindestens einer Person, die kein Schurke ist, mindestens 16.777.216 Iterationen erforderlich sind !
Um dies einzuschränken, übermittle ich Folgendes mit 168 Bytes. Sub in
26
for#{o.size}
, um es auf 161 zurückzuschneiden.Aber wenn ich stattdessen eine Reihe von Personen und eine Karte von Aussagen verwenden kann, zB:
Dann kriege ich es auf 128 runter.
quelle