Évaluation du score à partir d'une chaîne d'échecs FEN


17

Défi

La notation Forsyth – Edwards (FEN) est une notation standard pour décrire une position particulière du plateau d'une partie d'échecs. Votre défi consiste à évaluer le score à l'aide de la chaîne FEN. Voici un exemple de chaîne FEN:

5k2/ppp5/4P3/3R3p/6P1/1K2Nr2/PP3P2/8

À l'aide de cette chaîne, vous pouvez calculer le score du matériau pour chaque couleur avec le tableau de score suivant:

  • p / P = Pion = 1 point
  • n / N = chevalier = 3 points
  • b / B = Bishop = 3 points
  • r / R = Tour = 5 points
  • q / Q = Reine = 9 points
  • k / K = Roi, ceux-ci n'ont pas de points car chaque position légale contient un roi de chaque côté

Les pièces blanches sont désignées en lettres majuscules ("PNBRQK") tandis que les pièces noires utilisent des minuscules ("pnbrqk"). Les carrés vides sont notés en utilisant les chiffres 1 à 8 (le nombre de carrés vides), et "/" sépare les rangs.

À partir de l'exemple de chaîne FEN, nous pouvons calculer les scores des matériaux pour chaque côté:

Pour le noir:

5 k 2 / ppp 5 / 4P3 / 3R3 p / 6P1 / 1K2N r 2 / PP3P2 / 8

Toutes les pièces noires restantes: p + p + p + p + r, cela fait un total de 9

Pour le blanc:

5k2 / ppp5 / 4 P 3/3 R 3p / 6 P 1/1 K 2 N r2 / PP 3 P 2/8

Toutes les pièces blanches restantes: P + R + P + N + P + P + P, cela fait un total de 13

Le score final est déterminé avec la formule suivante: score blanc - score noir = score final , donc pour l'exemple le score final serait: 13 - 9 = 4

Exemple :

Contribution:

5k2/ppp5/4P3/3R3p/6P1/1K2Nr2/PP3P2/8

Production:

4

Toutes règles de s'appliquent ici, la solution avec le moins d'octets gagne.


Comment publier

# Language Name, N bytes

 [code]

 [explaination, etc.]

3
Donc, la position réelle n'a pas d'importance? Vous comptez juste des lettres dans la chaîne?
2015

4
Nitpick: Ce n'est pas une chaîne FEN complète. De plus, kr1NQQQQ / 2rNQQQQ / 3NQQQQ / 3NQQQQ / 3NQQQQ / 3NQQQQ / 3NQQQQ / K2NQQQQ gagne pour le blanc, avec le noir pour se déplacer? : P
Poignée de porte

@xnor Oui, je pense que si l'évaluation est également stratégiquement basée, cela deviendra trop compliqué. Vous pouvez également supposer que toutes les entrées sont des positions légales, alors ne vous inquiétez pas.
Adnan

@ Doorknob, oui, le score est uniquement basé sur du matériel pour simplifier les choses
Adnan

Réponses:


3

CJam, 28 27 26 octets

0l{i32mdD%[5ZZX9]=\3%(*+}/

Essayez-le en ligne dans l' interpréteur CJam .

Comment ça fonctionne

0l         e# Push a 0 (accumulator) and a line from STDIN.
{          e# For each character of that line:
  i32md    e#   Divide its code point by 32; push quotient and residue.
           e#   This serves two purposes:
           e#     1. The quotient will let us distinguish between uppercase
           e#        letters, lowercase letters and non-letters.
           e#     2. The residue will be the same for uppercase and lowercase
           e#        variants of the same letter.
  D%       e#   Take the residue modulo 13.
           e#   This maps R,N,B,P,Q -> 5,1,2,3,4
  [5ZZX9]= e#   Select the element at that index (5 ≡ 0) from [5 3 3 1 9].
  \        e#   Swap the quotient on top of the stack.
           e#   1 is digit or slash, 1 is uppercase, 2 is lowercase.
  3%(      e#   Take the quotient modulo 3 and subtract 1 from the result.
           e#   This maps 1,2,3 -> 0,1,-1.
  *+       e#   Multiply the generated integers.
  +        e#   Add the product to the accumulator.
}/         e#

5

> <> , 64 57 56 53 octets

"QRBNP"013359v
$0p4}:{:v?=1l<p4+' '{-
g4v?(0:i<+
n~<;

(-7 octets avec une certaine inspiration de la réponse de @ El'endiaStarman, -3 octets grâce à @randomra)

Explication

Le programme utilise la zone de code comme table de recherche. Les put / gets hors de portée ne fonctionnent pas avec l'interpréteur en ligne, donc cela ne fonctionne qu'avec l'interpréteur Python officiel.

La première ligne pousse les pièces, suivies des valeurs des pièces. Il pousse également un 0 initial pour lancer le total de la troisième ligne.

La deuxième ligne place ensuite la valeur positive ou négative appropriée dans la cellule de pièce correspondante, par exemple -1est placée à ('p', 4)et 1est placée ('P', 4). La longueur de la pile est vérifiée pour s'assurer que la boucle s'exécute 5 fois.

Une fois la boucle terminée, la pile se compose de notre zéro unique de la première ligne. Pour chaque caractère, nous effectuons une recherche dans la cellule correspondante du tableau et l'ajoutons à notre total. Par défaut, les valeurs de cellule non initialisées sont 0, ce qui est parfait pour nos besoins.

La dernière ligne imprime simplement le résultat.


4

Rubis, 88 caractères

->s{s.chars.map{|c|({P:1,N:3,B:3,R:5,Q:9}[:"#{c.upcase}"]||0)*(c.ord<90?1:-1)}.inject:+}

C'est maladroit et laid, et il y a probablement une meilleure façon, mais bon.

La {foo: 'bar'}syntaxe de Ruby n'est en fait que du sucre {:foo => 'bar'}- c'est ennuyeux pour le golf car cela signifie que je dois convertir la clé en symbole avant de l'utiliser pour accéder à un élément de hachage ( :"#{x}"est un caractère plus court que x.to_sym).


4

Pip, 39 octets

Je vais prendre ma brève direction avant que les réponses CJam et Pyth ne viennent ...

$+Y(95<=>A_)*013359@{"KPNBRQ"@?UCa|0}Ma

Prend la chaîne FEN comme argument de ligne de commande. Voici une explication pour une version légèrement non golfée:

$+({(95<=>Aa)*013359@("KPNBRQ"@?UCa|0)}Ma)

   {                                  }Ma   Map this function to each character in input:
                                UCa          Uppercase version of character
                      "KPNBRQ"@?             Its index in this string, nil if not present
                                   |0        Logical or with 0 (to turn nil into 0)
              013359@(               )       Index into this number to get piece's score
          Aa                                 ASCII value of character
     95<=>                                   1 if less than 95, -1 if greater than 95
    (       )*                               Multiply by the score
$+(                                      )  Sum all scores and autoprint result

4

Perl, 44 octets

#!perl -p
$\+=lc=~y/pnbrq/13359/r*(a cmp$_)for/\D/g}{

En comptant le shebang comme un, l'entrée provient de stdin.


Exemple d'utilisation

$ echo 5k2/ppp5/4P3/3R3p/6P1/1K2Nr2/PP3P2/8 | perl fen-score.pl
4

Explication

Les pièces sont translittérées avec leurs valeurs respectives. Si la pièce est capitalisée (c'est-à-dire inférieure à a), sa valeur est ajoutée à la somme, sinon elle est soustraite.


3

JavaScript ES7, 79 octets 124 131

s=>(i=0,[for(q of s)i+={P:1,N:3,B:3,R:5,Q:9,p:-1,n:-3,b:-3,r:-5,q:-9}[q]||0],i)

Aussi court que possible. Utilise des compréhensions de tableaux fantaisies pour parcourir la chaîne.

Explication

s=>(     // Define function with an argument

    i=0, // this var will store the score

    [for(q of s)   // Loops through input
      i+=          // Adds to score by...

         {P:1,...,   // Defines value of each letter
          p:-1,...}  // Negative value instead, which will subtract
         || 0        // Otherwise add 0

    ], i           // Return score

3

Minkolang 0.9 , 72 65 64 60 44 42 41 octets

13359"QRBNP"m5[d3~c~$r48*+0p0p]$I[o0q+]N.

Essayez-le ici.

Un grand merci à Sp3000 pour avoir indiqué un moyen beaucoup plus efficace de le faire!

Explication

13359"QRBNP"mrepousse les scores et leurs caractères, correspondant alors des intercalaires eux, donc la pile se présente comme suit: [1,80,3,78,3,66,5,82,9,81]. 5[d3~c~$r48*+0p0p]Place ensuite le score de chaque caractère, à la fois en minuscules et en majuscules, à son emplacement dans l'espace de code. Enfin, $I[o0q+]N.boucle l'entrée jusqu'à ce qu'elle soit vide, additionnant les scores au fur et à mesure.



2

Ouroboros , 82

Ouroboros est un esolang que j'ai conçu cette semaine. Il est temps de l'essayer!

i.1+!57*(\m1(M\1).96>.@32*-.80=\.78=3*\.66=3*\.82=5*\81=9*++++\2*1\-*+
)L!4*(4Sn1(

Chaque ligne de commandes à caractère unique 1 représente un serpent ouroboros, dans lequel l'exécution se déroule de la tête (début) à la queue (fin) et revient en boucle à la tête. Les commandes (et )vous permettent de manger une partie de la queue ou de la régurgiter, modifiant ainsi les commandes à exécuter. Si le pointeur d'instruction est avalé, le serpent meurt (arrête de s'exécuter). Un programme Ouroboros consiste en un ou plusieurs serpents s'exécutant en parallèle. Chaque serpent a sa propre pile, et il y a aussi une pile partagée.

1 Une exception, qui distingue Ouroboros de nombreux langages 2D: les nombres à plusieurs chiffres peuvent être écrits de manière simple, sans avoir à faire de maths ou à pousser un 0 en premier.

Serpent 1

Le premier serpent lit un caractère ( i) et vérifie s'il s'agit de -1 / EOF ( .1+!). Si c'est le cas, il mange la majeure partie de sa queue, jusque et y compris le M( 57*().

Le serpent échange ensuite le code de caractère avec le décompte qui se trouve au-dessus de lui sur la pile ( \), déplace le décompte vers la pile partagée ( m) et avale un autre caractère ( 1(). S'il a déjà avalé un tas, cela signifie qu'il avale (que l'IP est actuellement allumé et meurt. Sinon, l'exécution se poursuit en replaçant le décompte dans la pile du serpent 1, en l'échangeant avec le code de caractère et en régurgitant le personnage qui a été précédemment avalé ( M\1)).

Nous utilisons ensuite les opérations mathématiques et de pile pour générer le score approprié pour le personnage. .96>teste s'il est en minuscule ou non; le suivant se 32*-transforme en majuscule. Ensuite, le long tronçon de .80=aux 81=9*++++cartes P-> 1, N-> 3, etc. Enfin, \2*1\-*annule le score si la lettre était en minuscules et l' +ajoute au décompte courant. Le serpent boucle ensuite et lit un autre personnage.

Serpent 2

Le deuxième serpent commence par une opération de régurgitation ( )), qui ne fait rien la première fois (car rien n'a encore été avalé, et aussi depuis l'éclatement d'une pile vide 0). Ensuite, il pousse la longueur de la pile partagée vers sa propre pile et annule logiquement ( L!). Cela donne 1si la pile est vide, 0sinon. Le serpent se multiplie par 4 et mange autant de personnages (4*( ).

Si la pile partagée était vide, cela signifie que le serpent se termine maintenant avant le S. Il repousse 4et boucle vers le ), où il régurgite les personnages qu'il vient d'avaler et recommence.

S'il y avait une valeur sur la pile partagée, cependant, aucun caractère n'est avalé et l'exécution continue. Le serpent bascule vers la pile partagée et y renvoie le nombre ( Sn); puis il avale son dernier personnage et meurt (1( ).

Synchronisation

Les deux serpents doivent être soigneusement synchronisés afin qu'il n'y ait jamais de valeur sur la pile partagée lorsque le serpent 2 effectue sa vérification, jusqu'à ce que la fin de l'entrée soit atteinte. Snake 1 met une valeur sur la pile partagée brièvement à chaque passage dans sa boucle. Ainsi, la Lcommande de snake 2 ne doit jamais être exécutée entre les commandes met Mdans snake 1. Heureusement, les serpents s'alignent très bien. Fondamentalement, la longueur de la boucle de serpent 1 (70 instructions) est un multiple de la boucle de serpent 2 (7 instructions), de sorte que les deux ne se désynchroniseront jamais:

i.1+!57*(\m1(M\1).96>.@32*-.80=\.78=3*\.66=3*\.82=5*\81=9*++++\2*1\-*+
)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5)L!5*(5
          |__|
       Danger zone

Si les chiffres n'avaient pas fonctionné si parfaitement, j'aurais rembourré un ou les deux serpents avec des espaces pour les aligner au besoin.

Tout cela est très bien, mais je veux le voir en action!

Voici le programme ci-dessus via Stack Snippet. Même sur 1000 opérations par seconde, il faut environ 10 secondes pour cracher la réponse pour l'échantillon d'entrée - mais il y arrive!


2

JavaScript ES6, 71

En tant que fonction anonyme

n=>[...n].map(x=>t+=~(y='q   rnb p PBN R   Q'.search(x))?y-9|1:0,t=0)|t

2

Perl 5, 71 63 octets

%a=(P,1,N,3,B,3,R,5,Q,9);$\+=$a{$_}||-$a{uc$_}for<>=~/./g;print

Cela modifie $\(le séparateur de ligne pour print, qui commence faux) pour chaque alphanumérique dans la chaîne qui est une clé du hachage %adéfinie au début. Il incrémente $\de la valeur du hachage si la lettre est une clé telle quelle; sinon, il incrémente par négatif la valeur du hachage si la lettre est en majuscule une clé; sinon cela n'ajoute rien.

Un grand merci à primo pour m'avoir sauvé huit octets (dans un commentaire sur cette réponse).


Je peux enregistrer un autre octet avec une autre suggestion de primo (merci!): Passez $a{$_}||-$a{uc$_}à $a{$_}-$a{$"^$_}. Mais c'est une réponse assez différente de la mienne, je pense, donc je ne prendrai pas le "crédit" (de -1 octet) pour cela.


1

Clojure / ClojureScript, 63 caractères

#(apply +(map{"P"1"N"3"B"3"R"5"Q"9"p"-1"n"-3"b"-3"r"-5"q"-9}%))

Écrit à l'aide d'un ClojureScript REPL, doit également être un Clojure valide. Essayez-le ici . Saisissez-le, puis appelez-le en utilisant(*1 "FEN_string_here")

Assez simple. {"P"1..."q"-9}est un littéral de structure de données pour une carte de "P" à 1, "N" à 3, etc. mapprend la fonction comme premier argument et la structure de données à traiter comme deuxième - dans ce cas, il utilise la fonctionnalité qui une structure de données (le littéral de carte) peut agir comme sa propre fonction d'accesseur. Le paramètre de chaîne (à %partir de la macro de fonction) peut être traité comme une liste de chaînes de caractères individuelles. Tout personnage qui ne figure pas sur la carte se retrouvera comme nildans la liste résultante, qui est +heureusement ignorée.


1

Pyth, 25 octets

-Fmsmhy/4@S5%Ck12@Gd_rBz2

Manifestation

Il utilise la formule de mappage suivante pour les lettres entre pbnrq, si kest la lettre:

(4 / (((chr(k) % 12) % 5) + 1) * 2 + 1

Ceci est représenté en Pyth comme:

hy/4@S5%Ck12

Tout d'abord, le programme crée la version remplacée par la casse de l'entrée, puis sur les deux chaînes, filtre les lettres en minuscules, puis applique la formule ci-dessus, puis additionne et soustrait les valeurs noires des valeurs blanches.


1

Python 3, 93

v=dict(zip('pbnrqPBNRQ',[1,3,3,5,9]*2))
print(sum(v.get(c,0)*(-1)**(c>'Z')for c in input()))
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.