É um cubo de Rubik?

25

Um venerado tempo de passagem dos pedantes é apontar que as imagens dos "Cubos de Rubik" (em camisetas, pôsteres etc.) não são realmente solucionáveis.

A primeira coisa que deve ser verificada é que o cubo é composto pelas peças certas. Para ser solucionável, um cubo precisa de seis cores, cada uma com nove quadrados. O cubo também precisa que cada unidade de borda e canto (esses são os cubos menores que compõem o cubo) sejam exclusivos. Não apenas devem ser únicas, mas se duas peças centrais estiverem opostas, nenhuma aresta ou peça de canto pode conter ambas as cores.

Depois de ter um cubo composto de todas as peças certas, você ainda precisa verificar se ele pode ser solucionado. Existem algumas regras aqui, então vou recorrer a um especialista para explicá-las, o spoiler abaixo explica como podemos fazer isso. Se você estiver interessado em resolver o problema por conta própria, não precisará visitar o site para entender ou participar desse desafio.

Explicação vinculada

Sua tarefa é pegar um padrão como entrada e determinar se é de fato um cubo de Rubik solucionável. Para ser solucionável, deve haver uma maneira de executar movimentos válidos em um cubo para que o cubo tenha apenas uma cor em cada face (e as diferentes faces tenham cores diferentes). A maioria dos cubos de Rubik tem uma cor padrão (branco é oposto a amarelo etc.). Você não pode assumir que o estado de resolução segue essa cor específica.

Um movimento válido é a rotação no sentido horário ou anti-horário de uma única face do cubo. Com a rotação da face do cubo, todos os quadrados adjacentes à face também são rotacionados, permanecendo conectados à face em que estavam tocando anteriormente.

IO

Você pode pegar o cubo de qualquer maneira razoável. Se seu idioma possui algum tipo de "face do cubo" embutido, bom para você, isso é bom como entrada; caso contrário, você pode pegar uma matriz 2D da rede, do cubo, 1 3 por 3 listas para cada face. Apenas seja razoável. Se você quiser saber se um formato específico é aceitável, faça um comentário ou envie um ping para mim no bate-papo, e eu adicionarei o desafio de declarar sua validade.

Seu formato de entrada precisa suportar apenas 9 cores possíveis.

Para saída, este é um problema de decisão, portanto, você deve gerar um valor constante para "Sim, este é um cubo de Rubik válido" e um valor constante diferente para "Não, este não é um cubo de Rubiks válido".


Isso é então as respostas serão pontuadas em bytes, com menos bytes sendo melhores.

Casos de teste

Aqui estão os casos de teste. Eles são formatados como a rede de um cubo com cada quadrado como uma única letra. Letras diferentes representam cores diferentes. Mais casos de teste podem ser adicionados mediante solicitação.

Solvable

   RRR
   RRR
   RRR
GGGWWWBBBOOO
GGGWWWBBBOOO
GGGWWWBBBOOO
   YYY
   YYY
   YYY


   GRR
   GRR
   ORW
WWRBWYBOOGGY
GGRBWGYBBOOO
OOGRWGYWWRBB
   WYO
   YYB
   YYB

Insolúvel

   RRR
   RRR
   RRR
GGGWWWBBBOOO
GGGWWWBBBOOO
GGGWYWBBBOOO
   YWY
   YYY
   YYY


   RRR
   RRR
   RRR
GGGWWWBBBOOO
GGGWWWBBBOOO
GGGWWWBBBOOO
   YWY
   YYY
   YYY


   RRR
   RRR
   GGG
GGYWYWRBBOBO
GGYWWWROBOOO
GGYWWWRBBOOO
   BBB
   YWY
   YYY


   RRW
   RRW
   GGG
GGYWWYEOBROO
GGYWWYEBBROO
GGOWWYWBBROO
   BBB
   YYW
   YYO
Assistente de Trigo
fonte
14
Sinto-me obrigado a salientar que o cubo de Rubik no seu avatar não é solucionável. Ele tem apenas quatro quadrados do lado de frente para nós, enquanto um cubo de Rubik normal deve ter 9. Sem mencionar os símbolos estranhos no topo dos quadrados.
DJMcMayhem
2
@DJMcMayhem Meus filhos têm cubos de Rubik com apenas quatro "sub-cubos".
Adám
2
@ H.PWiz Não, você não pode. Isso estava implícito nas minhas definições, mas explicarei na pergunta.
Wheat Wizard
2
Sua especificação não inclui uma descrição completa das três leis de paridade do cubo. 1. É impossível ter apenas uma aresta invertida 180 graus (mencionado) 2. É impossível ter apenas 1 canto torcido 120 graus (não mencionado) 3. É impossível ter uma permutação ímpar dos cubos (não mencionado). ) Estou votando atentamente até que isso seja resolvido. Consulte ryanheise.com/cube/cube_laws.html para obter uma explicação.
Level River St
4
@LevelRiverSt Observe que o cubo de Rubik é independente, qualquer um pode derivar nas formulações matemáticas e nas leis de paridade independentemente.
user202729

Respostas:

14

Cubicamente , 1664 1631 1089 bytes

⇒FD2F'R'D2RUR'D2RFD2F'U'
⇒Ff1F'
⇒LFf1F'L'
⇒F'f1F
⇒F2f1F2
⇒L'F2f1F2L
⇒D'F'f1FD
⇒LR'FLR'DLR'B2L'RDL'RFL'RU2
⇒LFf8F'L'
⇒R'F'f8FR
⇒Ff8F'
⇒F'f8F
⇒ULU'f8UL'U'
⇒U'R'Uf8U'RU
⇒F2f8F2
⇒Df15D'
⇒D'f15D
⇒D2f15D2
⇒UF2UF2D'L2B2U'B2DL2F2D2B2D2F2
⇒U'DL2UD'B2
⇒UF2UF2D'L2B2D'R2UR2F2D2B2U2B2
⇒BL'BU2D2F'RF'U2D2
⇒LD'F2U'B2U'RU2R'F2R2F2D'R2DF2D
⇒B2URB2D2B2RB2U'D'L2D'B2
⇒B2LF'U'B2UFL'R2B2U'D2L2D'B2U
⇒B2RB2D2B2RB2U'L2UD'F2U'F2B2
⇒D2R'FUB2U'F'RU2B2D'F2R2UF2UF2
⇒B2R2U'L'D2B2U2R'U2R2F2L2R2UR2
⇒D2L'B2U2F2RUL2U'F2R2U'R2U2F2DL2D'
⇒UB2U'L2DL2B2DB2D'B2
⇒BR'BL2B'RBL2B2
⇒UF2B2U'F2B2U'F2L2R2B2R2
⇒R2U'F2DR2UF2D'R2DF2R2D'F2
⇒U'F2DF2UL2F2DL2DF2L2D2F2
⇒U2D'L2U'F2L2U'B2L2R2U'L2B2
⇒F2D'R2U2L2B2UF2L2U2F2L2UF2R2
⇒[f1]3
⇒[f2f37]3
⇒[f3f38]3
⇒[f4f39]3
⇒[f5f40]3
⇒[f6f41]3
⇒[f7f42]3
⇒[f8f43]2
⇒[f9f44]2
⇒[f10f45]2
⇒[f11f46]2
⇒[f12f47]2
⇒[f13f48]2
⇒[f14f49]2
⇒[f15f50]2
⇒[f16f51]2
⇒[f17f52]2
⇒[f18f53]2
⇒[f19f54]2
⇒[f20f55]3
⇒[f21f56]4
⇒[f22f57]5
⇒[f23f58]6
⇒[f24f59]7
⇒[f25f60]8
⇒[f26f61]9
⇒[f27f62]9[f27f62]2
⇒[f28f63]9[f28f63]3
⇒[f29f64]9[f29f64]4
⇒[f30f65]2
⇒[f31f66]3
⇒[f32f67]4
⇒[f33f68]5
⇒[f34f69]6
⇒[f35f70]7
rs[f36f71]8

Saída se solucionável: Solved!Saída se não solucionável:
(vazio, sem saída)

A entrada deve ser formatada como um despejo de cubo cubicamente (consulte a Debugseção). Isso foi explicitamente permitido pelo OP.

Explicação

Esse programa adota a abordagem de usar o algoritmo do diabo para iterar todos os estados possíveis do cubo no mesmo grupo que o cubo resolvido. Se o cubo for solucionável, ele será resolvido em algum momento antes da conclusão do algoritmo (assumindo que o algoritmo que eu usei funcione corretamente).

Toda linha que começa com (0x84 na página de código do Cubically) é uma definição de função; essas funções são construídas uma para a outra para compor o algoritmo real do diabo. A primeira linha a ser executada é a última:

rs[f36f71]8

rlê um cubo de stdin e define o cubo de memória para ele. scoloca o intérprete em "solvemode", o que significa que ele sai e é impresso Solved!se o cubo for resolvido (após não ter sido resolvido) a qualquer momento. O restante dos comandos (que simplesmente se repetem f36f718 vezes) correspondem ao algoritmo final na parte inferior da página vinculada:

(D) = (CP) = (CPT8) = [(CPC8)(CPT7)]8 (3,847,762,288,469,010,006,992 moves)

(D) is the Devil's Algorithm. If you apply it to the cube, it will be solved at some point before you have done the algorithm once. As you can see, it is terribly long, nearly a thousand times more moves than there are possible positions.

Como posso executá-lo?

Você pode experimentá-lo online , mas esse link não funciona. O TIO atingirá o tempo limite quase definitivamente antes que esse algoritmo termine (o tempo de execução máximo para um intérprete é de 60 segundos). Se o cubo não puder ser solucionado, esse algoritmo levará até 11 milhões de anos para terminar o Cubically (com ~ 15,2 milhões de movimentos por segundo, que é o que o meu Cloud9 IDE obtém).

Além disso, você precisa de muita memória para executar três movimentos de sextilhões. Cubicamente pode executar cerca de 4 milhões de movimentos por segundo, mas o processo provavelmente será eliminado devido à memória supercomprometida . Ele morre após 15 segundos na minha VM com 512 MB de memória. Por que executar movimentos em uma matriz plana já alocada custa memória? Encontrou um vazamento de memória (ou vinte) e o corrigiu .

Aqui está uma versão muito mais legível que se comporta da mesma maneira.

Mas eu realmente quero ver que funciona!

O primeiro movimento real que é executado no algoritmo desse diabo é F2, portanto, o cubo mais rápido de resolver seria um embaralhado F2:

   000
   000
   555
113222133444
113222133444
113222133444
   000
   555
   555

Isso realmente é executado em 0,007 segundos no TIO .

Como isso pode ser melhorado?

Certamente existem mais algoritmos do diabo; Eu encontrei um que usa menos de um trigésimo dos movimentos que este faz. No entanto, isso custaria vários milhares de bytes (cerca de 100 MB a mais) e várias dezenas de horas de conversão de um complexo circuito hamiltoniano em código cubicamente.

Também é possível remover algumas das funções e colocá-las diretamente no loop na parte inferior. No entanto, vou sacrificar alguns bytes por alguma legibilidade.

Além disso, estou considerando uma modificação do comportamento de loop do Cubically para que eu possa repetir mais facilmente os algoritmos 7 ou 8 vezes (em vez de apenas codificá-los com as chamadas de função repetidas 7 ou 8 vezes na fonte). Ou eu vou trabalhar um pouco de mágica com o bloco de notas, e jogar golfe usando mais loops.

Observe que continuarei a otimizar tudo o que for possível no intérprete; portanto, isso poderá funcionar em um PC comum em algum momento no futuro!


Cubicamente, 2 bytes

r▦

Eu gosto mais da resposta acima, então estou adicionando isso como uma solução alternativa. Isso ocorre em menos de um segundo, em oposição a alguns milhões de anos.

r    read cube from standard in
 ▦   and solve it

Saída se o cubo for solucionável: (nada)
Saída se o cubo for insolúvel: Error: The cube has reached an unsolvable state.

MD XF
fonte
Isso funciona se trocarmos de lado? Por exemplo 2 é o oposto de 4 no despejo de cubo, funciona se 2 é o oposto de 5 e 4 é o oposto de 0?
Assistente de trigo
1
@WheatWizard Sim, o solvemode verifica se cada face possui um número inteiro único e se esse número inteiro é o único na face.
MD XF
Ok, como deveria. Eu não conhecia o Cubically o suficiente para saber se esse era o caso ou não da sua descrição.
Assistente de trigo
@WheatWizard Apenas certifique-se de que entendi corretamente - é isso (ao longo das linhas) a que você estava se referindo, certo?
MD XF
Sim. E deve ser solucionável.
Wheat Wizard
4

APL (Dyalog Classic) , 190 174 bytes

{∧/~∊(×1 2 3|+.-⌿↑⊃∘⍋¨¨¨a)({2|≢∪{⍵⌊⍵[⍵]}⍣≡⍵,0}¨⍳⌿↑⌽b)((∪≢∩)¨/b←(⊃∘⍋⌽⊢)¨¨¨a),6≢≢∪⊃⊃a←{c4⍴⊂⍬⋄c[+/1≠i],←(≠/×i←↑⍳33){⊂⌽⍣⍺⊢⍵~' '}¨,⌿(3|∘.+⍨⍳3)⍉⍤¯11 0 1\⍵1c}¨⍵(3 3∘⍴¨1 1∘⌷¨⍵)}

Experimente online!

O argumento é uma matriz 3x2 (linha0: frente para trás, linha1: esquerda direita, linha2: cima para baixo) de matrizes de caracteres 3x3. Retorna 1 para um cubo de Rubik solucionável, 0 caso contrário.

No link TIO, a função t, que não está incluída na contagem de caracteres, lê 9 linhas de entrada, as converte do formato de entrada padrão (uma rede) para a matriz 3x2 x 3x3 necessária, chama a solução e imprime OK se o resultado é como esperado.

O algoritmo divide o cubo fornecido em 26 cubos - seqüências de comprimento 3 (cantos), 2 (arestas) e 1 (centros). Também gera os 26 cubos de um cubo resolvido com os mesmos 6 cubos centrais. Todos os seguintes critérios devem ser atendidos:

  • não há duplicatas entre os 6 centros

  • os conjuntos de dados / cubinhos resolvidos corresponder, até a rotação - por exemplo, considerar 'WBR'e 'BRW'ao mesmo cubinho, mas não'BWR'

  • as paridades da permutação de canto e da borda são iguais

  • a soma modulo-3 dos índices de rotação de canto (por exemplo, tomando a letra "menor" Bcomo ponto de referência temos: 'BRW'→0, 'WBR'→1, 'RWB'→2) jogo entre os cubos de dados e resolvidos; mesmo para os cantos módulo 2

ngn
fonte