Entrada:
Um labirinto contendo os caracteres:
--
(parede horizontal);|
(parede vertical);+
(conexão);(espaço para caminhar);
I
(Entrada);U
(Saída).
Ou seja, uma entrada pode ser assim:
+--+--+--+--+--+--+--+--+--+--+
I | | |
+ +--+--+--+ + + + +--+ +
| | | | | |
+--+--+--+ +--+--+ + + +--+
| | | | |
+ +--+--+ + +--+--+ +--+ +
| | | | | |
+--+ + +--+--+ +--+--+ + +
| | | | | |
+ +--+--+--+ +--+--+ + + +
| | | | | |
+--+ + +--+--+ +--+--+--+--+
| | | | |
+ + +--+--+--+ +--+ + + +
| | | | | | | |
+--+--+ + +--+ + + +--+ +
| | | | | |
+ +--+--+--+ + + + + +--+
| | | | U
+--+--+--+--+--+--+--+--+--+--+
Saída:
O mais eficiente caminho que deve andar para começar a partir da entrada para a saída do labirinto (através do labirinto), indicado pelos caracteres indicando esquerda, direita, para cima e para baixo (ou seja >
; <
; ^
; v
).
Regras do desafio:
- Você pode receber a entrada em qualquer formato razoável. String-array, String única com novas linhas, conjunto de caracteres 2D, etc. são todos os formatos de entrada possíveis.
- A saída pode consistir em quatro caracteres distintos. Ou seja
><^v
;→←↑↓
;⇒⇐⇑⇓
;RLUD
;0123
;ABCD
; etc.) - Você tem permissão para adicionar espaços ou novas linhas à saída, se preferir; isso é opcional.
- Os passos são contados por quadrado (veja quatro
+
símbolos para os quadrados) e não por caractere. - O labirinto pode ser do tamanho de 5x5 a 15x15 e sempre será um quadrado (portanto, não haverá casos de teste para labirintos 5x10).
- Você pode assumir que todo labirinto possui um ou mais caminhos válidos do início ao fim e sempre gera o menor (consulte os casos de teste 4 e 5).
- Se houver vários caminhos com o mesmo comprimento, você poderá escolher qual deles enviar (consulte o caso de teste 6).
- Você não pode 'andar' fora dos limites do labirinto (consulte os casos de teste 7 e 8).
Regras gerais:
- Isso é código-golfe , então a resposta mais curta em bytes vence.
Não permita que idiomas com código de golfe o desencorajem a postar respostas com idiomas que não sejam codegolf. Tente encontrar uma resposta o mais curta possível para 'qualquer' linguagem de programação. - As regras padrão se aplicam à sua resposta, para que você possa usar STDIN / STDOUT, funções / método com os parâmetros adequados, programas completos. Sua chamada.
- As brechas padrão são proibidas.
- Se possível, adicione um link com um teste para o seu código.
- Além disso, adicione uma explicação, se necessário.
Casos de teste:
1. Input:
+--+--+--+--+--+--+--+--+--+--+
I | | |
+ +--+--+--+ + + + +--+ +
| | | | | |
+--+--+--+ +--+--+ + + +--+
| | | | |
+ +--+--+ + +--+--+ +--+ +
| | | | | |
+--+ + +--+--+ +--+--+ + +
| | | | | |
+ +--+--+--+ +--+--+ + + +
| | | | | |
+--+ + +--+--+ +--+--+--+--+
| | | | |
+ + +--+--+--+ +--+ + + +
| | | | | | | |
+--+--+ + +--+ + + +--+ +
| | | | | |
+ +--+--+--+ + + + + +--+
| | | | U
+--+--+--+--+--+--+--+--+--+--+
1. Output:
>v>>>vv<v>>v>v>>vvv>>>
2. Input:
+--+--+--+--+--+
I | | |
+ +--+--+ + +
| | | |
+ +--+ + + +
| | | | |
+ + +--+ + +
| | |
+--+ + +--+--+
| | U
+--+--+--+--+--+
2. Output:
>vvv>>v>>>
3. Input:
+--+--+--+--+--+
U | |
+ + +--+--+ +
| | | |
+--+--+ + +--+
| | |
+ +--+--+--+ +
| | | |
+ + + + +--+
| | I
+--+--+--+--+--+
3. Output:
<<<^<v<^^>>^<^<<
4. Input (test case with two valid paths):
+--+--+--+--+--+
U | |
+ + +--+--+ +
| | |
+--+--+ + +--+
| | |
+ +--+--+--+ +
| | | |
+ + + + +--+
| | I
+--+--+--+--+--+
4. Output:
<<^>^<^<<^<< (<<<^<v<^^>>^<^<< is less efficient, and therefore not a valid output)
5. Input (test case with two valid paths):
I
+--+--+--+--+--+--+--+--+--+--+ +--+--+--+--+
| | | | |
+ + + +--+--+--+ + +--+--+ +--+--+ + +
| | | | | | | |
+--+--+--+ +--+ + +--+--+--+--+ +--+--+--+
| | | | | | | | |
+ + + + + +--+ + + + +--+--+ +--+ +
| | | | | | | |
+ +--+--+--+ +--+--+ + +--+ +--+--+ +--+
| | | | | | | | |
+ +--+ + +--+ +--+--+ +--+--+ + +--+ +
| | | | | | |
+ + +--+--+--+--+ + +--+--+--+ +--+ +--+
| | | | | | | |
+--+--+--+ + +--+--+ +--+ + +--+ +--+ +
| | | | | | | |
+ +--+--+--+--+ + + +--+--+--+ + + + +
| | | | | | | | | |
+--+ + + + + + +--+--+ + + +--+ + +
| | | | | | | | | |
+--+ +--+--+ + + + +--+--+--+ + + + +
| | | | | | | | | |
+ +--+ +--+--+ + +--+--+ + +--+ + + +
| | | | | | | | | |
+--+--+--+ + + +--+ + +--+--+ +--+ + +
| | | | | | | |
+ + +--+--+--+--+ +--+--+ +--+--+ +--+ +
| | | | | |
+ + + +--+--+--+--+--+--+--+--+ +--+ +--+
| | | |
+--+--+--+--+--+--+--+--+--+ +--+--+--+--+--+
U
5. Output:
v<<<v<vv<<v<v>>^>>^^>vvv>>>v>vv<vv<<v<v<^<^^^^<vvvvv<^<v<<v>v>>>>>>>v (v<<<v<vv<<v<v>>^>>^^>vvv>>>v>vv<vv<<v<v<^<^^^^<vvvvv>v>>>^>>^>^^>vvv<v<v<<v is less efficient, and therefore not a valid output)
6. Input:
+--+--+--+--+--+
I |
+ + + + + +
| |
+ + + + + +
| |
+ + + + + +
| |
+ + + + + +
| U
+--+--+--+--+--+
6. Output:
>>v>v>v>v> or >v>v>v>v>> or >>>>>vvvv> or etc. (all are equally efficient, so all 10-length outputs are valid)
7. Input:
I U
+ + +--+--+--+
| | | |
+ +--+--+ + +
| | | |
+--+ + +--+ +
| | | |
+ +--+ + + +
| | |
+--+ +--+--+ +
| | |
+--+--+--+--+--+
7. Output:
vv>v>^>^<<^
8. Input:
+--+--+--+--+--+
| | |
+ +--+ +--+ +
I | | | |
+ + +--+ + +
U | | | |
+--+--+ + + +
| | | |
+ +--+--+--+ +
|
+--+--+--+--+--+
8. Output:
>v<
Labirintos gerados usando esta ferramenta (e em alguns casos ligeiramente modificados).
code-golf
path-finding
maze
Kevin Cruijssen
fonte
fonte
v<<<<<<^^^^^
(sempre pensar fora da caixa)>v>>>vv<v>>v>v>>vvv>>>
.Respostas:
Retina ,
338281275273261 bytesExperimente online!
Notas
0x20
) são substituídos por interpunct (·
) nesta resposta e no link TIO. O programa funciona bem se os espaços forem restaurados.AvKr
para cima, baixo, esquerda e direita, respectivamente. Esses podem ser substituídos por quaisquer letras, excetoI
.Leva cerca de 40s no TIO para o caso de teste 15 × 15. Seja paciente.Retrabalhou a peça para encontrar o caminho mais curto assim que o caminho chegou à saída. Acontece que estava demorando muito tempo.Explicação
O programa consiste em 3 fases:
Formato
Como o formato do labirinto original é bastante pesado, a primeira parte do programa o converte em um formato diferente.
Células
No formato original, cada célula é representada como uma região 2 × 3:
Como a coluna da direita não contém informações, o programa identifica células como qualquer região 2 × 2 com um
+
na parte superior esquerda.Isso nos deixa com 3 tipos de células:
U
no caso de teste 1 está em uma célula R.No novo formato, as células são representadas como uma sequência de comprimento variável:
As paredes esquerda e superior são copiadas do formato original. O número da coluna é baseado na posição horizontal da célula e é usado para alinhamento (identificação de células diretamente em cima / abaixo uma da outra). Caminho é uma sequência alfabética usada durante a fase de preenchimento para salvar o caminho mais curto para alcançar essa célula. O marcador de caminho e saída será mais explicado.
Meias células
Embora a maioria do labirinto seja de células, existem regiões do labirinto que não são células:
+
s ao longo da parede direita não formarão células, pois estão na última coluna.+
à esquerda delas. Por exemplo, a entradaI
no caso de teste 1 está em uma meia célula L.Tecnicamente, existem meias células T acima do labirinto (quando há preenchimento superior) e meias células B (ao longo da parede inferior quando não há preenchimento inferior), mas elas não são representadas no novo formato.
A linha superior de uma meia célula seria removida como parte da construção de células completas na mesma linha, para que as meias células sejam representadas no novo formato como
An meias células é apenas
|
. An L Meia célula tem apenasI
o caminho, apenas o marcador de saída e um caminho vazio, ou apenas uma parede vazia.Entradas e saídas
Se a entrada estiver à esquerda, direita ou parte inferior do labirinto, o marcador de entrada
I
seria naturalmente incluído na (meia) célula como o caminho, que pode ser removido ao retornar o caminho final.Se a entrada estiver acima do labirinto, o primeiro passo (para baixo) é dado durante a fase de construção, pois as meias células T são removidas durante a construção. Isso mantém um caminho viável em uma célula cheia. A parede superior é fechada depois.
Se a saída for para a esquerda, direita ou parte inferior do labirinto, então
U
seria naturalmente incluída na (meia) célula. Para evitar ser confundido com um caminho, o marcador de saída não alfanumérico&
é usado em vez deU
. O marcador de saída é incorporado em uma célula ou meia célula (conforme especificado acima).Se a saída estiver acima do labirinto, seria o único buraco que pode ir acima da linha superior das células (já que o da entrada, se presente, já estaria fechado). Qualquer caminho que alcance esse buraco pode sair do labirinto dando um passo para cima.
Por fim, qualquer célula B que contenha a entrada ou a saída deve fechar a parede esquerda para evitar "resolver" o labirinto caminhando pelas células B. Entradas e saídas em Células R ou L Meia-célula não precisam de processamento adicional, pois o algoritmo de preenchimento não permite movimentos verticais de / para elas.
Exemplo
Como exemplo, o primeiro caso de teste
é
no novo formato. Você pode converter outros labirintos aqui .
Fase de construção
A fase de construção compõe as 13 primeiras linhas do programa.
Converte a saída em L Meia célula para sair do marcador
Adiciona paredes à esquerda da entrada e saída nas células B
Dá o primeiro passo se a entrada estiver acima do labirinto
Executa a conversão real
Fecha o orifício de entrada superior
Mantém apenas linhas com a
1
. Como os labirintos têm pelo menos 5 células de largura e o número de colunas ocorre em incrementos de 3, uma linha com células de novo formato deve conter um número de coluna entre 10 e 19.Converte a saída na célula R ou na célula B para sair do marcador
Fase de preenchimento
A fase de preenchimento compõe as próximas 8 linhas do programa. Ele usa um algoritmo de preenchimento de inundação para preencher todas as células com o caminho mais curto a ser alcançado a partir da entrada.
Coloca toda a fase de preenchimento em um loop para preencher todo o labirinto.
Cada célula capaz de se mover para a esquerda o faz. Uma célula é capaz de se mover para a esquerda se
Então, cada célula capaz de se mover para a direita o faz. Uma célula é capaz de se mover para a direita se
Então, cada célula capaz de se mover para baixo o faz. Uma célula é capaz de descer se
Observe que L meias-células não podem se mover para baixo, pois não possuem números de coluna.
Então, cada célula capaz de subir faz isso. Uma célula é capaz de subir se
Fase de retorno
A fase de retorno compõe as últimas 5 linhas do programa. Essa fase procura e retorna o caminho preenchido na célula de saída.
O padrão do caminho na saída depende de onde a saída está:
& <path>
<left wall> <column number> & <path>
<left wall> <column number> · <path>
na linha superior.Localiza uma célula na linha superior com uma parede superior vazia e um caminho não vazio. Isso cuida do último caso, adicionando o último passo e o marcador de saída.
Corresponde e retorna um caminho não vazio após um marcador de saída.
Remove o marcador de saída e o
I
prefixo do caminho.fonte
AvKr
? Eles têm um significado / são abreviações para cima, baixo, esquerda e direita no seu idioma nativo ou há outro motivo para você escolher esses caracteres específicos?AvKr
ser a coisa mais próxima das setas no alfano.Perl 6 ,
259295 bytesComo funciona
Isso comprime o labirinto para que o interior de cada célula seja 1x1 em vez de caracteres de espaço 2x1:
Esta é a função de busca de caminho recursiva. São necessários três parâmetros: a coordenada atual
c=(y,x)
, a lista de coordenadas já visitadasv
e o caminhop
percorrido até o momento (como uma lista de caracteres de seta).Se o caractere na coordenada atual for um espaço, ele retornará aos quatro vizinhos.
Se o personagem na coordenada atual é a
I
, ele se repete para os dois vizinhos que não estão "ao longo da borda", forçando soluções a percorrer o labirinto e não em torno dele.Se o caractere na coordenada atual for a
U
, ele chamarátake
a cadeia de caminho acumulada.A função recursiva é chamada inicialmente com a coordenada da letra
I
, encontrada usando um regex.A
gather
palavra-chave coleta todos os valores nos quaistake
foi chamado dentro da função, ou seja, todos os caminhos não cíclicos válidos pelo labirinto.O caminho mais curto é escolhido, cada segunda seta é descartada para explicar o fato de que são necessários dois movimentos idênticos para passar de uma célula para a próxima e as setas restantes são concatenadas para formar a sequência retornada do lambda.
fonte
Python 2: 302 bytes
Recebe entrada como uma matriz de cadeias, todas com o mesmo comprimento. Imprime
0
para a direita,1
para baixo,2
para esquerda e3
para cima.Explicação
Adotei uma abordagem diferente das outras respostas. Ideia geral: procure recursivamente encontrando o caminho mais curto entre avançar e girar a prancha 90 graus.
Experimente online!
fonte
I
para impedir que o caminho saia do labirinto. Aproveite sua estadia e receba +1 de mim. :)JavaScript (ES6), 356 bytes
Recebe a entrada como uma matriz 2D de caracteres. Cada linha deve ser preenchida à esquerda por um espaço e não deve ter espaço à direita, não importa onde estejam os pontos de partida / chegada.
Usa a ideia de smls de o labirinto para tornar cada célula 1x1 e remover setas repetidas da saída.
Ungolfed e Explained
Snippet de teste
Mostrar snippet de código
fonte
Retina , 416 bytes
Experimente online! Se eu tivesse visto essa pergunta quando foi publicada originalmente, esta provavelmente é a resposta que eu daria, então estou postando mesmo assim, mesmo que haja uma resposta muito melhor na Retina. Explicação:
Preencha a borda. Isso evita caminhar ao redor do labirinto (por exemplo, no caso de teste 7).
Coloque um marcador não alfabético na entrada.
Preenchimento de inundação da saída para a entrada. Em cada etapa, use uma letra para indicar a melhor direção a seguir (wasd - isso pode ser familiar para os jogadores; eu também havia considerado o hjkl, mas achei muito confuso). Além disso, prefira repetir a mesma direção; isso evita ir para a esquerda / direita entre duas células adjacentes verticalmente.
Suponha que o primeiro passo esteja abaixo.
Mas se houver uma letra acima, esquerda ou direita da entrada, mude para a primeira etapa.
Mova o marcador na direção do último movimento, lendo a direção do próximo movimento a partir do quadrado para o qual o marcador está se movendo e adicione-o à lista de direções. Isso se repete até que
U
seja alcançado.Exclua tudo após as instruções, pois não é mais necessário.
A grade original está em um layout 3 × 2. Ao mover verticalmente, se zig-zag horizontalmente, o preenchimento de inundação otimizará o movimento e moverá apenas 3n-1 caracteres horizontalmente; portanto, ao dividir por três, precisamos arredondar para cima. Verticalmente, apenas dividimos por 2.
Também investiguei uma solução de grade quadrada verdadeira, ou seja, onde a matriz de caracteres é ela própria quadrada, em vez de ser um layout 3 × 2 com uma borda opcional. Embora provavelmente não esteja em conformidade com a pergunta, a capacidade de transpor reduziu a contagem de bytes para 350: Experimente on-line!
fonte
-
torno dos caracteres de entrada e saída. Como o desafio é principalmente atravessar o labirinto, acho que está bem, mas estou curioso: quais foram os problemas quando você não colocou aquelas paredes acima / abaixo daI
eU
? Além disso, você pode verificar se isso funciona para o caso de teste 7 com oI
eU
na parte superior em vez de nos lados? O TIO excede o limite de 60 segundos, por isso não consigo testá-lo. Apesar de ler sua explicação sobre a primeira tentativa de desativação por padrão, presumo que ela funcione bem.