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; a
apunta a la posición de destino (que no contiene una pieza blanca). Luego o
se identifica la pieza que falta ( ): es la que no eliminamos de la cadena h
como 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 << "`, ";
}