Existe uma variante do conhecido problema das rainhas N que envolve rainhas e cavaleiros e é considerado "consideravelmente mais difícil" 1 . A declaração do problema é a seguinte:
Você deve colocar um número igual de cavaleiros e rainhas em um tabuleiro de xadrez, de modo que nenhuma peça ataque outra peça. Qual é o número máximo de peças que você pode colocar no quadro e quantas maneiras diferentes você pode fazer isso?
Neste desafio do código-golfe , você receberá uma entrada n entre 3 e 32 (da maneira mais adequada para o seu idioma). Para um dado n , pode haver zero ou mais soluções para o problema acima. Caso não exista solução, você não deve produzir / devolver nada ( nulo , string vazia , false , ...). Caso contrário, você deve fornecer dois resultados:
- Uma placa de solução (veja abaixo) para o tamanho n, em que não é possível adicionar uma peça de xadrez da rainha ou do cavaleiro sem que nenhuma peça esteja sendo atacada. Deve haver um número igual de rainhas e cavaleiros .
- A fonte de um programa a ser executado que não aceita entrada e fornece (i) outra solução (ou nada ) para o mesmo tamanho n , no mesmo formato, bem como (ii) outro programa para a próxima solução (e assim por diante) ...)
Observe que:
- A sequência de programas nunca deve retornar a mesma placa duas vezes, deve cobrir todas as soluções possíveis para o problema de tamanho n e, eventualmente, deve terminar (não produzindo saída).
- Você pode retornar dois valores, retornar um e imprimir o outro ou imprimir os dois valores de retorno.
- No entanto , se você imprimir a placa e o próximo programa, a placa não deve ser considerada parte do próximo programa (eu recomendo imprimir a placa em comentário ou usar os fluxos de saída e erro padrão).
- O valor do programa como um retorno deve ser uma sequência, não um encerramento.
Formato da placa
- Uma placa é um quadrado de tamanho n .
- Uma célula do tabuleiro pode estar vazia, uma rainha ou um cavaleiro.
- Você deve escolher valores distintos para cada tipo de célula (ou seja, você pode usar outros símbolos além de Q, N ao imprimir o quadro).
- Se você retornar um quadro não-string, ele deverá ser uma coleção ordenada dos n 2 valores do quadro (por exemplo, matriz, vetor ou lista na ordem principal de linha / coluna, ...).
Se você imprimir o quadro, poderá imprimi-lo ao quadrado ou como uma linha. Por exemplo, uma placa de solução do tamanho 4 pode ser impressa da seguinte maneira (espaços não necessários; símbolos a seu critério):
Q - - - - - - - - - - - - - N -
Se você sente isso, também pode gerar:
♛ · · · · · · · · · · · · · ♞ ·
... mas isso é suficiente:
Q-------------N-
Não importa se você itera pelas células em uma ordem principal ou de coluna, porque existem soluções simétricas. Por exemplo, as soluções para n = 4 são:
Q------N-------- Q----------N---- Q------------N-- Q-------------N- -Q----------N--- -Q------------N- -Q-------------N --Q---------N--- --Q----------N-- --Q------------N ---QN----------- ---Q----N------- ---Q---------N-- ---Q----------N- ---NQ----------- ----Q------N---- ----Q----------N N------Q-------- -------QN------- -------Q----N--- ---N----Q------- -------NQ------- --------Q------N N----------Q---- ----N------Q---- -----------QN--- -N----------Q--- --N---------Q--- -------N----Q--- -----------NQ--- N------------Q-- --N----------Q-- ---N---------Q-- N-------------Q- -N------------Q- ---N----------Q- -N-------------Q --N------------Q ----N----------Q --------N------Q
Você também pode olhar para as soluções para n = 5 como matrizes ; as placas contém #
, q
e n
símbolos, que são células vazias de diferentes tipos (ver minha resposta abaixo). Eu conto 2836 placas para n = 6 , como na resposta de Sleafar (eu introduzi um bug ao reduzir a contagem de bytes, mas está corrigido agora).
Muito obrigado a Sleafar por encontrar não um, mas dois bugs no meu código.
Ponto
O código mais curto em bytes vence.
Medimos o tamanho do primeiro programa, o que aceita n .
1 . Queens and Knights , de Roger KW Hui (cuidado! Contém uma solução)
-------------------------N--------Q-
é inválida porque mais peças podem ser adicionadas :)Q--------N---------------N--------Q-
.Respostas:
Groovy, 515 bytes
Teste
Forneça n como um argumento de linha de comando:
A primeira linha da saída é sempre uma solução como comentário (0 = vazio, 1 = rainha, 2 = cavaleiro), seguido pelo código na segunda linha:
O script a seguir pode ser usado para teste automatizado (forneça n como argumento novamente):
Como tentei tornar a solução a menor possível, ela é muito lenta (veja os detalhes abaixo). Testei apenas n = 4 com esta versão para ver se a quineificação funciona.
Resultados
n = soluções 4: 40 ( formato convertido )
n = soluções 5: 172 ( formato convertido )
n = soluções 6: 2836 ( formato convertido )
Algoritmo
Esta é uma versão não quine da solução, levemente não destruída:
Quineificação
Eu usei uma abordagem muito simples aqui para manter o tamanho do código baixo.
A variável X mantém o índice da solução para imprimir a seguir. Y mantém uma cópia modificada do algoritmo acima, usada para calcular todas as soluções e, em seguida, selecionar apenas uma delas, razão pela qual é tão lenta. A vantagem desta solução é que ela não requer muito código adicional. O código armazenado em Y é executado com a ajuda da classe Eval (um quine verdadeiro não é necessário).
O código modificado imprime a solução apontada por X , aumenta X e anexa uma cópia de si mesma:
Também tentei produzir todas as soluções como código para o segundo passo, mas para n = 6 estava produzindo muito código para o Groovy lidar.
fonte
Lisp comum, 737
auto-resposta
Exemplo
Cole o acima no REPL, que retorna um objeto de função:
Chame-o (a estrela está vinculada ao último valor retornado):
Isso imprime o seguinte na saída padrão:
Além disso, o valor retornado por esta função é:
... que é uma matriz literal. O número 5 representa rainhas, 6 é para cavaleiros e qualquer outra coisa representa uma célula vazia, exceto que há mais informações armazenadas internamente. Se copiarmos e colarmos a função retornada para a repl, obteremos uma nova função.
E podemos chamá-lo, sem argumentos:
Essa chamada retorna uma nova solução
#(5 0 0 0 0 0 0 2 0 0 0 6 0 0 2 0)
e a fonte de outra função (não mostrada aqui). Caso a função original ou a última gerada não encontre uma solução, nada será impresso e nada será retornado.Valores internos
Eu costumava gerar poucas soluções. Agora, propago qual célula é segura para uma rainha e para um cavaleiro, independentemente. Por exemplo, aqui está uma saída para n = 5 com impressão bonita:
Quando colocamos a rainha
Q
, as posições afastadas por um cavaleiro desta rainha ainda são seguras para rainhas e são indicadasq
. Da mesma forma, cavaleiros que são alcançáveis apenas por rainhas são seguros para outros cavaleiros. Os valores são bit a bit e -ed para representar os movimentos possíveis e algumas células são alcançáveis por nenhum tipo de peça.Mais precisamente, aqui está a sequência de placas que levam à seguinte solução (da esquerda para a direita), onde as células livres são gradualmente restringidas com valores diferentes:
Abordagem não quine
Versão comentada e não-gasta
Duplicatas e erros
Minha primeira solução gerou soluções duplicadas. Para resolvê-lo, apresentei dois contadores para rainhas e cavaleiros. O contador para rainhas (respectivamente cavaleiros) mantém o controle da primeira posição no tabuleiro onde existe uma rainha (resp. Cavaleiro): eu adiciono uma rainha (resp. Cavaleiro) apenas nas posições que seguem essa posição mínima.
Esse método me impede de revisar soluções que já foram encontradas em iterações anteriores, porque eu itero com uma posição crescente de rainha (resp. Cavaleiro).
No entanto, Sleafar notou que havia soluções para as quais havia espaço para rainhas e cavaleiros, o que é contrário às regras. Por um tempo, tive que voltar a uma pesquisa normal e armazenar todas as soluções conhecidas para evitar duplicatas, que pareciam muito caras (tanto em termos de bytes quanto de uso de memória).
Em vez disso, eis o que faço agora: quando um quadro de soluções em potencial é encontrado, tento adicionar exatamente uma rainha e uma cavaleiro, sem levar em conta os contadores (ou seja, para todas as células do quadro). Se isso for possível, a placa atual é uma duplicata da anterior e eu rejeito a solução.
Testes
Quine-ification
Tive idéias diferentes para fazer sucessivos cálculos. O mais fácil é provavelmente gerar todas as soluções primeiro como uma lista de strings e escrever quines seqüenciais que saem dessa lista a cada geração. No entanto, isso não parecia ser mais curto do que a abordagem atual. Como alternativa, tentei reescrever o código recursivo com uma pilha personalizada e despejar todas as variáveis de estado toda vez que encontro uma solução; o objetivo é que a próxima etapa possa ser processada como uma continuação da etapa atual. Talvez isso seja mais adequado para uma linguagem baseada em pilha. O atual é bastante simples e depende das variáveis do leitor Common Lisp, que são sempre divertidas de usar.
fonte