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";
总体而言,这是一个非常简单的解决方案。它“执行”路径编号的以5为基数的表示的数字,该路径编号每次迭代都从0开始递增,直到路径有效为止。数字1- 4向上,向下,向左和向右映射操作,0但不执行任何操作。第一次迭代使用的路径恰好0就是退化的情况。0永远不会选择包含a的所有其他路径,因为它们只是经过测试的路径的版本,并且添加了无操作。
状态以尽可能简化的方式建模:删除了开始和结束标记的文本,文本中的光标位置以及“列内存”。换行符几乎与其他任何字符一样被对待,因此没有行的概念,并且光标位置只是一个索引。这使左右移动变得简单,只需将其实现为递减和递增(并限制为文本的大小)即可。上下移动比较棘手,但仍然可以管理。
代码重用是非常重要的优化策略。例如:
- 编写用于向上移动的代码,使得在运行时生成用于向下移动的代码比编写自己的代码要小。通过复制用于向上移动的代码并删除/替换一些字符来完成此操作。
- 更新“列存储器”是根据路径数字除以3来有条件地完成的,而不是将其编码为操作逻辑。这也允许通过
5在路径字符串的开头添加一个虚拟操作来初始化列存储器,0由于循环数组索引并且只有5个定义的操作,因此恰好使用无操作逻辑。
总体而言,我对这一结果如何感到非常满意。到目前为止,这绝对是我在代码高尔夫球答案中所做的最多的工作(适合推文!!)。但是,运行时非常糟糕。CJam并不是一开始就最快的语言,该算法的复杂度类似于O(m * 5 n),其中m是输入的大小,n是输出的大小。好东西的速度不算数!