Generador de posición Chess960

11

Contexto

Chess960 (o Fischer Random Chess) es una variante del ajedrez inventada y defendida por el ex campeón mundial de ajedrez Bobby Fischer, anunciada públicamente el 19 de junio de 1996 en Buenos Aires, Argentina. Emplea el mismo tablero y piezas que el ajedrez estándar; sin embargo, la posición inicial de las piezas en las filas de inicio de los jugadores es aleatoria

Reglas

  • Los peones blancos se colocan en el segundo rango como en el ajedrez estándar
  • Todas las piezas blancas restantes se colocan al azar en el primer rango
  • Los obispos deben colocarse en cuadrados de colores opuestos.
  • El rey debe colocarse en un cuadrado entre las torres.
  • Las piezas de las negras se colocan iguales y opuestas a las piezas de las blancas.

De: http://en.wikipedia.org/wiki/Chess960

Para todas las personas que desean publicar respuestas ...

tiene que hacer un generador de posiciones Chess960, capaz de generar aleatoriamente una de las 960 posiciones siguiendo las reglas descritas anteriormente (tiene que ser capaz de generar cualquiera de los 960, ¡no se acepta codificar una posición!), y solo necesita salida de las piezas blancas de rango uno.

Salida de ejemplo:

rkrbnnbq

dónde:

  • k rey
  • q reina
  • b obispo
  • n caballero
  • r torre

Este será el código de golf, y el desempate serán los votos a favor.

jsedano
fuente
Cuando dice que tiene que ser capaz de generar cualquiera de las 960 posiciones, ¿tienen que ser equiprobables?
Peter Taylor
Interesante, realmente no he pensado en eso ... quiero decir, idealmente debería ser, creo ... Las respuestas hasta ahora ofrecen esta calidad, ... ¿verdad?
jsedano
Los dos que están escritos en idiomas que tienen incorporados que barajan uniformemente hacen; los dos GolfScript son cercanos pero no del todo uniformes.
Peter Taylor
Yo diría que cerca es lo suficientemente bueno
jsedano
Esta pregunta me inspiró a preguntar codegolf.stackexchange.com/questions/12322/…
user123444555621

Respuestas:

6

GolfScript ( 49 48 caracteres, o 47 para salida en mayúsculas)

'bbnnrrkq'{{;9rand}$.'b'/1=,1$'r'/1='k'?)!|1&}do

Esto utiliza la técnica estándar de permutar aleatoriamente hasta que cumplamos con los criterios. A diferencia de la solución GolfScript de w0lf, esto realiza ambas comprobaciones en la cadena, por lo que es probable que se ejecute a través del bucle más veces.

El uso de mayúsculas permite guardar un carácter:

'BBNNRRKQ'{{;9rand}$.'B'/1=,1$'R'/1=75?)!|1&}do
Peter Taylor
fuente
8

Ruby 1.9, 67 65 caracteres

Ah, la vieja técnica "sigue aleatorizando hasta que generes algo válido" ...

$_=%w(r r n n b b q k).shuffle*''until/r.*k.*r/&&/b(..)*b/
$><<$_

(En Ruby 2.0, %w(r r n n b b q k)podría ser 'rrnnbbqk'.chars)

Paul Prestidge
fuente
1
En 1.9.3 puede ahorrar el ~costo de una advertencia, cuando esté disponible. pastebin.com/nuE9zWSw
manatwork
@manatwork eso es genial, ¡gracias!
Paul Prestidge
2
la técnica de "seguir aleatorizando hasta que genere algo válido" es aún mucho más rápida que la técnica de "barajar la lista de posibilidades, filtrar y tomar primero" que los lenguajes puramente funcionales como APL tienden a producir :-)
John Dvorak
1
@Daniero, esa es definitivamente la $_variable. Funciona porque ruby ​​tiene algunos métodos limpios como Kernel # chop que funcionan como el método String # chop equivalente pero con $_su receptor. Esto ahorra mucho tiempo cuando (por ejemplo) está escribiendo un ciclo de lectura / proceso / escritura usando ruby -no ruby -p.
Paul Prestidge
2
@GigaWatt no. La primera coincide si hay un número par de caracteres entre unas dos B. El último coincide solo si los B'S están en los extremos.
John Dvorak el
8

GolfScript 60 49

;'qbbnnxxx'{{9rand*}$.'b'/1=,2%}do'x'/'rkr'1/]zip

(acortado a 49 caracteres gracias a los excelentes consejos de Peter Taylor)

Prueba en línea aquí .

Una explicación del código:

;'qbbnnxxx'         # push the string 'qbbnnxxx' on the clean stack
{

    {9rand*}$       # shuffle the string

    .'b'/1=,2%      # count the number of places between the 'b's
                    # (including the 'b's themselves)
                    # if this count is even, the bishops are on
                    # squares of different colors, so place a 0
                    # on the stack to make the do loop stop

}do                 # repeat the procedure above until a 
                    # good string is encountered

'x'/                # split the string where the 'x's are

'rkr'1/]zip         # and put 'r', 'k' and then 'r' again
                    # where the 'x's used to be
w0lf
fuente
1
Su método para verificar que haya un número par de letras entre las bs parece muy largo. ¿Qué tal .'b'/1=,2%?
Peter Taylor
Y puede evitar descartar intentos fallidos sacando 'qbbnnxxx'el bucle y reorganizando la misma cadena.
Peter Taylor
@PeterTaylor Gracias por los excelentes consejos. Para el tema "cuenta entre 'b' 'sentí que debería haber un camino más corto, pero simplemente no pude encontrarlo.
Cristian Lupascu
4

J, 56 caracteres

{.(#~'(?=.*b(..)*b).*r.*k.*r.*'&rxeq"1)'kqbbnnrr'A.~?~!8

Toma varios segundos en mi máquina debido al algoritmo ineficiente. Se puede ganar algo de velocidad agregando ~.(eliminar duplicados) antes 'kqbbnnrr'.

explicación:

  • ?~!8trata 8!elementos aleatorios de0 ... 8!
  • 'kqbbnnrr'A.~los usa como índices de anagramas para la cadena kqbbnnrr.
  • (#~'...'&rxeq"1)' los filtra por la expresión regular entre comillas.
  • {. significa "tomar el primer elemento"
John Dvorak
fuente
4

K, 69

(-8?)/[{~*(*/~~':{m=_m:x%2}@&x="b")&(&x="k")within&"r"=x};"rrbbnnkq"]
tmartin
fuente
3

Python, 105 caracteres

Básicamente, la técnica de Chron, menos las elegantes cosas de Ruby.

import re,random
a='rrbbnnkq'
while re.search('b.(..)*b|r[^k]*r',a):a=''.join(random.sample(a,8))
print a

Gracias a Peter Taylor por el acortamiento de la expresión regular.

daniero
fuente
not s('b(..)*b',a)parece una forma de decir larga y sin aliento s('b.(..)*b',a). Además, samplepuede ser un carácter más corto que shuffle, pero requiere un argumento adicional.
Peter Taylor
Tienes razón sobre la expresión regular, Peter. ¡Gracias! ShuffleSin Noneembargo, regresa , así que no es bueno :(
daniero
1
Perdí el bosque por los árboles. No necesita dos expresiones regulares, porque está comprobando la misma cadena y ores equivalente a la alternancia de expresiones regulares ( |). Ahorra 13 caracteres.
Peter Taylor
@PeterTaylor ¡Buena captura! Gracias.
daniero