Tic-Tac-Toe y Ajedrez, con la menor cantidad de caracteres [distintos]

9

En esta forma del juego Tic-Tac-Chec, el objetivo es mover las piezas de ajedrez para obtener cuatro en una fila. Su objetivo aquí es averiguar si una posición tiene un movimiento ganador.

Reglas

Las reglas son similares, pero no idénticas, a las de Tic-Tac-Chec.

El tablero es de 4 por 4 cuadrados. Cada jugador tiene una torre, un obispo, un caballero y una reina. En tu turno, tienes dos opciones. Puedes mover una de tus piezas ya en el tablero, siguiendo las reglas estándar de ajedrez. O puede colocar una pieza que aún no está en el tablero, en cualquier lugar desocupado.

Si mueve una pieza existente a la pieza de un oponente, su pieza se retira del tablero y se devuelve a ellos. Sin embargo, no puede colocar una nueva pieza encima de la pieza de un oponente.

Tan pronto como un jugador tiene todas sus piezas en una fila (o columna, o diagonal), gana.

Desafío

Escriba un programa completo que acepte un tablero de STDIN y muestre si el jugador blanco puede ganar en el próximo turno.

Entrada

Cuatro cadenas de 4 caracteres cada una. Cada personaje es un espacio o una pieza de ajedrez. Solo se usan torres, obispos, caballeros y reinas, y como máximo puede aparecer uno de cada uno (por color). Ninguno de los jugadores ya tiene un cuatro en fila.

Puede elegir si acepta como entrada los símbolos Unicode para las piezas de ajedrez o las letras. Si elige letras, RBKQrepresenta piezas blancas y rbkqrepresenta piezas negras.

Salida

Si el jugador blanco puede ganar en el siguiente turno, salida trueo 1. De lo contrario, salida falseo 0.

Programa

Elija un número X. Su programa puede contener como máximo X caracteres distintos, y ningún personaje puede aparecer más de X veces.

Victorioso

La X más baja gana. En caso de empate, gana la menor cantidad de personajes.

Ejemplos

Estos ejemplos asumen que la entrada usa letras para representar las piezas.

rkb 


RB Q
true - the white player can place the knight to complete the bottom row.
-----------------------------------
rk    


RBbQ
false - the black bishop prevents the white knight from completing the row.
-----------------------------------
rk  
 K  

RBbQ
true - the white knight can capture the black bishop and complete the row.
-----------------------------------
rkRB

 Qb 
K   
true - the white rook can move down one to complete the diagonal.
Ypnypn
fuente
Entonces, ¿ va a ganar el código oOo ?
kennytm
@KennyTM Ningún personaje puede aparecer más de X veces que quedará inútil
Optimizer
@Optimizer OK, lo siento, leí mal las reglas.
kennytm
2
Si los ejemplos se pusieran en un formato más legible, es bastante difícil ver cuáles son las posiciones de las piezas y a qué color pertenecen.
Tally
¿Se permite el espacio en blanco?

Respuestas:

3

C, 53 caracteres distintos

Esto utiliza "#%&()*+,-./01234569;<=>BKQR[\]acdefghilmnoprstu{|}, espacio y nueva línea, distribuidos de la siguiente manera: 24 × \n, 33 × , 20 × ", 2 × #, 3 × %, 16 × &, 46 × (, 46 × ), 13 × *, 12 × +, 35 × ,, 10 × -, 2 × ., 2 × /, 18 × 0, 9 × 1, 4 × 2, 4 × 3, 4 × 4, 4 × 5, 3 × 6, 3 × 9, 34 × ;, 6 × <, 46 × =, 2 × >, 2 × B, 2 × K, 3 × Q, 2 × R, 8 × [, 1 × \, 8 × ], 39 × a, 23 × c, 5 × d, 19 × e, 15 × f, 1 × g, 22 × h, 36 × i, 5 × l, 1 × m, 35 × n, 9 ×o, 33 × p, 44 × r, 20 × s, 43 × t, 15 × u, 8 × {, 14 × |, 8 × }.

#include <stdio.h>
#include <string.h>
int n(char*a,char*e,int i)
{int c=0;for(;a<e;)c+=*a++=="\n"[0];return c==i;}

int p(char *t, int r, int u)
{char h[]=" RBQK";char*p=t+r;char*a;int c=0;
for(int i=0;i<=3;++i,p+=u){char*s=strchr(h,*p);if(s&&s==h==0){++c;*s=" "[0];}else{a=p;}}
if(c-3)return 0;
char o=h[strspn(h, " ")];
p=strchr(t, o);
if(p==0)return*a==" "[0];
if(p<a){char*s=p;p=a;a=s;}
if(o=="K"[0])return(p-a)==3&&n(a,p,1)||(p-a)==2+5&&n(a,p,1)||(p-a)==9&&n(a,p,2)||(p-a)==11&&n(a,p,2);
if((p-a)%5==0||n(a,p,0))return (int)strchr("RQ", o);
return((p-a)%4==0&&n(a,p,(p-a)/4)||(p-a)%6==0&&n(a,p,(p-a)/6))&&strchr("BQ",o);}

int f(char *t)
{for(int i=0;i<4;++i)if(p(t,i,5)||p(t,i*5,1))return 1;
return p(t,0,6)||p(t,3,4);}

int main()
{char t[20];fread(t,19,1,stdin);t[19]=0;
if(f(t))puts("true");else puts("false");}

Explicación

#include <stdio.h>
#include <string.h>

/* count newlines */    
int n(char *a, char *e)
{
    int c = 0;
    for (;a<e;) c += *a++=='\n';
    return c;
}

/* check a single row, column or diagonal */
int p(char *t, int start, int stride)
{
    char h[] = " RBQK"; /* pieces not in line */
    char *p = t+start;
    char *a;
    int c = 0;
    for (int i = 0;  i <= 3;  ++i, p+=stride) {
        char *s = strchr(h, *p);
        if (s && s == h == 0) {
            /* a white piece */
            ++c;
            *s = " "[0];
        } else {
            /* candidate target square */
            a = p;
        }
    }

    /* did we find three white pieces in this line? */
    if (c != 3)
        return 0;

    char o = h[strspn(h, " ")];

    p = strchr(t, o);

    if (p==0)
        return *a == " "[0];

    /* ensure a < p */
    if (p < a) {
        char *s = p;
        p = a;
        a = s;
    }

    /* knight moves */
    if (o == 'K')
        return (p-a)==3 && n(a,p)==1
            || (p-a)==7 && n(a,p)==1
            || (p-a)==9 && n(a,p)==2
            || (p-a)==11 && n(a,p)==2;

    /* rook moves */
    if ((p-a)%5 == 0 || n(a,p)==0)
        return 0==strchr("RQ", o)==0;

    /* bishop moves */
    return
        ((p-a)%4==0 && n(a,p)==(p-a)/4 ||
         (p-a)%6==0 && n(a,p)==(p-a)/6)
        && strchr("BQ", o);
}

/* main predicate function */
int f(char *t)
{
    /* try rows and columns */
    for (int i = 0;  i < 4;  ++i)
        if (p(t, i, 5) || p(t, i*5, 1))
            return 1;
    /* try diagonals */
    return p(t, 0, 6) || p(t, 3, 4);
}

int main()
{
    char t[20];
    fread(t, 19, 1, stdin);
    t[19]=0;
    if (f(t)) puts("true"); else puts("false");
}

Funciona buscando una fila, columna o diagonal que contenga tres de las piezas blancas; aapunta a la posición de destino (que no contiene una pieza blanca). Luego ose identifica la pieza que falta ( ): es la que no eliminamos de la cadena hcomo la vimos.

Si la pieza no está en el tablero, debe estar en la mano y solo se puede jugar en un espacio. De lo contrario (si lo encontramos en el tablero), debe estar en una posición en la que pueda moverse hacia la casilla objetivo. Como los movimientos son reversibles, intercambiamos si es necesario, de modo que a < p.

Primero probamos los movimientos de los caballeros: hay cuatro movimientos legales hacia abajo, y evitamos envolver los bordes izquierdo / derecho del tablero verificando el número de líneas nuevas que pasamos.

Después de eso, probamos los movimientos de torre, y luego los movimientos de alfil, usando un algoritmo similar (y una reina puede usar cualquiera de estos movimientos).

Programa de prueba

int expect_true(char *board)
{
    if (strlen(board) != 19) {
        fprintf(stderr, "Wrong length board:\n%s\n\n", board);
        return 1;
    }
    if (!f(board)) {
        fprintf(stderr, "Expected true, but got false, for\n%s\n\n", board);
        return 1;
    }
    return 0;
}

int expect_false(char *board)
{
    if (strlen(board) != 19) {
        fprintf(stderr, "Wrong length board:\n%s\n\n", board);
        return 1;
    }
    if (f(board)) {
        fprintf(stderr, "Expected false, but got true, for\n%s\n\n", board);
        return 1;
    }
    return 0;
}


int main()
{
    return
        + expect_true("rkb \n"
                      "    \n"
                      "    \n"
                      "RB Q")
        + expect_false("rk  \n"
                       "    \n"
                       "    \n"
                       "RBbQ")
        + expect_true("rk  \n"
                      " K  \n"
                      "    \n"
                      "RBbQ")
        + expect_true("rk  \n"
                      "    \n"
                      "K   \n"
                      "RBbQ")
        + expect_true("rkRB\n"
                       "    \n"
                       " Qb \n"
                       "K   ")
        + expect_true("rk  \n"
                      "    \n"
                      "K   \n"
                      "RBbQ");
}

Programa de conteo (en C ++)

#include<algorithm>
#include<iostream>
#include<map>

int main()
{
    std::map<char,int> m;
    for (int c;  (c = getchar()) != EOF; )
        ++m[c];

    for (auto e: m)
        std::cout << e.first;

    std::cout << "\n distributed as follows: ";
    for (auto e: m)
        std::cout << e.second << "×`" << e.first << "`, ";
}
Toby Speight
fuente
1
Sugerir 6+3para 9y 16+3para19
ceilingcat