CJam, 139 bytes
Bem, isso levou muitas horas para chegar a algo que parece feito. Parece que o tempo necessário para otimizar agressivamente o código CJam é algo maior que O (n) em relação ao tamanho do código ...
Você pode experimentá-lo on-line , mas, para qualquer entrada cujo melhor caminho seja pelo menos seis operações, provavelmente você deve experimentá-lo off-line com um intérprete mais rápido.
Squished:
q_'$-_'^-:T;'^#\'^-'$#W{)2$5Y$5b+{:D[L"_T<W%_N#)_@>N+N#X-Ue>+-"_"W%-U"--2'<t2'>t'++'(')]=~0e>T,e<D3/1$T<N\+W%N#X?:X;}/2$-}g5b{" ^v<>"=}%]W=
Expandido e comentado:
q "Read the input";
_'$- "Remove the end marker";
_'^-:T; "Remove the start marker and save the text";
'^# "With only the end marker removed, locate the start marker";
\'^-'$# "With only the start marker removed, locate the end marker";
W "Initialize the path number to -1";
{ "Do...";
) "Increment the path number";
2$ "Initialize the cursor position to that of the start marker";
5Y$5b+ "Convert the path number to base 5, then add a leading 5
(the leading 5 will act to initialize the column memory)";
{:D "For each digit in the path digit string:";
[ "Begin cases:";
L "0: Do nothing";
"_T<W%_N#)_@>N+N#X-Ue>+-"
"REFS: [ 1 ][ 2 ][ 3 ]45
1: [1] Calculate the distance to the end of the previous
line (0 if no such line)
[2] Calculate the length of the previous line (0 if
no such line)
[3] Calculate the distance to move backwards in the
previous line as the maximum of the length of the
previous line minus the column memory and 0
[4] Calculate the total distance to move as the sum
of [1] and [3]
[5] Subtract [4] from the cursor position";
_"W%-U"- "2: Start with a base of the logic of case 1, but with a
few operations adjusted.";
-2'<t2'>t " [1] Calculate the distance to the *start* of the
*next* line (0 if no such line)
[2] Calculate the length of the *next* line (0 if no
such line)
[3] Calculate the distance to move *forwards* in the
*next* line as the *minimum* of the length of the
*next line* and *the column memory*
[4] Calculate the total distance to move as the sum
of [1] and [3]";
'++ " [5] *Add* [4] *to* the cursor position";
'( "3: Decrement the cursor position";
') "4: Increment the cursor position";
]=~ "Execute the case corresponding to the path digit mod 5";
0e>T,e< "Clamp the cursor position to [0, text length]";
D3/ "Check if the path digit is not 0, 1, or 2...";
1$T<N\+W%N# "Calculate the current column";
X?:X; "If the above check succeeded, update the column memory";
}/ "End for each";
2$- "Subtract the end marker position from the cursor position";
}g "... While the above subtraction is nonzero";
5b "Convert the path number to base 5";
{" ^v<>"=}% "Map each digit in the path string to its operation symbol";
]W= "Clean up";
No geral, esta é uma solução bastante direta. Ele "executa" os dígitos da representação da base 5 de um número de caminho que é incrementado a cada iteração, começando com 0, até que um caminho funcione. Os dígitos 1- são 4mapeados para as operações para cima, baixo, esquerda e direita e 0não fazem nada. A primeira iteração usando um caminho de apenas 0captura o caso degenerado. Todos os outros caminhos que contêm a 0nunca são selecionados porque são apenas versões de caminhos já testados com não operações adicionais.
O estado é modelado da maneira mais minimalista possível: o texto com os marcadores de início e fim removidos, a posição do cursor no texto e a "memória da coluna". As novas linhas são tratadas principalmente como qualquer outro caractere, portanto não há conceito de linha e a posição do cursor é apenas um índice. Isso simplifica a movimentação da esquerda e da direita, que são implementadas apenas como decremento e incremento (com fixação do tamanho do texto). Mover para cima e para baixo é um pouco mais complicado, mas ainda gerenciável.
A reutilização de código foi uma tática de otimização bastante vital. Exemplos disso incluem:
- Escreva o código para subir de uma maneira que seja menor gerar o código para descer no tempo de execução do que escrever seu próprio código. Isso é feito copiando o código para subir e remover / substituir alguns caracteres.
- A atualização da "memória da coluna" é feita condicionalmente com base no dígito do caminho dividido por 3, em vez de ser codificado na lógica da operação. Isso também permite a inicialização da memória da coluna adicionando uma
5operação fictícia ao início da cadeia de caminho, que também usa a 0lógica no-op devido à indexação circular da matriz e apenas cinco operações definidas.
No geral, estou muito feliz com o resultado. Esse é definitivamente o maior trabalho que eu coloquei em uma resposta de código de golfe até o momento (para algo que se encaixa em um tweet !?). O tempo de execução é bastante abismal, no entanto. CJam não é exatamente o idioma mais rápido para começar e esse algoritmo tem uma complexidade de algo como O (m * 5 n ) , onde m é o tamanho da entrada en é o tamanho da saída. Ainda bem que a velocidade não conta!