Em alguns telefones antigos da Nokia, havia uma variação dos quinze quebra-cabeças chamados Rotação. Nesta variação, em vez de deslizar um bloco de cada vez, você girou quatro blocos de cada vez em uma direção.
Neste jogo, você começaria com um quadro como este:
4 9 2
3 5 7
8 1 6
E girando o bloco inferior esquerdo duas vezes no sentido horário e o bloco superior esquerdo uma vez no sentido horário, você obtém o seguinte:
4 9 2
8 3 7
1 5 6
4 9 2
1 8 7
3 5 6
1 4 2
8 9 7
3 5 6
e o 1
ladrilho estaria no canto superior esquerdo, onde deveria estar. Eventualmente, depois de mais alguns movimentos, você acabaria com:
1 2 3
4 5 6
7 8 9
qual é a configuração "original".
Sua tarefa é criar um programa que terá como entrada uma grade de números 3x3 de 1 a 9 (em qualquer formato que você escolher) e retorne como saída uma sequência de movimentos que representam os movimentos que você deve executar para retornar o quadro ao seu original. configuração (novamente, em qualquer formato que você escolher). Os movimentos legais são definidos como mover o bloco [superior / inferior] - [esquerdo / direito] de 4 peças [no sentido horário / anti-horário].
Seu programa deve ser capaz de resolver todas as grades 3x3 possíveis (todas as permutações são solucionáveis).
O código mais curto para fazer isso vence.
fonte
...and return as output a sequence of moves representing the moves you must take to return the board back to its original
Isso significa "voltar para1 2 3\n4 5 6\n7 8 9
"? Não sei bem como ler isso.Respostas:
GolfScript, 39/83 bytes
Velocidade vs tamanho
A versão com tamanho otimizado escolhe aleatoriamente as rotações no sentido horário até que a permutação desejada seja alcançada. Isso é suficiente, uma vez que uma rotação no sentido anti-horário é equivalente a três rotações consecutivas no sentido horário do mesmo quadrado.
A versão com velocidade otimizada faz o mesmo, exceto pelo seguinte:
Se o número 1 estiver no canto superior esquerdo, ele não girará mais o quadrado superior esquerdo.
Se o número 9 estiver no canto inferior direito, ele não girará mais o quadrado inferior direito.
As etapas para trocar as posições 7 e 8 são codificadas permanentemente, portanto, existem duas posições que permitem a quebra do loop.
Além de alterar o algoritmo, a versão com velocidade otimizada consegue a rotação de maneira direta, enquanto a versão com tamanho otimizado usa a classificação incorporada do GolfScript por mapeamento. Ele também codifica o estado final (para comparação) em vez de classificar o estado em todas as iterações.
A versão otimizada para velocidade requer menos iterações e cada iteração é muito mais rápida por si só.
Benchmarks
Eu usei o seguinte código para randomizar as posições dos números e executar testes, descomentando a linha correspondente à versão a ser testada:
A saída mostra o número mínimo e máximo de etapas necessárias para ordenar os números, a média e a mediana de todas as execuções, bem como o tempo decorrido em segundos:
Na minha máquina (Intel Core i7-3770), o tempo médio de execução da versão com tamanho otimizado foi de 3,58 minutos. O tempo médio de execução da versão com velocidade otimizada foi de 0,20 segundos. Assim, a versão com velocidade otimizada é aproximadamente 1075 vezes mais rápida.
A versão com velocidade otimizada produz 114 vezes menos rotações. A execução de cada rotação é 9,4 vezes mais lenta, principalmente devido à atualização do estado.
I / O
A saída consiste em números de 3 bits. O MSB é definido para rotações no sentido anti-horário, o bit do meio é definido para os quadrados inferiores e o LSB é definido para os quadrados direitos. Assim, 0 (4) é o quadrado superior esquerdo, 1 (5) o superior direito, 2 (6) o inferior esquerdo e 3 (7) o inferior direito.
A versão com velocidade otimizada imprime todas as rotações em uma única linha. A versão com tamanho otimizado imprime uma rotação por linha, seguida pela posição final dos números.
Para a versão com velocidade otimizada, a entrada deve gerar uma matriz contendo os números de 1 a 9 quando avaliados. Para a versão com tamanho otimizado, a entrada deve ser uma sequência sem nova linha final; não é avaliado.
Exemplo é executado:
Código com tamanho otimizado
A atualização do estado é alcançada da seguinte maneira:
A rotação 2 produz o número inteiro 3 após adicionar 1. Se o estado for "123456789", o fatiamento do estado produzirá "456789".
Logo antes de executar "$", os elementos mais altos da pilha são:
"$" Executa o bloco uma vez para cada elemento da matriz a ser classificado, depois de pressionar o próprio elemento.
O índice de 1 em “[4 5 6 7 8 9]” é -1 (não está presente); portanto, o último elemento de "1420344440" é pressionado. Isso gera 48, o código ASCII correspondente ao caractere 0. Para 2 e 3, 48 também é pressionado.
Os números inteiros pressionados para 4, 5, 6, 7, 8 e 9 são 49, 52, 50, 48, 51 e 52.
Após a classificação, o primeiro elemento do estado será um dos elementos com 48; o último será um daqueles com 52 anos. A classificação interna é instável em geral, mas verifiquei empiricamente que é estável nesse caso específico.
O resultado é "[1 2 3 7 4 6 8 5 9]", que corresponde a uma rotação no sentido horário do quadrado inferior esquerdo.
Código otimizado para velocidade
Observe que as rotações 3, 0, 7, 6 e 4 trocam os elementos nas posições 7 e 8, sem alterar as posições dos sete elementos restantes.
fonte
Python com Numpy - 158
A entrada deve ter o seguinte formato:
Cada linha de saída é um movimento codificado em strings como
trw
oublc
e deve ser lido da seguinte maneira:t
: topob
: inferiorl
: esquerdar
: certoc
: sentido horáriow
: anti-horário (widdershins)Este programa executa movimentos aleatórios até que a configuração de destino seja atingida. Sob o pressuposto aproximado de que todo movimento tem uma probabilidade independente de 1/9! para atingir a configuração de destino¹, o número de rotações antes que uma solução seja exponencialmente distribuída com uma média (ou seja, o número médio de movimentos) de 9! ≈ 3,6 · 10⁵. Isso está de acordo com um pequeno experimento (20 execuções).
9! sendo o número total de configurações.
fonte
Solução com menos movimentos de C ++ - largura em primeiro lugar (caracteres de 1847)
Depois de pensar um pouco mais, acho que fiz isso de maneira muito mais eficiente e sensata. Essa solução, embora certamente não esteja ganhando esse golfe, é a única que tenta encontrar o menor número de rotações que resolverá o quadro. Até agora, ele resolve todos os tabuleiros aleatórios que joguei em nove ou menos movimentos. Ele também tem um desempenho significativamente melhor que o meu último e, espero, aborda os comentários de Dennis abaixo.
A partir da solução anterior, a maior mudança foi mover o histórico principal do estado da placa (BS) para uma nova classe que armazena o histórico em uma determinada profundidade (DKH). Sempre que o aplicativo faz uma mudança, ele verifica o histórico nessa profundidade e em todas as profundidades anteriores para ver se alguma vez foi avaliado; nesse caso, não será adicionado à fila novamente. Isso parece reduzir significativamente o armazenamento na fila (removendo todo esse histórico do próprio estado da placa) e, portanto, reduz praticamente todas as podas estúpidas que eu tive que fazer para impedir que o código fique sem memória. Além disso, ele roda muito mais rápido, pois há muito menos para copiar na fila.
Agora, é uma primeira pesquisa simples e abrangente nos vários estados do fórum. Além disso, como quero dizer, eu quero alterar o conjunto de teclas (atualmente armazenado como conjunto de números na base-9, cada um dos quais é calculado pela BS :: key como a representação da placa-base-9) para um bitset tendo 9! bits parece desnecessário; embora eu tenha descoberto como calcular uma chave no "sistema de números fatoriais" que poderia ter sido usada para calcular o bit no bitset para testar / alternar.
Portanto, a solução mais nova é:
fonte
int[]
paraconst int[]
e definir o sinalizador-fpermissive
.CJam - 39
Outro solucionador aleatório :)
Ele pega uma sequência como 492357816 e gera uma série (longa) de dígitos de 0 a 3, cada um representando uma rotação no sentido horário de um bloco: 0 = superior esquerdo, 1 = superior direito, 2 = inferior esquerda, 3 = canto inferior direito.
Breve explicação:
4mr
gera um número aleatório de 0 a 3_1>+
incrementa o número se for maior que 1 (então terminamos com 0, 1, 3 ou 4 - os índices iniciais dos 4 blocos)m<
gira a string para a esquerda (como 492357816 -> 923578164, não a rotação do bloco) para fazer com que o bloco gire na primeira posição,[Z0Y4X]\f=
faz a rotação do bloco que afeta os 5 primeiros caracteres, como 12345 -> 41352;X = 1, Y = 2, Z = 3, de modo que [Z0Y4X] é realmente [3 0 2 4 1] e esses são os índices baseados em 0 dos blocos girados copiam
5>
o restante da sequênciam>
gira a sequência (modificada) de volta para o direito__$>
verifica se a sequência está classificada (é a condição de parada)fonte
Mathematica, 104 caracteres
Podemos interpretar a tarefa na linguagem dos grupos de permutação. As quatro rotações são apenas quatro permutações que geram o grupo simétrico S 9 , e a tarefa é apenas escrever uma permutação como um produto dos geradores. O Mathematica possui uma função interna para fazer isso.
Exemplo:
Entrada:
Resultado:
1
: canto superior esquerdo no sentido horário2
: canto superior direito no sentido horário3
: canto inferior direito no sentido horário4
: canto inferior esquerdo no sentido horário-1
: superior esquerdo no sentido anti-horário-2
: canto superior direito no sentido anti-horário-3
: canto inferior direito no sentido anti-horário-4
: canto inferior esquerdo no sentido anti-horáriofonte