CJam, 139 байтов
Ну, это заняло много часов, чтобы прийти к тому, что кажется готовым. Похоже, что время, которое требуется для агрессивной оптимизации кода CJam, больше, чем O (n) по отношению к размеру кода ...
Вы можете попробовать его онлайн , но для любого ввода, для которого наилучший путь составляет не менее 6 операций или около того, вам, вероятно, следует попробовать его в автономном режиме с более быстрым интерпретатором.
сплющенные:
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=
Расширено и прокомментировано:
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";
В целом, это довольно простое решение. Он «выполняет» цифры представления base-5 номера пути, который увеличивается на каждой итерации, начиная с 0, до тех пор, пока путь не будет работать. Цифры 1
- 4
отображают операции вверх, вниз, влево и вправо и 0
ничего не делают. Первая итерация, использующая путь just, 0
ловит вырожденный случай. Все остальные пути, содержащие a 0
, никогда не выбираются, потому что это просто версии уже протестированных путей с добавленными no-ops.
Состояние моделируется настолько минималистично, насколько это возможно: текст с удаленными маркерами начала и конца, положение курсора в тексте и «память столбца». Символы новой строки в основном обрабатываются как любой другой символ, поэтому концепция строки отсутствует, а позиция курсора - просто индекс. Это упрощает перемещение влево и вправо, что просто реализуется как уменьшение и приращение (с ограничением по размеру текста). Движение вверх и вниз немного сложнее, но все же управляемо.
Повторное использование кода было довольно важной тактикой оптимизации. Примеры этого включают в себя:
- Написание кода для продвижения вверх таким образом, чтобы меньше генерировать код для перемещения во время выполнения, чем для написания собственного кода. Это делается путем копирования кода для перемещения вверх и удаления / замены нескольких символов.
- Обновление «памяти столбцов» выполняется условно на основе цифры пути, деленной на 3, вместо того, чтобы кодироваться в логику операции. Это также позволяет инициализировать память столбца путем добавления фиктивной
5
операции в начало строки пути, которая также использует 0
логику запрета операций из-за индексации циклического массива и имеет только 5 определенных операций.
В целом, я очень доволен тем, как это получилось. Это определенно самая большая работа, которую я поместил в ответе по гольфу в коде на сегодняшний день (для чего-то, что вписывается в твит !?). Время выполнения довольно ужасно, хотя. CJam не является самым быстрым языком для начала, и этот алгоритм имеет такую сложность, как O (m * 5 n ) , где m - размер ввода, а n - размер вывода. Хорошая скорость не считается!