Min: 0 bits
Max: 1734 243 bits (4.335 4.401 bits / tablero amortizado)
Esperado: 351 177 bits (4.376 4.430 bits / tablero amortizado)
Como puedo determinar la entrada y la salida que quiera, decidí seguir codificando la historia del juego hasta este momento. Una ventaja es que la información adicional de quién es el turno, pasa y quién tiene la capacidad de atacar dónde se puede derivar y no codificar.
Intento 1:
Ingenuamente pensé que puedo codificar cada movimiento en 12 bits, 4 tripletas de la forma (inicio x, inicio y, final x, final y) donde cada uno es de 3 bits.
Asumiríamos la posición inicial y moveríamos las piezas desde allí con las blancas primero. El tablero está dispuesto de tal manera que (0, 0) es la esquina inferior izquierda del blanco.
Por ejemplo el juego:
e4 e5
Nf3 f6
Nxe5 fxe5
... ...
Sería codificado como:
100001 100010 100110 100100
110000 101010 101110 101101
101010 100100 101101 100100
...
Esto lleva a una codificación de 12 m bits, donde m es el número de movimientos realizados
Por un lado, esto podría ser realmente grande, por otro lado, puede considerar que cada movimiento es su propio juego, por lo que cada codificación realmente codifica m "tableros de ajedrez". Si amortizaste esto, obtienes que cada "tablero de ajedrez" es de 12 bits. Pero siento que esto es un poco trampa ...
Intento 2:
Me di cuenta de que cada movimiento en el intento anterior codifica muchos movimientos ilegales. Así que decidí codificar solo movimientos legales. Enumeramos posibles movimientos de la siguiente manera, numera cada cuadrado de manera que (0, 0) → 0, (1, 0) → 1, (x, y) → x + 8 y. Itere a través de las fichas y compruebe si hay una pieza y si puede moverse. Si es así, agregue las posiciones a las que puede ir a una lista. Elija el índice de la lista que es el movimiento que desea hacer. Agregue ese número al total acumulado de movimientos ponderados por 1 más el número de movimientos posibles.
Ejemplo como el anterior: desde la posición inicial, la primera pieza que puede moverse es el caballero en el cuadrado 1, puede moverse al cuadrado 16 o 18, así que agréguelos a la lista [(1,16),(1,18)]
. El siguiente es el caballero en el cuadrado 6, agregue sus movimientos. En general obtenemos:
[(1,16),(1,18),(6,21),(6,23),(8,16),(8,24),(9,17),(9,25),(10,18),(10,26),(11,19),(11,27),(12,20),(12,28),(13,21),(13,29),(14,22),(14,30),(15,23),(15,31)]
Como queremos el movimiento (12, 28), codificamos esto como 13 en la base 20, ya que hay 20 movimientos posibles.
Entonces ahora tenemos el número de juego g 0
= 13
A continuación, hacemos lo mismo para el negro, excepto que numeramos las fichas al revés (para que sea más fácil, no obligatorio) obtener la lista de movimientos:
[(1,16),(1,18),(6,21),(6,23),(8,16),(8,24),(9,17),(9,25),(10,18),(10,26),(11,19),(11,27),(12,20),(12,28),(13,21),(13,29),(14,22),(14,30),(15,23),(15,31)]
Como queremos el movimiento (11, 27), codificamos esto como 11 en la base 20, ya que hay 20 movimientos posibles.
Entonces ahora obtenemos el número de juego g 1
= (11 ⋅ 20) + 13 = 233
A continuación obtenemos la siguiente lista de movimientos para las blancas:
[(1,16),(1,18),(3,12),(3,21),(3,30),(3,39),(4,12),(5,12),(5,19),(5,26),(5,33),(5,40),(6,12),(6,21),(6,23),(8,16),(8,24),(9,17),(9,25),(10,18),(10,26),(11,19),(11,27)(13,21),(13,29),(14,22),(14,30),(15,23),(15,31)]
Como queremos el movimiento (6, 21), codificamos esto como 13 en la base 29 ya que hay 29 movimientos posibles.
Entonces ahora obtenemos el número de juego g 2
= ((13 ⋅ 20) + 11) 20 + 13 = 5433
A continuación obtenemos la siguiente lista de movimientos para las negras:
[(1,11),(1,16),(1,18),(2,11),(2,20),(2,29),(2,38),(2,47),(3,11),(4,11),(4,18),(4,25),(4,32),(6,21),(6,23),(8,16),(8,24),(9,17),(9,25),(10,18),(10,26),(12,20),(12,28),(13,21),(13,29),(14,22),(14,30),(15,23),(15,31)]
Como queremos el movimiento $ (10, 18) $ (10, 18)
Entonces ahora obtenemos el número de juego g 3
= (((19 ⋅ 29 + 13) 20) + 11) 20 + 13 = 225833
Y continúe este proceso para todos los movimientos restantes. Puedes pensar en g como la función g (x, y, z) = x y + z. Así g 0
= g (1, 1, 13), g 1
= g (g (1, 1, 11), 20, 13), g 2
= g (g (g (1, 1, 13), 20, 11), 20, 13), g 3
= g (g (g (g (1, 1, 19), 29, 13), 20, 11), 20, 13)
Para decodificar un número de juego g 0 , comenzamos en la posición inicial y enumeramos todos los movimientos posibles. Luego calculamos g 1 = g 0 // l , m 0 = g 0 % l , donde l es el número de movimientos posibles, '//' es el operador de división entera y '%' es el operador de módulo. Debe sostener que g 0 = g 1 + m 0 . Luego hacemos el movimiento m 0 y repetimos.
Del ejemplo anterior si g 0 = 225833, entonces g 1 = 225833 // 20 = 11291 ym 0 = 225833% 20 = 13. A continuación g 2 = 11291 // 20 = 564 ym 1 = 11291% 20 = 11. Luego g 3 = 11291 // 20 = 564 y m 2 = 11291% 20 = 11. Por lo tanto, g 4 = 564 // 29 = 19 y_m_ 3 = 564% 29 = 13. Finalmente g 5 = 19 // 29 = 0 ym 4 = 19% 29 = 19.
Entonces, ¿cuántos bits se usan para codificar un juego de esta manera?
Por simplicidad, digamos que siempre hay 20 movimientos cada turno y para el peor de los casos siempre elegimos el más grande, 19. El número que obtendremos es 19 ⋅ 20 m
+ 19 ⋅ 20 m-1
+ 19 ⋅ 20 m-2
+ ⋯ + 19 ⋅ 20 + 19 = 20 m + 1
- 1 donde _m es el número de movimientos. Para codificar 20 m + 1
- 1 necesitamos aproximadamente log 2
(20 m + 1
) bits, que es aproximadamente (m + 1) ∗ log 2
(20) = 4.3219 ∗ (m + 1)
En promedio m = 80 (40 movimientos por jugador), por lo que se necesitarían 351 bits para codificar. Si estuviéramos grabando muchos juegos necesitaríamos una codificación universal ya que no sabemos cuántos bits necesitará cada número
El peor de los casos cuando m = 400 (200 movimientos por jugador), por lo que se necesitarían 1734 bits para codificar.
Tenga en cuenta que la posición que queremos codificar nos debe ser dada a través del camino más corto para llegar siguiendo las reglas. Por ejemplo, el juego teorizado aquí no necesita m = 11741 para codificar la posición final. En su lugar, ejecutamos una búsqueda Breadth-First para encontrar la ruta más corta a esa posición y codificarla en su lugar. No sé qué tan profundo tendríamos que llegar para enumerar todas las posiciones de ajedrez, pero sospecho que 400 es una sobreestimación.
Cálculo rápido
Hay 12 piezas únicas o el cuadrado puede estar vacío, por lo que colocarlas en un tablero de ajedrez es 13 64 . Esta es una gran sobreestimación ya que incluye muchas posiciones inválidas. Cuando estamos m se mueve en el juego que hemos creado unos 20 m posiciones. Entonces estamos buscando cuando 20 m = 13 64 . Registre ambos lados para obtener m = 64 * log 20 (13) = 54.797. Esto muestra que deberíamos poder llegar a cualquier posición en 55 movimientos.
Ahora que calculé que el peor de los casos sería m = 55 no m = 400, editaré mis resultados. Para codificar una posición donde m = 55 toma 243 bits. También voy a decir que el caso promedio es de alrededor de m = 40, que toma 177 bits para codificar.
Si utilizamos el argumento de amortización de antes, estamos codificando 400 "tableros de ajedrez" en 1734 bits, de modo que obtenemos que cada "tablero de ajedrez" ocupa 4.335 bits en el peor de los casos.
Tenga en cuenta que g = 0 denota un juego válido, aquel en el que la pieza en el cuadrado más bajo se mueve al cuadrado más bajo que puede.
Notas adicionales:
Si desea referirse a una posición específica en el juego, es posible que deba codificar el índice. Esto se puede agregar manualmente, por ejemplo, concatenar el índice al juego, o agregar un movimiento "final" adicional como el último movimiento posible en cada turno. Esto ahora puede dar cuenta de los jugadores que conceden, o 2 seguidos para denotar que los jugadores aceptaron un empate. Esto solo es necesario si el juego no terminó en jaque mate o estancado según la posición, en este caso está implícito. En este caso, lleva el número de bits necesarios en promedio a 356 y, en el peor de los casos, a 1762.