Este desafio fará você contar "criaturas" no jogo de azulejos Palago.
Uma criatura é qualquer forma fechada que possa ser formada por peças Palago de cores correspondentes em uma grade hexagonal.
O jogo Palago consiste em peças como esta:
Esses ladrilhos podem ser girados , ou, de maneira alguma, e colocados em qualquer lugar em uma grade hexagonal. Por exemplo, aqui está uma criatura (vermelha) que requer 12 peças.
Desafio
O objetivo desse desafio é escrever um programa que use um número inteiro n
como entrada e calcule o número de criaturas (até rotação e reflexão) que requerem n
blocos. O programa deve ser capaz de lidar com até n=10
na TIO . Isso é código-golfe , e o menor número de bytes vence.
Dados de exemplo
Os valores devem corresponder aos dados encontrados na seção "Estimativas e contagens de criaturas" do site do criador . Nomeadamente
n | output
---+-------
1 | 0
2 | 0
3 | 1
4 | 0
5 | 1
6 | 1
7 | 2
8 | 2
9 | 9
10 | 13
11 | 37
12 | 81
fonte
n=10
TIO." - se esse é um requisito de velocidade de execução, use desafio de código em vez de golfe de código , este último se referindo a uma tarefa de otimização de byte puro.Respostas:
JavaScript (Node.js) ,
480417 bytes-63 bytes graças a @Arnauld. Uau.
Experimente online!
Em primeiro lugar, respeite Arnauld, cuja resposta me deu a inspiração para aprofundar. Eu tentei ser original com meus algoritmos, apesar de ter intencionalmente alterado parte do meu código para usar as mesmas variáveis que Arnauld, para que o código pudesse ser comparado com mais facilidade.
Procurando por hexágonos vazios
A busca por criaturas é:
A busca por hexágonos vazios revelou uma simetria interessante. Arnauld descobriu que uma das seis direções poderia ser ignorada, mas na verdade três em cada seis podem ser ignoradas!
Aqui está a chave e a direção originais de Arnauld:
Imagine que começamos no bloco A do tipo 1 no ponto azul. Parece que precisamos recuar em d = 0 ed = 5. No entanto, qualquer que seja o bloco colocado em d = 0, certamente terá uma saída em d = 4, que visitará o mesmo hexadecimal que sair do bloco A em d = 5. Essa é a descoberta de Arnauld, e foi o que me fez pensar.
Notar que:
Todo bloco que tem uma saída em d = 4 tem uma saída em d = 3
Todo bloco que pode ser inserido de d = 0 tem uma saída em d = 4
Isso significa que precisamos apenas considerar as direções 0,2,4. Quaisquer saídas nas direções 1,3,5 podem ser ignoradas porque os hexágonos alcançáveis nas direções 1,3,5 podem ser alcançados a partir de um hexadecimal adjacente usando as direções 0,2 ou 4.
Quão legal é isso!?
Direções rotuladas
Então, eu rotulo novamente as direções e os blocos assim (imagem de Arnauld editada):
Agora, temos a seguinte relação entre blocos, entradas e saídas:
Então, as saídas são: d + t == 2? (4-t)% 3: 2-t e 2 * t% 3
Rotações hexagonais e reflexões
Para rotações e reflexões, decidi tentar coordenadas axiais hexagonais x, y em vez das coordenadas do cubo x, y, z.
Nesse sistema, a rotação e a reflexão eram mais simples do que eu esperava:
Para obter todas as combinações que realizei: apodrecer, apodrecer, apodrecer, refletir, apodrecer, apodrecer
Código (480 bytes originais)
Código (Arnauld 417 bytes)
Arnauld gentilmente enviou uma economia de 63 bytes que usou truques que levaram algum tempo para entender. Como ele tem muitas edições interessantes, pensei em colocar o código abaixo (adicionei meus comentários) para que ele possa ser contrastado com a minha versão.
fonte
JavaScript (Node.js) ,
578 ... 433431 bytesQuão?
Direções e peças
Usamos os seguintes códigos para a bússola de 6 direções e os ladrilhos:
Assumimos que a criatura é azul.
Conexões
Precisamos de uma tabela para saber quais partes da criatura precisam ser conectadas a outras peças quando inserimos uma determinada peça em uma determinada direção:
Exemplo:
Uma vez achatado, isso fornece:
Coordenadas
Créditos: www.redblobgames.com
Isso facilitará o processamento de rotações e reflexões na etapa final do algoritmo.
Codificação de bloco
Os blocos são armazenados em uma lista, sem ordem específica. Isso significa que não precisamos nos preocupar com alguma alocação dinâmica em 2D e podemos iterar facilmente nos blocos existentes. A desvantagem é que, dadas coordenadas específicas, precisamos
find()
do bloco correspondente na lista.Algoritmo
Portanto, esse bloco é codificado como
[0,0,0,1,1]
.Em cada iteração, procuramos:
Ladrilhos com conexões ausentes: nesse caso, tentamos sucessivamente concluir a conexão com cada tipo de ladrilho.
Ladrilhos que já estão conectados, mas para os quais novas conexões precisam ser adicionadas porque foram alcançadas em uma direção diferente: nesse caso, atualizamos a máscara de direção (com um OR bit a bit) e forçamos uma nova iteração.
Se todas as conexões são válidas e atingimos o número solicitado de peças, ainda precisamos testar se é uma nova criatura ou apenas uma versão modificada de uma existente:
Aplicamos as seguintes transformações:
Classificamos os blocos de acordo com suas coordenadas e tipos. (Essa classificação é processada em ordem lexicográfica, o que é aceitável.)
Finalmente, coagimos a lista resultante a uma cadeia de chaves que pode ser comparada com as outras chaves.
Abortamos assim que uma chave conhecida é correspondida ou armazenamos a nova chave e incrementamos o resultado final se nenhuma das transformações levar a uma chave conhecida.
Comentado
fonte