Votre but est d'écrire un joueur parfait pour le jeu de Wythoff's Nim .
Les règles du Nim de Wythoff
Le Nim de Wythoff est un jeu déterministe à deux joueurs joué avec deux piles de jetons identiques. Les joueurs alternent les tours, au cours desquels ils effectuent l'une de ces actions:
- Retirez un ou plusieurs jetons de la première pile
- Retirez un ou plusieurs jetons de la deuxième pile
- Retirez un nombre égal de jetons (un ou plusieurs), à la fois de la première pile et de la deuxième pile.
Bien sûr, les piles ne peuvent pas devenir négatives, mais elles peuvent atteindre 0. Quel que soit le joueur qui enlève le dernier compteur, il gagne la partie.
Pour les plus géométriques, voici une formulation équivalente du jeu que vous pouvez jouer sur cette applet . Une seule reine commence sur un carré d'un échiquier quart infini dont le coin est en bas à gauche. Les joueurs alternent en déplaçant la reine, qui se déplace comme une reine d'échecs mais limitée à trois directions:
- Vers le bas
- La gauche
- En diagonale vers le bas et à gauche
Celui qui déplace la reine dans le coin gagne.
Associer les coordonnées de la reine (avec coin (0,0)
) aux tailles des piles respectives, il est facile de voir que les deux jeux sont identiques.
Jeu parfait
(Vous pouvez ignorer cela si vous êtes familier avec les notions de jeu parfait et de coups gagnants.)
Puisque le Nim de Wythoff est un jeu fini et déterministe, il a une notion de jeu parfait . Un joueur parfait est une stratégie qui gagnera toujours d'une position théoriquement gagnée, c'est-à-dire une position dans laquelle il existe une stratégie qui garantit une victoire.
Pour être une stratégie gagnante, il suffit de se déplacer pour toujours passer à une position gagnante théorique pour le joueur qui vient de bouger, et donc le joueur qui ne passe pas ensuite. Les premières de ces positions gagnantes (également appelées positions froides ) sont (0,0), (1,2), (2,1), (3,5), (5,3)
. Voir l'article Wikipedia pour une explication d'un algorithme pour trouver une stratégie gagnante pour le Nim de Wythoff, ainsi qu'une formule pour générer des positions gagnantes.
Exigences du programme
Écrire un programme ou une fonction prend une position en entrée et sort un coup gagnant sous la forme de la position après ce coup. Le moins d'octets gagne.
S'il n'y a pas de coup gagnant, c'est-à-dire que la position est une perte théorique, votre programme devrait l'indiquer et être annulé.
Votre programme doit s'exécuter dans un délai raisonnable. Ainsi, une recherche exponentielle récursive d'arbre de jeu ne suffira pas. Si vous souhaitez précalculer et coder en dur une stratégie, c'est très bien.
Contribution
Une paire (i,j)
de nombres non négatifs représentant au maximum la taille des tas 99
. Cela peut être deux nombres, un tuple, une liste ou tout autre conteneur que vous préférez.
Production
Imprimez ou affichez la position après votre déménagement, à nouveau sous la forme de deux chiffres ou d'un conteneur de celle-ci. Cela doit être un mouvement légal vers une position gagnante. S'il y a plusieurs de ces mouvements, tout le monde va bien, mais un seul.
S'il n'y a pas de coup gagnant, vous devez l'indiquer dans la sortie. Toute sortie comme False
, None
, 0, ou (-1,-1)
fera, aussi longtemps que ce n'est pas une situation juridique, et est la même pour chaque entrée perdante.
Exemple d'exécutions
f(5,0) = (0,0)
f(2,2) = (1,2) # Or (2,1) or (0,0)
f(1,2) = False
f(13,9) = (13,8) # Or (10,6)
f(10,6) = False
f(5,10) = (5,3)
f(25,30) = (8,13)
la source
Réponses:
Haskell,
167165 caractèresL'algorithme est inefficace, mais il s'exécute toujours dans une seconde (mais pas dans la console interactive) pour les entrées <100.
Explication:
La liste des positions froides pour un ensemble de positions froides précédentes est une position froide suivie de la liste des positions froides pour cette position et les précédentes (Inefficacité: cette position est générée deux fois)
Une position froide est la première paire de sorte qu'aucune position froide ne peut être atteinte à partir de cette paire (inefficacité: nous devrions plutôt rechercher à partir de la paire précédente)
Les positions accessibles à partir d'une paire sont celles telles que leurs premiers éléments correspondent, leurs seconds éléments correspondent, leurs différences correspondent ou le plus petit tas avant la suppression est le plus grand tas après la suppression.
(méthode principale) Si les tas sont dans le mauvais ordre, échangez-les. Sinon, si la première position froide accessible depuis une position est la position elle-même, indiquer l'échec (idéalement, on reviendrait à la
Maybe (Int,Int)
place). Sinon, retournez cette position froide (Inefficacité: ladite paire est recherchée deux fois. Pire, la liste des positions froides est générée deux fois)la source
x@
dex@(a,b)?p=...
GolfScript (
6357 octets)Attend l'entrée de stdin dans le formulaire
[a b]
et laisse la sortie sur stdout dans ce formulaire ou0
s'il s'agit d'une position perdante. Démo en ligneAperçu
calcule une liste de positions froides (y compris la version inversée
[b a]
pour chaque position froide[a b]
) à l'aide de la propriété de séquence Beatty .?
Recherche ensuite la première position froide satisfaisant le bloc créé parqui fondamentalement vérifie que la position est accessible à partir de la position d'entrée en calculant la différence de vecteur et ensuite vérifier qu'il est soit
[0 x]
,[x 0]
ou[x x]
pour certainsx > 0
. IMO ce test est le bit de plus habiles:0|$
forces toute matrice dans l' un de ces formats sous la forme[0 x]
tandis que la cartographie[0 0]
à[0]
,[a b]
où ni ,a
nib
est0
un réseau à trois éléments, et[-x 0]
ou[-x -x]
à[-x 0]
.(!*,1=
Vérifie ensuite que nous avons[0 x]
.Enfin,
0]0=`
le cas de secours et le formatage pour la sortie.la source
Pyth 57
58 61 62Essayez-le en ligne.
Assez similaire aux autres réponses, mais cette page wikipedia ne donnait pas grand-chose d'autre à faire;) Le nombre magique
39
est le nombre de positions froides avec des valeurs <99
.Définit une fonction
g
que vous pouvez appeler commeg 30 25
. Retourne[]
pour échec,[(13,8)]
en cas de succès.Explication
la source
s
est casté en int - sauvegarde quelques caractères/____1
.rZ39
peut être remplacé parU39
, en utilisant une plage unaire. De même, vous pouvez remplacerr99)
parU99
.U
. Je devrais vraiment mettre à jour l'explication: P@
effectuer l'intersection d'ensemble si son deuxième argument est maintenant une liste. C'est un peu maladroitement laissé de côté depuis lea
changement: PJavascript ES6 - 280 octets
Minifié
Étendu
Algorithme agréable et rapide. S'exécute en O (n), mais s'exécuterait en temps constant si ce n'était pour une boucle d'économie d'octets. La boucle est implémentée comme un incrémenteur récursif, donc le script échouera finalement avec une erreur de récursivité pour n dans les centaines ou les milliers. Utilise la même propriété de séquence Beatty que M. Taylor mentionne, mais plutôt que de calculer la séquence, elle passe simplement au (x) terme (s) correct (s).
Fonctionne correctement sur toutes les entrées de test et plusieurs dizaines en plus de celles que j'ai testées.
La fonction à invoquer est
f
. Il renvoie un tableau en cas de succès et un0
abandon.la source
Perl 5-109 (avec 2 drapeaux)
Usage:
Calcule simplement la solution pour chaque entrée possible, puis ne fait qu'une seule recherche.
la source