Evaluación de la puntuación basada en una cadena de ajedrez FEN

17

Desafío

La notación de Forsyth-Edwards (FEN) es una notación estándar para describir una posición particular del tablero de un juego de ajedrez. Su desafío es evaluar el puntaje utilizando la cadena FEN. Este es un ejemplo de una cadena FEN:

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

Con esta cadena, puede calcular la puntuación del material para cada color con la siguiente tabla de puntuación:

  • p / P = Peón = 1 punto
  • n / N = Caballero = 3 puntos
  • b / B = Obispo = 3 puntos
  • r / R = Torre = 5 puntos
  • q / Q = Reina = 9 puntos
  • k / K = Rey, estos no tienen ningún punto porque cada posición legal contiene un rey para cada lado

Las piezas blancas se designan con letras mayúsculas ("PNBRQK") mientras que las piezas negras usan minúsculas ("pnbrqk"). Los cuadrados vacíos se observan utilizando los dígitos del 1 al 8 (el número de cuadrados vacíos), y "/" separa los rangos.

A partir de la cadena de ejemplo FEN, podemos calcular las puntuaciones de material para cada lado:

Para negro:

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

Quedan todas las piezas negras: p + p + p + p + r, esto es un total de 9

Para blanco:

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

Quedan todas las piezas blancas: P + R + P + N + P + P + P, esto es un total de 13

El puntaje final se determina con la siguiente fórmula: puntaje blanco - puntaje negro = puntaje final , entonces, por ejemplo, el puntaje final sería: 13 - 9 = 4

Ejemplo :

Entrada:

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

Salida:

4

Todos los reglas se aplican aquí, la solución con la menor cantidad de bytes victorias.


Cómo publicar

# Language Name, N bytes

 [code]

 [explaination, etc.]
Adnan
fuente
3
Entonces, ¿la posición real no importa? ¿Solo cuentas letras en la cadena?
xnor
44
Nitpick: Esa no es una cadena FEN completa. Además, kr1NQQQQ / 2rNQQQQ / 3NQQQQ / 3NQQQQ / 3NQQQQ / 3NQQQQ / 3NQQQQ / K2NQQQQ está ganando para las blancas, con las negras para moverse. : P
Pomo de la puerta
@xnor Sí, creo que si la evaluación también se basa estratégicamente, será demasiado complicada. También puede suponer que todas las entradas son posiciones legales, así que no se preocupe por eso.
Adnan
@Doorknob, sí, el puntaje es solo material basado en simplificar las cosas
Adnan

Respuestas:

3

CJam, 28 27 26 bytes

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

Pruébelo en línea en el intérprete de CJam .

Cómo funciona

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#
Dennis
fuente
5

> <> , 64 57 56 53 bytes

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

(-7 bytes con algo de inspiración de la respuesta de @ El'endiaStarman, -3 bytes gracias a @randomra)

Explicación

El programa usa el cuadro de código como una tabla de búsqueda. Los put / gets fuera de rango no funcionan con el intérprete en línea, por lo que esto solo funciona con el intérprete oficial de Python.

La primera línea empuja las piezas, seguido de los valores de las piezas. También empuja un 0 inicial para iniciar el total de la tercera línea.

La segunda línea coloca el valor positivo o negativo apropiado en la celda de pieza correspondiente, por ejemplo, -1se coloca en ('p', 4)y 1se coloca ('P', 4). La longitud de la pila se verifica para asegurarse de que el ciclo se ejecute 5 veces.

Una vez que finaliza el ciclo, la pila consiste en nuestro único cero desde la primera línea. Para cada carácter, realizamos una búsqueda en la celda correspondiente en la tabla y la agregamos a nuestro total. Por defecto, los valores de celda no inicializados son 0, lo cual es perfecto para nuestros propósitos.

La última línea simplemente imprime el resultado.

Sp3000
fuente
4

Ruby, 88 caracteres

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

Esto es incómodo y feo, y probablemente haya una mejor manera, pero bueno.

La {foo: 'bar'}sintaxis de Ruby en realidad es solo azúcar, esto {:foo => 'bar'}es molesto para el golf porque significa que tengo que convertir la clave en un símbolo antes de usarla para acceder a un elemento hash ( :"#{x}"es un carácter más corto que x.to_sym).

Pomo de la puerta
fuente
4

Pip, 39 bytes

Tomaré mi breve turno antes de que lleguen las respuestas de CJam y Pyth ...

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

Toma la cadena FEN como un argumento de línea de comandos. Aquí hay una explicación para una versión ungolfed:

$+({(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
DLosc
fuente
4

Perl, 44 bytes

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

Contando el shebang como uno, la entrada se toma de stdin.


Uso de muestra

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

Explicación

Las piezas se transliteran con sus respectivos valores. Si la pieza está en mayúscula (es decir, menor que a), su valor se agrega a la suma, si no se resta.

primo
fuente
3

JavaScript ES7, 79 bytes 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)

Tan corto como puedo llegar. Utiliza comprensiones de arreglos elegantes para recorrer la cadena.

Explicación

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
Downgoat
fuente
3

Minkolang 0.9 , 72 65 64 60 44 42 41 bytes

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

Pruébalo aquí

¡Muchas gracias a Sp3000 por señalar una forma mucho más eficiente de hacer esto!

Explicación

13359"QRBNP"mempuja los puntajes y sus caracteres correspondientes, luego los intercala , para que la pila se vea así:[1,80,3,78,3,66,5,82,9,81] . Luego 5[d3~c~$r48*+0p0p]coloca la puntuación de cada carácter, tanto en minúsculas como en mayúsculas, en su ubicación en el espacio de código. Finalmente, $I[o0q+]N.recorre la entrada hasta que esté vacía, sumando los puntajes a medida que avanza.

El'endia Starman
fuente
2

CJam, 33 bytes

q{"PNBRQ"_el+#13359Ab_Wf*+0+=}%:+

Aquí está la manera súper ingenua de encontrar cuerdas. Pruébalo en línea .

Sp3000
fuente
2

Ouroboros , 82

Ouroboros es un esolang que diseñé esta semana. ¡Es hora de dar una vuelta!

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

Cada línea de comandos de un solo carácter 1 representa una serpiente ouroboros, en la que la ejecución procede de la cabeza (inicio) a la cola (final) y regresa a la cabeza. El (y) comandos le permiten comer parte de la cola o regurgitan, cambiando así lo que los comandos se ejecutan. Si alguna vez se traga el puntero de instrucción, la serpiente muere (deja de ejecutarse). Un programa Ouroboros consiste en una o más serpientes que se ejecutan en paralelo. Cada serpiente tiene una pila propia, y también hay una pila compartida.

1 Una excepción, que distingue a Ouroboros de muchos lenguajes 2D: los números de varios dígitos se pueden escribir directamente, sin tener que hacer cálculos matemáticos o presionar un 0 primero.

Serpiente 1

La primera serpiente lee un carácter ( i) y comprueba si es -1 / EOF ( .1+!). Si es así, se come la mayor parte de su cola, hasta e incluyendo el M( 57*().

Luego, la serpiente intercambia el código del personaje con la cuenta que está arriba de la pila ( \), mueve la cuenta a la pila compartida ( m) y se traga otro personaje ( 1(). Si ya se había tragado un montón, esto significa que se traga el hecho de (que la IP está actualmente encendida y muere. De lo contrario, la ejecución continúa moviendo la cuenta de regreso a la pila de la serpiente 1, intercambiándola con el código de char y regurgitando el personaje que se tragó previamente ( M\1)).

Luego usamos operaciones matemáticas y de pila para generar el puntaje apropiado para el personaje. .96>prueba si es minúscula o no; los siguientes se 32*-convierten a mayúsculas. A continuación, el largo tramo de .80=a 81=9*++++mapas P-> 1, N-> 3, etc. Por último, \2*1\-*niega la puntuación si la carta fue minúscula, y +lo añade a la cuenta corriente. La serpiente luego gira y lee otro personaje.

Serpiente 2

La segunda serpiente comienza con una operación de regurgitación ( )), que no hace nada la primera vez (ya que todavía no se ha tragado nada, y también desde que aparece una pila vacía 0). Luego, empuja la longitud de la pila compartida a su propia pila y niega lógicamente ( L!). Esto da 1si la pila está vacía, de lo 0contrario. La serpiente se multiplica por 4 y se come esa cantidad de caracteres ( 4*().

Si la pila compartida estaba vacía, esto significa que la serpiente ahora termina antes que S. Empuja 4y regresa al ), donde regurgita a los personajes que acaba de tragar y comienza de nuevo.

Sin embargo, si hubo un valor en la pila compartida, no se tragan caracteres y la ejecución continúa. La serpiente cambia a la pila compartida y muestra el número allí ( Sn); luego se traga su último personaje y muere (1( ).

Sincronización

Las dos serpientes deben sincronizarse cuidadosamente para que nunca haya un valor en la pila compartida cuando la serpiente 2 hace su verificación, hasta que se alcanza el final de la entrada. Snake 1 pone un valor en la pila compartida brevemente en cada pasada a través de su ciclo. Por lo tanto, el Lcomando de la serpiente 2 nunca debe ejecutarse entre los comandos my Mde la serpiente 1. Afortunadamente, las serpientes se alinean muy bien. Crucialmente, la longitud del bucle de la serpiente 1 (70 instrucciones) es un múltiplo del bucle de la serpiente 2 (7 instrucciones), por lo que los dos nunca se desincronizarán:

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 los números no hubieran funcionado tan perfectamente, habría rellenado una o ambas serpientes con espacios para alinearlas según sea necesario.

¡Todo esto está muy bien, pero quiero verlo en acción!

Aquí está el programa anterior a través de Fragmento de pila. Incluso en 1000 operaciones por segundo, lleva unos 10 segundos escupir la respuesta para la entrada de muestra, ¡pero llega allí!

DLosc
fuente
2

JavaScript ES6, 71

Como una función anónima

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

Perl 5, 71 63 bytes

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

Esto modifica $\ (el separador de línea para print, que comienza en falso) para cada alfanumérico en la cadena que es una clave del hash %adefinido al principio. Se incrementa $\por el valor del hash si la letra es una clave como es; de lo contrario, incrementa en negativo el valor del hash si la letra mayúscula es una clave; de lo contrario no agrega nada.

Muchas gracias a primo por salvarme ocho bytes (en un comentario sobre esta respuesta).


Puedo guardar otro byte con otra sugerencia de primo (¡gracias!): Cambiar $a{$_}||-$a{uc$_}a$a{$_}-$a{$"^$_} . Pero creo que esa es una respuesta bastante diferente a la mía, así que no tomaré el "crédito" (de -1 byte) por ello.

msh210
fuente
1

Clojure / ClojureScript, 63 caracteres

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

Escrito usando un ClojureScript REPL, también debe ser válido Clojure. Intentalo aquí . Ingrese, luego llámelo usando(*1 "FEN_string_here")

Muy claro. {"P"1..."q"-9}es una estructura de datos literal para un mapa de "P" a 1, "N" a 3, etc. maptoma la función como primer argumento y la estructura de datos para procesar como el segundo; en este caso, está utilizando la función que Una estructura de datos (el literal del mapa) puede actuar como su propia función de acceso. El parámetro de cadena ( %de la macro de función) puede tratarse como una lista de cadenas de caracteres individuales. Cualquier personaje que no esté en el mapa terminará como nilen la lista resultante, que +felizmente ignora.

MattPutnam
fuente
1

Pyth, 25 bytes

-Fmsmhy/4@S5%Ck12@Gd_rBz2

Demostración

Utiliza la siguiente fórmula de mapeo para las letras pbnrq, si kes la letra:

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

Esto se representa en Pyth como:

hy/4@S5%Ck12

Primero, el programa crea la versión con mayúsculas y minúsculas de la entrada, luego en ambas cadenas se filtran las letras minúsculas, luego aplica la fórmula anterior, luego suma y resta los valores negros de los valores blancos.

isaacg
fuente
1

Pitón 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()))
Morgan Thrapp
fuente