Avaliando a pontuação com base em uma sequência FEN de xadrez

17

Desafio

A notação de Forsyth-Edwards (FEN) é uma notação padrão para descrever uma posição específica do tabuleiro de um jogo de xadrez. Seu desafio é avaliar a pontuação usando a string FEN. Este é um exemplo de uma sequência FEN:

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

Usando essa sequência, você pode calcular a pontuação do material para cada cor com a seguinte tabela de pontuação:

  • p / P = Peão = 1 ponto
  • n / N = Cavaleiro = 3 pontos
  • b / B = Bispo = 3 pontos
  • r / R = Torre = 5 pontos
  • q / Q = rainha = 9 pontos
  • k / K = Rei, estes não têm nenhum ponto porque toda posição legal contém um rei para cada lado

As peças brancas são designadas usando letras maiúsculas ("PNBRQK"), enquanto as peças pretas usam letras minúsculas ("pnbrqk"). Os quadrados vazios são anotados usando os dígitos de 1 a 8 (o número de quadrados vazios) e "/" separa as classificações.

A partir da sequência FEN de exemplo, podemos calcular as pontuações do material para cada lado:

Para preto:

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

Todas as peças pretas restantes: p + p + p + p + r, totalizam 9

Para branco:

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

Todas as peças brancas restantes: P + R + P + N + P + P + P, totalizam 13

A pontuação final é determinada com a seguinte fórmula: Escore em branco - Escore em preto = Escore final , portanto, no exemplo, o escore final seria: 13 - 9 = 4

Exemplo :

Entrada:

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

Resultado:

4

Todas as regras de aplicam aqui, a solução com a menor quantidade de bytes ganha.


Como publicar

# Language Name, N bytes

 [code]

 [explaination, etc.]
Adnan
fonte
3
Então a posição atual não importa? Você apenas conta letras na string?
Xnor
4
Nitpick: Essa não é uma sequência completa de FEN. Além disso, kr1NQQQQ / 2rNQQQQ / 3NQQQQ / 3NQQQQ / 3NQQQQ / 3NQQQQ / 3NQQQQ / K2NQQQQ está ganhando para branco, com preto para mover? : P
Maçaneta da porta
@ xnor Sim, acho que se a avaliação também for estrategicamente baseada, ficará muito complicada. Você também pode assumir que todas as entradas são posições legais, portanto, não se preocupe com isso.
Adnan
@Doorknob, sim, a pontuação é único material base para coisas Simplifique
Adnan

Respostas:

3

CJam, 28 27 26 bytes

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

Experimente on-line no intérprete CJam .

Como 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
fonte
5

> <> , 64 57 56 53 bytes

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

(-7 bytes com alguma inspiração da resposta de @ El'endiaStarman, -3 bytes graças a @randomra)

Explicação

O programa usa o codebox como uma tabela de pesquisa. Put / gets fora do intervalo não funcionam com o intérprete on-line, portanto, isso só funciona com o intérprete oficial do Python.

A primeira linha empurra as peças, seguida pelos valores das peças. Ele também pressiona um 0 inicial para iniciar o total da terceira linha.

A segunda linha coloca o valor positivo ou negativo apropriado na célula da peça correspondente, por exemplo, -1é colocada em ('p', 4)e 1é colocada('P', 4) . O comprimento da pilha é verificado para garantir que o loop seja executado 5 vezes.

Depois que o loop termina, a pilha consiste em nosso único zero da primeira linha. Para cada caracter, realizamos uma pesquisa na célula correspondente na tabela e a adicionamos ao nosso total. Por padrão, os valores das células não inicializadas são 0, o que é perfeito para nossos propósitos.

A última linha apenas imprime o resultado.

Sp3000
fonte
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:+}

Isso é estranho e feio, e provavelmente existe uma maneira melhor, mas tudo bem.

{foo: 'bar'}Na verdade, a sintaxe do Ruby é apenas para açúcar {:foo => 'bar'}- isso é irritante para o golfe, porque significa que tenho que converter a chave em um símbolo antes de usá-la para acessar um elemento de hash ( :"#{x}"é um caractere menor que x.to_sym).

Maçaneta da porta
fonte
4

Pip, 39 bytes

Vou assumir minha breve liderança antes que as respostas CJam e Pyth apareçam ...

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

Toma a seqüência de caracteres FEN como um argumento de linha de comando. Aqui está uma explicação para uma versão um pouco não destruída:

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

Perl, 44 bytes

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

Contando o shebang como um, a entrada é obtida de stdin.


Uso da amostra

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

Explicação

As peças são transliteradas com seus respectivos valores. Se a peça estiver em maiúscula (ou seja, menor que a), seu valor será adicionado à soma, se não for subtraído.

primo
fonte
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)

O mais curto que eu conseguir. Usa sofisticadas compreensões de array, para percorrer a string.

Explicação

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
fonte
3

Minkolang 0.9 , 72 65 64 60 44 42 41 bytes

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

Experimente aqui.

Muito obrigado ao Sp3000 por apontar uma maneira muito mais eficiente de fazer isso!

Explicação

13359"QRBNP"mempurra as pontuações e seus personagens correspondentes, em seguida, intercala -los, de modo que os olhares pilha como este: [1,80,3,78,3,66,5,82,9,81]. Em seguida, 5[d3~c~$r48*+0p0p]coloca a pontuação de cada caractere, em minúsculas e maiúsculas, em seu local no espaço de código. Por fim, $I[o0q+]N.percorre a entrada até ficar vazia, somando as pontuações à medida que avança.

El'endia Starman
fonte
2

CJam, 33 bytes

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

Aqui está a maneira super ingênua de encontrar seqüências de caracteres. Experimente online .

Sp3000
fonte
2

Ouroboros , 82

Ouroboros é um esolang que eu projetei esta semana. Hora de dar uma volta!

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

Cada linha de comandos de caractere único 1 representa uma cobra ouroboros, em que a execução prossegue da cabeça (início) à cauda (final) e volta à cabeça. Os comandos (e )permitem que você coma parte da cauda ou regurgite, alterando assim os comandos que são executados. Se o ponteiro da instrução for engolido, a cobra morre (para de executar). Um programa Ouroboros consiste em uma ou mais cobras executando em paralelo. Cada cobra tem uma pilha própria e também há uma pilha compartilhada.

1 Uma exceção, que distingue Ouroboros de muitas linguagens 2D: números de vários dígitos podem ser escritos diretamente, sem a necessidade de fazer contas ou pressionar o 0 primeiro.

Cobra 1

A primeira cobra lê um caractere ( i) e verifica se é -1 / EOF ( .1+!). Nesse caso, ele come a maior parte de sua cauda, ​​incluindo e M( 57*().

A cobra então troca o código do caractere com o registro que está acima dele na pilha ( \), move o registro para a pilha compartilhada ( m) e engole outro caractere ( 1(). Se ele já engoliu um monte, isso significa que engole o (que o IP está atualmente ativo e morre. Caso contrário, a execução prossegue movendo o registro de volta para a pilha da cobra 1, trocando-o pelo código char e regurgitando o personagem que foi engolido anteriormente ( M\1)).

Em seguida, usamos operações matemáticas e de pilha para gerar a pontuação apropriada para o personagem. .96>testa se é minúsculo ou não; o subsequente 32*-converte para maiúsculas. Em seguida, a longa extensão de .80=para 81=9*++++mapas P-> 1, N-> 3, etc. Finalmente, \2*1\-*nega a pontuação se a carta foi minúsculas, e +adiciona-lo para o registro ativo. A cobra então dá laços e lê outro personagem.

Cobra 2

A segunda cobra começa com uma operação de regurgitação ( )), que não faz nada na primeira vez (já que nada foi engolido ainda e também desde que abrir uma pilha vazia 0). Em seguida, envia o comprimento da pilha compartilhada para sua própria pilha e nega logicamente ( L!). Isso fornece 1se a pilha estiver vazia, 0caso contrário. A cobra multiplica por 4 e come tantos caracteres ( 4*().

Se a pilha compartilhada estava vazia, isso significa que a cobra agora termina antes da S. Ele empurra 4e volta para o ), onde regurgita os personagens que acabou de engolir e começa novamente.

Se houver um valor na pilha compartilhada, no entanto, nenhum caractere será engolido e a execução continuará. A cobra muda para a pilha compartilhada e gera o número lá ( Sn); depois engole seu último caractere e morre ( 1().

Sincronização

As duas cobras devem ser cuidadosamente sincronizadas para que nunca haja um valor na pilha compartilhada quando a cobra 2 faz sua verificação, até que o final da entrada seja alcançado. Snake 1 coloca um valor brevemente na pilha compartilhada em cada passagem em seu loop. Assim, o Lcomando da cobra 2 nunca deve ser executado entre os comandos me Mna cobra 1. Felizmente, as cobras se alinham muito bem. Fundamentalmente, o comprimento do loop da cobra 1 (70 instruções) é um múltiplo do loop da cobra 2 (7 instruções), para que os dois nunca fiquem fora de sincronia:

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

Se os números não tivessem funcionado tão perfeitamente, eu teria preenchido uma ou ambas as cobras com espaços para fazê-las alinhar conforme necessário.

Tudo isso está muito bem, mas eu quero vê-lo em ação!

Aqui está o programa acima via Stack Snippet. Mesmo em 1000 operações por segundo, leva cerca de 10 segundos para cuspir a resposta para a entrada de amostra - mas chega lá!

DLosc
fonte
2

JavaScript ES6, 71

Como uma função anônima

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

Perl 5, 71 63 bytes

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

Isso modifica $\(o separador de linha para print, que começa com false) para cada alfanumérico na string que é uma chave do hash %adefinido no início. Aumenta $\pelo valor do hash se a letra for uma chave como está; caso contrário, aumenta em negativo o valor do hash se a letra maiúscula for uma chave; caso contrário, não adiciona nada.

Muito obrigado ao primo por me salvar oito bytes (em um comentário sobre esta resposta).


Posso salvar outro byte com outra sugestão do primo (obrigado!): Mude $a{$_}||-$a{uc$_}para $a{$_}-$a{$"^$_}. Mas essa é uma resposta bastante diferente da minha, eu acho, então não aceitarei o "crédito" (de -1 byte) por ela.

msh210
fonte
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 um ClojureScript REPL, também deve ser um Clojure válido. Experimente aqui . Digite e chame usando(*1 "FEN_string_here")

Bem direto. {"P"1..."q"-9}é uma estrutura de dados literal para um mapa de "P" para 1, "N" para 3, etc. mapassume a função como o primeiro argumento e a estrutura de dados a processar como o segundo - nesse caso, ele está usando o recurso que uma estrutura de dados (o literal do mapa) pode atuar como sua própria função de acessador. O parâmetro string ( %da macro de funções) pode ser tratado como uma lista de cadeias de caracteres individuais. Qualquer personagem que não esteja no mapa terminará como nilna lista resultante, que +felizmente ignora.

MattPutnam
fonte
1

Pitão, 25 bytes

-Fmsmhy/4@S5%Ck12@Gd_rBz2

Demonstração

Isso usa a seguinte fórmula de mapeamento para letras em pbnrq, se kfor a letra:

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

Isso é representado no Pyth como:

hy/4@S5%Ck12

Primeiro, o programa cria a versão trocada entre maiúsculas e minúsculas da entrada e, em seguida, em ambas as seqüências filtra letras minúsculas, aplica a fórmula acima e depois soma e subtrai os valores em preto dos valores em branco.

isaacg
fonte
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()))
Morgan Thrapp
fonte