Em nossos amigos do Puzzling.SE , foi publicado o seguinte quebra-cabeça: Esse quebra-cabeça cromático é sempre solucionável? by Edgar G. Você pode reproduzi-lo aqui .
Explicação do quebra-cabeça
Dada uma m x n
grade com peças de três cores diferentes, você pode selecionar duas peças adjacentes , se as cores forem diferentes . Esses dois ladrilhos são convertidos para a terceira cor, ou seja, a única cor não representada por esses dois ladrilhos. O quebra-cabeça é resolvido se todas as peças tiverem a mesma cor . Aparentemente, pode-se provar que este quebra-cabeça é sempre solucionáveis, se nem m
nem n
são divisíveis por 3.
Obviamente, isso implora por um algoritmo de solução. Você escreverá uma função ou programa que resolve esse quebra-cabeça. Observe que funções com 'efeitos colaterais' (ou seja, a saída está ativada stdout
e não em algum valor de retorno de tipo de dados estranho) são explicitamente permitidas.
Entrada e Saída
A entrada será uma m x n
matriz consistindo dos inteiros 1
, 2
e 3
(ou 0
, 1
, 2
se conveniente). Você pode receber esta entrada em qualquer formato são. Ambos m
e n
são >1
e não são divisíveis por 3. Você pode assumir que o quebra-cabeça não foi resolvido
Você então resolverá o quebra-cabeça. Isso envolverá uma seleção repetida de dois blocos adjacentes a serem 'convertidos' (veja acima). Você produzirá as duas coordenadas desses blocos para cada etapa executada pelo algoritmo de resolução. Isso também pode estar em qualquer formato de saída sã. Você pode escolher entre a indexação com base em 0 e com base em 1 de suas coordenadas e se as linhas ou colunas são indexadas primeiro. Por favor, mencione isso em sua resposta.
Seu algoritmo deve ser executado dentro de um prazo razoável no gabinete 8x8 original. Forçar brutalmente completamente é explicitamente proibido, ou seja, seu algoritmo deve ser executado O(k^[m*(n-1)+(m-1)*n])
com k
o número de etapas necessárias para a solução. A solução, no entanto, não precisa ser ideal. A prova fornecida na pergunta vinculada pode fornecer uma idéia de como fazer isso (por exemplo, primeiro faça todas as colunas usando apenas blocos adjacentes verticalmente e, em seguida, todas as linhas)
Casos de teste
Nesses casos de teste, as coordenadas são baseadas em 1 e as linhas são indexadas primeiro (como MATLAB / Octave e provavelmente muitas outras).
Input:
[1 2]
Output: (result: all 3's)
[1 1],[1,2]
Input:
[ 1 2
3 1 ]
Output: (result: all 1's)
[1 1],[2 1] (turn left column into 2's)
[2 1],[2 2] (turn right column into 3's)
[1 1],[1 2] (turn top row into 1's)
[2 1],[2 2] (turn bottom row into 1's)
Input:
[1 2 3 2
3 2 1 1]
Output: (result: all 3's)
[1 1],[1 2]
[1 3],[1 4]
[1 2],[1 3]
[1 1],[1 2]
[1 2],[1 3]
[1 1],[1 2]
[1 3],[1 4]
[2 1],[2 2]
[1 1],[2 1]
[1 2],[2 2]
[1 3],[2 3]
[1 4],[2 4]
Se desejar, posso postar uma pasta de casos de teste maiores, mas acho que isso deve ser suficiente.
fonte
Respostas:
Ruby, 266 bytes
Mais ou menos, apenas uma porta da solução Octave, exceto que ela resolve primeiro as linhas, em vez das colunas. Entrada é uma matriz de matrizes, com as matrizes internas sendo as linhas. Movimentos de saída são
[row, column, row, column]
. Suíte de testeUngolfed com explicação
fonte
intersect
É uma palavra-chave, tais volumosos)intersect
, não sei se você pode consertar isso da maneira como o meu funciona, porque Rubyfind
basicamente opera em funções, e suafunction
palavra-chave é igualmente volumosa.find
- obrigado! Ainda assim, em nenhum lugar perto de bater-lhe ...Oitava,
334313 bytesComo o desafio pode parecer um pouco assustador, apresento minha própria solução. Não provei formalmente que esse método funciona (acho que tudo se resume a provar que o algoritmo nunca ficará preso em um loop), mas até agora funciona perfeitamente, executando testes de 100x100 em 15 segundos. Observe que eu escolhi usar uma função com efeitos colaterais em vez de uma que retorna todas as coordenadas, pois isso me salvou alguns bytes. As coordenadas são de linha principal, com base em 1 e formatadas como
row1 col1 row2 col2
. As cores de entrada são0,1,2
uma vez que isso funciona melhor commod
, ao custo de ter que usar emnumel
vez dennz
. Versão em golfe: Editar: salvou mais alguns bytes usando uma técnica da resposta de Kevin Lau.Exemplo de GIF do algoritmo de resolução:
Versão não destruída:
fonte
Lua,
594575559 bytesAviso Ainda há muito trabalho antes de terminar este golfe! Eu deveria ser capaz de suportar menos de 500 bytes, no mínimo. No momento, é a primeira solução que funcionou, e ainda estou trabalhando nisso.
Vou fornecer uma explicação completa quando terminar.
fonte
Ferrugem,
496495 bytesInfelizmente, não consigo vencer o OP, mas, para uma resposta do Rust, estou bastante satisfeito com o bytecount.
Entrada: um vetor de números, bem como o número de colunas. Por exemplo
saídas
para a linha de comando.
Primeiro resolvo todas as linhas e depois resolvo a coluna resultante apenas uma vez, mas imprimo as etapas para todas as colunas. Portanto, é realmente bastante eficiente :-P.
Com formatação:
Edit: agora retorna a cor da solução que me poupa ponto e vírgula ^^
fonte
Befunge ,
197368696754 Bytes(sim, estou praticando golfe com código reverso, quanto mais bytes, melhor)
Eu estava pensando que poderia ser um desafio escrever esse algoritmo no Befunge e que poderia ser divertido
Eu gostaria que fosse um programa comunitário, portanto, se alguém quiser trabalhar nele, faça-o.No final, eu fiz tudo sozinho até agora, então vou terminar por conta própria (está quase pronto)
O que foi feito ainda: um código em forma de troll
(sim, é um troll, acredite em mim)
Basicamente, ele lê uma matriz e calcula a movimentação a ser feita para resolver as linhas, dada uma entrada como
(toda a matriz é passada como uma lista [linha1, linha2, linha3,…])
saída é
linhas e colunas começam em 0.
Agora que as linhas estão resolvidas, está quase pronto! Viva!
Explicação: (será atualizado posteriormente)
Portanto, existem 5 partes principais:
Peças cinzas são inicializações
Aqui está uma explicação mais profunda do módulo que encontra as caixas a serem combinadas (que são codificadas aqui, a propósito)
A parte CALL é quando o ponteiro da instrução está indo para outro módulo, para combinar com as caixas. Volta a este módulo através da entrada 'B'
Aqui está um pseudo-código: (currentx está relacionado à leitura da matriz)
Observe que, se você quiser testá-lo, terá que colocar algum espaço à direita e novas linhas à direita para que haja espaço suficiente para armazenar a matriz, se desejar usar a interpretação que eu vinculei. 22 + o número de linhas na entrada como linhas finais, e 34 + o número de colunas como espaços finais em uma linha deve estar ok.
fonte
\r\n
vez de\n
apenas?) #C, 404 bytes
No meu primeiro código de golfe, estou muito feliz com o resultado. Levou muito tempo, no entanto. Não é totalmente C padrão, o que quer que seja compilado no gcc sem sinalizadores especiais (e ignorando avisos). Portanto, há uma função aninhada lá. A função
f
assume as dimensõesm
e,n
como seu primeiro argumento, e, como seu terceiro argumento, leva um (ponteiro int) para uma matriz de tamanhom
×n
(indexada pelas linhas primeiro). Os outros argumentos são argumentos fictícios, você não precisa passá-los, eles estão lá apenas para salvar bytes em variáveis declarantes. Ele grava cada par alterado em STDOUT no formatorow1,col1:row1,col1;
, com o ponto e vírgula separando os pares. Usa indexação baseada em 0.Usei um algoritmo ligeiramente diferente do OP para resolver linhas / colunas individuais. É mais ou menos assim (pseudocódigo):
O
for(;~b;b--)
loop é executado exatamente duas vezes, na segunda passagem ele resolve colunas em vez de linhas. Isso é feito trocandon
em
alterando os valores deo
ep
que são usados na aritmética do ponteiro para endereçar a matriz.Aqui está uma versão não-destruída, com um teste principal, e imprime toda a matriz após cada movimento (pressione enter para a etapa 1 volta):
fonte