Quebra-cabeça do desafio das rainhas do xadrez
O desafio é colocar N rainhas em um tabuleiro NxN de forma que nenhuma rainha possa "atacar" qualquer outra rainha. As rainhas podem se mover horizontalmente, verticalmente ou ao longo de uma diagonal (45%). O diagrama a seguir mostra uma solução para N=4
rainhas.
________________
| | | Q | |
|___|___|___|___|
| Q | | | |
|___|___|___|___|
| | | | Q |
|___|___|___|___|
| | Q | | |
|___|___|___|___|
Uma solução para este quebra-cabeça pode ser representada como uma permutação especial da lista [1,2,3,4]. Por exemplo, a solução ilustrada acima pode ser representada como [3,1,4,2], o que significa que, na primeira linha coloque uma rainha na coluna 3, na segunda linha coloque uma rainha na coluna 1, etc. Para testar se uma dada permutação é uma solução, é necessário calcular se a permutação tem (ou representa uma situação onde) duas ou mais rainhas estão na mesma diagonal. A própria representação evita duas ou mais rainhas na mesma linha ou coluna. Duas rainhas estão na mesma / diagonal se e somente se a soma da linha e coluna for a mesma para cada uma; eles estão na mesma diagonal se e somente se a diferença de sua linha e coluna for o mesmo número. O programa Prolog a seguir contém os detalhes; assuma que os predicados 'perm' e 'takeout' são definidos como na seção 2.7.
solve(P) :-
perm([1,2,3,4,5,6,7,8],P),
combine([1,2,3,4,5,6,7,8],P,S,D),
all_diff(S),
all_diff(D).
combine([X1|X],[Y1|Y],[S1|S],[D1|D]) :-
S1 is X1 +Y1,
D1 is X1 - Y1,
combine(X,Y,S,D).
combine([],[],[],[]).
all_diff([X|Y]) :- \+member(X,Y), all_diff(Y).
all_diff([X]).
Observe a inclusão do arquivo 'lists.pro' discutido na seção 2.6. Esta é uma especificação simples e tranquila que usa 'perm' para gerar soluções possíveis para o quebra-cabeça. Um exemplo de objetivo é
?- solve(P).
P = [5,2,6,1,7,4,8,3] ;
P = [6,3,5,7,1,4,2,8] ;
...
?- setof(P,solve(P),Set), length(Set,L).
...
L = 92
O último objetivo reflete o fato de que existem 92 soluções distintas para o quebra-cabeça do desafio das rainhas para um tabuleiro 8x8. Uma ineficiência que esse programa sofre é que cada permutação é completamente calculada antes de ser verificada para ver se representa uma solução para o quebra-cabeça. É fácil perceber que isso não é necessário. Por exemplo, suponha que uma "solução parcial" P = [1,3,2, ...] seja considerada. Os cálculos de linha e coluna já mostram que o "2" não é um movimento seguro! Uma solução que evita essa ineficiência é considerada na seção 2.13.
Veja Também
- Código do Prolog para esta seção.
- 2.6 Dados e relações em árvores
- 2.7 Listas em Prolog
- 2.12 Conjunto de respostas
- 2.13 Gerador de Tabela Verdade
- Prolog Tutorial Sumário