C, 53 caracteres distintos
Isso usa "#%&()*+,-./01234569;<=>BKQR[\]acdefghilmnoprstu{|}
espaço e nova linha, distribuídos da seguinte forma: 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
, 2 × , 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");}
Explicação
#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");
}
Ele trabalha procurando uma linha, coluna ou diagonal contendo três das peças brancas; a
aponta para a posição de destino (ainda não contém uma peça branca). Então a peça que falta ( o
) é identificada - é a que não removemos da corda h
como a vimos.
Se a peça não estiver no tabuleiro, ela deve estar na mão e só pode ser jogada em um espaço. Caso contrário (se o encontrarmos no quadro), ele deverá estar em uma posição em que possa se mover para o quadrado alvo. Como os movimentos são reversíveis, trocamos, se necessário, para que a < p
.
Testamos os movimentos de cavaleiro primeiro - há quatro movimentos legais para baixo e evitamos envolver as bordas esquerda / direita do quadro verificando o número de novas linhas que passamos.
Depois disso, testamos movimentos de torre e, em seguida, movimentos de bispo, usando um algoritmo semelhante (e uma rainha pode usar qualquer um desses movimentos).
Programa de teste
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 contagem (em 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 << "`, ";
}