使用箭头键浏览文本


11

背景

大多数(半途而废的)文本编辑器允许您使用箭头键导航文本。向上和向下允许您浏览行,同时左右移动一条线但也可以环绕。此外,如果该行短于光标的X位置,则光标会出现在该行的末尾,但如果您继续向上或向下移动,则会返回到相同的X位置。以下视觉说明可能会有所帮助:

运动实例

一个简单的文本示例可能看起来像这样。光标将插入在此文本中的两个字符之间或结尾。

-----
---
------

let's put the cursor here:

X-----
---
------

move down (v):

-----
X---
------

move left (<):

-----X
---
------

v

-----
---X
------

v (notice how the X position of the cursor has been maintained)

-----
---
-----X-

^

-----
---X
------

>  (more line wrapping)

-----
---
X------

<

-----
---X
------

^ (the X-position from earlier is no longer maintained due to the left-right motion)

---X--
---
------

挑战

给定几行ASCII测试,找到从开始位置到结束位置的最短路径。起始位置由表示,^结束位置由表示$,每个将只有一个。这些不被认为是文本的一部分,并且不会增加该行的“长度”。

输入将包含几行非空白文本。输出将是^v<>显示最短路径之一的一系列字符。您可以选择在每行的末尾假设一个额外的换行符,但该行不包含在可导航文本中。

您可以编写程序或命名函数。获胜者为最短提交,以字节为单位。

示例I / O

^Squares
are
fun$ny

vv<v  (which is better than the naive vv>>>)

Squares
^are
funny$

<vv

Alp$habet^
Song

v<^

Mary had a little lamb,
His fleece was white as snow,
And$ everywhere that ^Mary went,
The lamb was sure to go.

^^>>>>v>>>

$^degenerate case

(no output)

“光标将在此文本中的两个字符之间插入,或在末尾插入” – 在第一个示例中继续将光标放置在开头
由于SE为EVIL,Edi退出

每行有两个末端。编辑为“结束”。
PhiNotPi 2015年

Vim允许箭头。我的AIX框上没有一个真正的vi(我已将映射语句添加到启动文件中)。“半路不错” ...是的
杰里·耶利米

第一个示例的输出也可能是v<vv,对吗?还是在该行的最后一个字符之后结束?
mbomb007'2

@ mbomb007它将在该行的最后一个字符之后结束。
PhiNotPi 2015年

Answers:


7

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是输出的大小。好东西的速度不算数!


尼斯:)我因间接使您花大量时间在此上而
感到内

2

Python 2:446

Q=input().split('\n');
def g(c):l=[l for l in Q if c in l][0];return Q.index(l),l.index(c)
a,b=g('^');c,d=g('$');Q=map(len,Q);Q[a]-=1;Q[c]-=1
if a==c:d-=b<d;b-=d<b
t=-1
while Q:
 l=[];T=t=t+1;x,y,z=a,b,b
 while T:l+=[T%5]*(T%5>0);T/=5
 for T in l:A=":x+=T+T-3;y=min(Q[x],z)";B="x<len(Q)-1";exec"if "+["","x"+A,B+A,"y:y=z=y-1\nelif x:x-=1;y=z=Q[x]","y<Q[x]:y=z=y+1\nelif "+B+":x+=1;y=z=0"][T]
 if(x,y)==(c,d):print''.join(' ^v<>'[x]for x in l);Q=0

简单的解决方案。我正在执行广度优先搜索。t遍历所有不同的路径。我转换t为base 5,但仅使用非零的条目。1向上,2向下,3向左和4向右。

我将光标的当前位置保留在3个变量中xy并且zx是行,y列位置和z“隐藏”列位置(如果您向上或向下并且行太短)。许多if决定了变量在移动过程中如何变化。

预处理确实很长,前4行仅执行此任务。

较长的测试用例需要很长时间。该算法的复杂度为O(N * 5 ^ N),其中N是最短解的长度。

用法:将这些行输入为单个字符串(以分隔的行\n),例如"Alp$habet^\nSong"


1

果酱-274

还没有答案吗?好的,这是一个:)

qN/_{0:V;{_'^={[UVV]:B;;}{'$={[UV]:E;}{V):V;}?}?}/U):U;}/"^$"f-:,:A;{:X0=[X0=(_A=X2=_@e<\]X?}:U;{:X0=A,(=X[X0=)_A=X2=_@e<\]?}:D;{:X1=[X~;(_]{X0=[X0=(_A=_]X?}?}:L;{:X1=X0=A=={X0=A,(=X[X0=)0_]?}[X~;)_]?}:R;[[BM]]{_{0=2<E=},_{0=1=o0}{;[{"U^DvL<R>"2/\f{[~@1/~@\+@@~\]}~}/]1}?}g;

http://cjam.aditsu.net/上尝试一下...除了Mary例子或类似大小的东西,您可能需要Java解释器


1
WTF?第274章
Optimizer

@Optimizer哈哈哈,好吧,我浪费了很多时间,如果愿意,可以继续打高尔夫球:p
aditsu退出,因为SE是邪恶的2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.