C'est du code-golf .
Dans ce défi, nous allons écrire des programmes / fonctions qui résolvent les puzzles " Knights and Knaves ".
Contexte
Vous vous retrouvez sur une île ... etc ... chaque personne sur l'île sauf vous est soit un chevalier soit un valet .
Les chevaliers ne peuvent que faire de véritables déclarations.
Les knaves ne peuvent faire que de fausses déclarations.
Je ne veux pas définir rigoureusement «déclaration», mais nous dirons qu'une déclaration est tout ce qui est «vrai» ou «faux». Notez que cela exclut les phrases paradoxales.
Aux fins de ce défi, vous rencontrerez des groupes d'insulaires; ils vous feront des déclarations.
Votre tâche consiste à déterminer qui est un chevalier et qui est un knave.
Contribution:
Vous recevrez (dans tout format raisonnable) les informations suivantes:
Une liste des personnes présentes. Ils seront nommés avec des caractères alphabétiques majuscules "AZ". La limite du nombre de personnes imposée par cela ne sera pas dépassée.
Les déclarations que chacun fait. Voir ci-dessous pour des détails importants à ce sujet.
Production
Vous afficherez ensuite (dans n'importe quel format raisonnable) ce que chaque personne est. Par exemple, s'il y avait des joueurs A B C D
et qu'il A
s'agit d'un chevalier, mais que les autres sont des chevaliers, vous pourriez produire
A: 1
B: 0
C: 0
D: 0
Détails importants:
Les caractères alphabétiques majuscules AZ désignent les insulaires.
Les caractères
0
(zéro) et1
(un) font respectivement référence à un "Knave" et à un "Knight". (Vous pouvez utiliser deux autres caractères non AZ, tant que vous spécifiez)Chaque insulaire présent peut faire un nombre naturel de déclarations, ou peut choisir de ne rien dire.
Les opérateurs logiques normaux peuvent être utilisés dans des instructions ( IS *, AND, OR, NOT ). En plus de cela, les lois et conditions de De Morgan peuvent être utilisées. Voici des exemples de la façon dont ils pourraient être présentés dans un puzzle parlé, suivis de la façon dont ils pourraient être introduits dans votre programme.
(* sur une note plus technique. L'opérateur "IS" est vraiment utilisé comme confinement (ce qui n'est pas un opérateur logique). Quand je dis "A est un chevalier", je veux vraiment dire "A est un membre de l'ensemble de Chevaliers ". Le véritable opérateur utilisé serait 'ϵ'. Par souci de simplicité, nous utiliserons plutôt '='.)
J'utilise ce qui suit (vous pouvez utiliser n'importe quoi, tant qu'il est raisonnable et cohérent):
^
ETv
OU=
EST~
NE PAS=>
IMPLIESX:
La personne X prétend que ...
La personne Z peut faire n'importe quelle combinaison de l'un des types de déclarations suivants:
La personne Z dit que ...
La personne A est un chevalier.
Z: A = 1
La personne Q est un Knave.
Z: Q = 0
Je suis chevalier.
Z: Z = 1
La personne A est un chevalier OU la personne B est un chevalier.
Z: ( A = 1 ) v ( B = 1)
La personne C est un chevalier ET je suis un chevalier.
Z: ( C = 1 ) ^ ( Z = 0 )
La personne R n'est PAS un chevalier.
Z: ~( R = 1 )
En plus de cela, l'entrée peut également utiliser les lois de De Morgan
Ce n'est PAS vrai que la personne A et la personne B sont des Knaves
Z: ~( ( A = 0 ) ^ ( B = 0 ) )
Il est faux que la personne A ou la personne B soit un chevalier
Z: ~( ( A = 1 ) v ( B = 1) )
Enfin, les conditionnelles et leurs négations peuvent être utilisées
Si je suis un chevalier, alors la personne B est un Knave
Z: ( Z = 1 ) => ( B = 0 )
Il n'est PAS vrai que si la personne B est un chevalier, alors la personne C est un chevalier.
Z: ~( ( B = 1 ) => ( C = 0 ) )
Remarques sur les conditions
Consultez wikipedia pour plus d'informations.
Une instruction conditionnelle prend la forme p => q , où p et q sont eux-mêmes des instructions. p est "l'antécédent" et q est le "conséquent". Voici quelques informations utiles
La négation d'une condition ressemble à ceci: ~ (p => q) est équivalent à p ^ ~ q
Une fausse prémisse implique n'importe quoi. C'est-à-dire: si p est faux, alors toute déclaration p => q est vraie, quel que soit q . Par exemple: "si 2 + 2 = 5 alors je suis Spiderman" est une vraie affirmation.
Quelques cas de test simples
Ces cas sont donnés de la façon suivante (1) comment nous poserions le problème dans la parole (2) comment nous pourrions le poser à l'ordinateur (3) la sortie correcte que l'ordinateur pourrait donner.
La personne A et la personne B vous approchent sur la route et font les déclarations suivantes:
A: B est un chevalier ou je suis un chevalier.
B: A est un chevalier.
Répondre:
B est un chevalier et A est un chevalier.
Contribution:
A B # Cast of Characters
A: ( B = 0 ) v ( A = 1)
B: A = 1
Production:
A = 1 B = 1
Les personnes A, B et F vous approchent sur la route et font les déclarations suivantes:
R: Si je suis chevalier, alors B est un Knave.
B: Si c'est vrai, alors F est aussi un Knave.
Répondre:
A est un chevalier, B est un chevalier, F est un chevalier.
Contribution
A B F
A: ( A = 1 ) => ( B = 0 )
B: ( A = 1 ) => ( F = 0 )
Production:
A = 1 B = 0 F = 1
Q, X et W vous approchent sur la route et font les déclarations suivantes:
W: Il n'est pas vrai que Q et X soient tous deux chevaliers.
Q: C'est vrai.
X: Si ce que W dit est vrai, alors ce que Q dit est faux.
Répondre:
W et Q sont des chevaliers. X est un Knave.
Contribution
Q X W
W: ~( ( Q = 1 ) ^ ( X = 1 ) )
Q: W = 1
X: ( W = 1 ) => ( Q = 0 )
Production
W = 1 Q = 1 X = 0
Il y a un défi similaire d'il y a 3 ans qui se concentre sur l'analyse et ne contient pas de conditions ni de De Morgan. Et donc, je dirais, est suffisamment différent dans la mise au point et la mise en œuvre pour éviter que cela ne soit dupe.
Ce défi a été brièvement clos en tant que dupe. Il a depuis été rouvert.
Je prétends que ce défi est d'abord différent. L'autre défi se concentre sur l'analyse syntaxique en anglais, ce n'est pas le cas. Deuxièmement, il utilise uniquement AND et OR alors que cela utilise des conditions et permet de résoudre de nombreux autres puzzles. À la fin de la journée, la question est de savoir si les réponses à ce défi peuvent être trivialement substituées à celle-ci, et je pense que l'inclusion des conditionnels et des négations conditionnelles ajoute une complexité suffisante pour que des changements plus robustes soient apportés afin pour relever ce défi.
(B=1)=>(C=0)
?~((B=1)=>(C=0))
ou(B=1)=>(C=1)
ou autre chose?OR
, cela pourrait êtreA:1 B:1
ouA:1 B:0
parce que les BB=1
pourraient être faux tandis que A serait toujours vrai.(B=1)^(C=1)
à la façon dont les conditions sont normalement traitéesRéponses:
Python 3,
450342307 octetsEdit: il s'avère que j'ai oublié une importation ...
Ma première solution profite d'une dénomination flexible pour les requêtes
Vous pouvez appeler celui-ci avec
Le suivant ici utilise le même format de requêtes que celui vu dans l'OP, il n'a pas non plus certaines des modifications que j'ai apportées au premier. Il est de 417 octets car il convertit entre les deux formats.
Et il peut être appelé par:
Ils reviennent tous les deux
Explication non golfée:
En outre, la deuxième solution nécessite 3,5 (et non 3,4) en raison de l'utilisation de PEP 448
la source
Mathematica, 80 octets
Explication
La fonction
F
prend deux arguments,c
est une liste des noms de tous les personnages,s
est une liste de déclarations, chacune contenant deux parties - qui dit quoi.Par exemple, il y a trois caractères, Q, X et W.
Et ils disent:
où
True
etFalse
signifie Chevaliers et Knaves respectivement. alorsdonnera
{{q->True, x->False, w->True}}
, ce qui signifie qu'il n'y a qu'une seule solution que Q et W sont des chevaliers tandis que X est un Knave. S'il existe plusieurs solutions, la sortie ressemblera à{{...},{...},...}
L'algorithme est très simple.
{True,False}~Tuples~Length@c
donne toutes les combinaisons possibles de chevaliers et de knaves parmi les personnages.Thread[c->#]&/@
Construisez ensuite un tableau de règles basé sur ces combinaisons. Dans le cas de deux caractères A et B, le tableau seraEn remplaçant les instructions par une ligne de ces règles, nous obtiendrons un tableau comme
La première colonne de ce tableau est l'identité des locuteurs, et la deuxième colonne indique si leurs déclarations sont vraies ou fausses. Une solution valable nécessite la concordance entre l'identité des locuteurs et leurs déclarations. Le tableau ci-dessus signifie que cette combinaison n'est pas une solution, car le deuxième haut-parleur, un Knight, fait une déclaration incorrecte.
effectue les substitutions et sélectionne les combinaisons qui satisfont à la condition.
la source
Rubis, 128
C'est le même algorithme que tout le monde, essayez toutes les combinaisons possibles de chevaliers et de chevaliers et voyez quels bâtons. J'en ai un autre sur lequel je travaille, mais je pense que ce sera plus long (bien que plus intéressant).
Les entrées de l'instruction doivent être:
&
ET|
OU==
EST!
NE PAS>
IMPLIESX:
La personne X prétend que ...J'exige également que chaque instruction et sous-instruction soit entre parenthèses. Le seul problème avec cette version est qu'elle passe par 2 ^ 26 itérations au maximum, et si ce ne sont pas tous des knaves, au moins 2 ^ (26-n) itérations ! Pour mettre cela en perspective, cela signifie que s'il y a deux personnes, et au moins une n'est pas un valet, cela prendra un minimum de 16 777 216 itérations !
Pour limiter cela, je soumets ce qui suit à 168 octets. Remplacez-le
26
pour#{o.size}
le ramener à 161.Mais si je peux utiliser à la place un tableau de personnes et une carte d'instructions, par exemple:
Ensuite, je descends à 128.
la source