Eu orgulhosamente apresento ...
<}74}}:23}29}59}}}}}}}:111_}}}}:::::::23_}:111
? @
:" }}_47}_95 3""""""""(
_ : } _ } {=}
2 23_}29_ _ ; : \
0 ; 3 +_( 3_" 60{ .{.{.
"-_95:}}"" 2 0 ) 2 " _ _ {
"" _ : 2 _ ."(; } 3 .{
;_92}_47} : _ 0 = : * ;
: "" 2 {.{{ . -""(
}}:59_}}:::: "";_ . { _ "
} " {.{.{. 32.
}}}_95:}}}}_20-
... meu novo labirinto esolang bidimensional! O código acima não é incrivelmente bom (existem 161 espaços e 25 NOPs, portanto, um layout melhor pode reduzir muito isso), mas pelo menos eu consegui mostrar que o idioma é utilizável para tarefas não triviais. :)
Como funciona
Primeiro, uma rápida visão geral do idioma:
- O labirinto opera em duas pilhas, principal e auxiliar , que podem conter números inteiros assinados arbitrariamente. Na parte inferior das duas pilhas, há uma quantidade infinita de zeros.
- Os comandos são caracteres individuais em uma grade 2D e formam um labirinto (caracteres desconhecidos, principalmente espaços, são paredes).
"
é um NOP que não é uma parede e pode ser útil para preencher determinados caminhos no código. Ao contrário de muitas outras linguagens 2D, as bordas não se enrolam.
- O ponteiro de instrução (IP) começa com o primeiro caractere que não é de parede (em ordem de leitura) movendo-se para a direita.
@
finaliza o programa.
- Se possível, o IP segue corredores (também em torno de curvas). Se o IP tiver várias células para mover, geralmente vira à esquerda se a parte superior da pilha principal for negativa, seguirá em frente se for zero ou vire à direita se for positivo. Quando o IP atinge uma parede, ele inverte a direção. (Existem mais algumas sutilezas, mas elas não devem importar para esse código.) Essa é a única maneira de implementar o fluxo de controle.
- Além dos comandos aritméticos e de manipulação de pilha, o código fonte pode ser modificado em tempo de execução com os quatro comandos
>v<^
que deslocam uma linha ou coluna do código fonte ciclicamente por uma célula. A linha ou coluna afetada depende da parte superior da pilha. Se a própria linha ou coluna do IP for alterada, ela se moverá com a mudança. Isso torna possível pular de uma borda do código fonte para a outra.
Agora, para este desafio em particular, aqui está a ideia geral do algoritmo:
- Empurre as extremidades dos carros até as capotas (ou seja
/ \_o oo o
) na pilha auxiliar.
- Leia a entrada e determine se deve pressionar
__
ou a /\
seguir.
- Empurre o restante dos carros (ou seja,
__ __ _/ \
dois espaços à esquerda) na pilha auxiliar.
- Prenda a entrada no valor máximo de
20
, vamos chamar isso de N .
- Agora faça o seguinte 3 vezes:
- Imprima N espaços.
- Imprima 6 caracteres armazenados.
- Imprima 60 - 3 * N espaços.
- Imprima 6 caracteres armazenados.
- Imprima uma nova linha.
Por fim, vejamos algumas partes do código. O IP inicia no canto superior esquerdo, em um comando de mudança de grade. A parte superior da pilha principal é 0
(que é usada como um índice relativo); portanto, a primeira linha é deslocada para a esquerda, o que também move o IP para a extremidade direita da grade. Agora, a primeira linha é simplesmente executada da direita para a esquerda, o que coloca o primeiro conjunto de caracteres fixos na pilha auxiliar:
}74}}:23}29}59}}}}}}}:111_}}}}:::::::23_}:111<
Essa mudança de linha é útil para jogar golfe quando você deseja iniciar com uma grande quantidade de código linear.
Em seguida, lemos a entrada e pressionamos os capôs corretos:
?
:"
_
2
0 ;
"-_95:}}""
"" _
;_92}_47}
O bit à esquerda com os três NOPs envia resultados negativos ao longo do ramo superior e não negativos ao longo do ramo inferior. À direita, eles se juntam novamente.
Agora segue outra seção linear grande (que provavelmente poderia ser muito jogada com outro truque de mudança de linha):
}}_47}_95
: }
23_}29_ _
3
2
:
:
:
}}:59_}}::::
}
}}}_95:}}}}
Isso empurra o restante dos carros para a pilha auxiliar.
Em seguida, computamos min(20, input)
, que é semelhante ao primeiro ramo:
;
+_(
0 )
2 _
_ 0
"" 2
"";_
"
_20-
Finalmente, temos o loop que é executado três vezes para imprimir as linhas. Cada iteração do loop contém dois pequenos loops (3x3) para imprimir os espaços, bem como duas seções para imprimir 6 caracteres da pilha auxiliar:
@
3""""""""(
_ } {=}
: \
3_" 60{ .{.{.
2 " _ _ {
."(; } 3 .{
= : * ;
{.{{ . -""(
. { _ "
{.{.{. 32.
Um truque bacana que eu gostaria de chamar a atenção é o .{.{.
da borda direita. Esse é um beco sem saída, portanto, além do .
final, o código é executado duas vezes, uma para frente e outra para trás. Isso fornece uma maneira clara de reduzir o código palindrômico (o problema é que você precisa garantir que o IP tome a curva correta ao sair do beco sem saída novamente).
/ \
e não diminuem_ _
?