นำทางข้อความด้วยปุ่มลูกศร


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)

"เคอร์เซอร์จะถูกแทรกระหว่างอักขระสองตัวในข้อความนี้หรือในตอนท้าย" - ดำเนินการเพื่อวางเคอร์เซอร์ที่จุดเริ่มต้นในตัวอย่างแรก
aditsu ออกเพราะ SE เป็นความชั่วร้าย

มีสองปลายของทุกบรรทัด แก้ไขเป็น "สิ้นสุด"
PhiNotPi

เป็นกลุ่มช่วยให้ลูกศร ฉันมี vi จริงในกล่อง AIX ของฉันที่ไม่ได้ (ฉันได้เพิ่มคำสั่งแผนที่ไปยังไฟล์เริ่มต้นของฉัน) "ครึ่งทางที่เหมาะสม" ... อ๋อ
Jerry Jeremiah

ผลลัพธ์ตัวอย่างแรกอาจเป็นv<vvจริงไหม หรือว่าจะจบลงหลังจากตัวละครตัวสุดท้ายในบรรทัดนั้น?
mbomb007

@ mbomb007 มันจะจบลงหลังจากตัวอักษรตัวสุดท้ายของบรรทัด
PhiNotPi

คำตอบ:


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จับตัวเคสที่เสื่อม เส้นทางอื่น ๆ ทั้งหมดที่มี a 0จะไม่ถูกเลือกเนื่องจากเป็นเพียงรุ่นของเส้นทางที่ผ่านการทดสอบแล้วและไม่มีการเพิ่ม

สถานะถูกจำลองในแบบที่เรียบง่ายที่สุดเท่าที่จะทำได้: ข้อความที่มีเครื่องหมายเริ่มต้นและสิ้นสุดถูกลบตำแหน่งเคอร์เซอร์ในข้อความและ "หน่วยความจำคอลัมน์" ขึ้นบรรทัดใหม่ส่วนใหญ่ถือว่าเหมือนตัวละครอื่น ๆ ดังนั้นจึงไม่มีแนวคิดของแถวและตำแหน่งเคอร์เซอร์เป็นเพียงดัชนี สิ่งนี้ทำให้การย้ายไปทางซ้ายและขวาตายง่ายซึ่งเพิ่งถูกนำมาใช้เป็นการลดลงและเพิ่มขึ้น (โดยยึดขนาดของข้อความ) การเลื่อนขึ้นและลงนั้นค่อนข้างยุ่งยาก แต่ก็ยังสามารถจัดการได้

การใช้รหัสซ้ำเป็นกลยุทธ์การเพิ่มประสิทธิภาพที่สำคัญ ตัวอย่างของสิ่งนี้รวมถึง:

  • การเขียนโค้ดเพื่อเลื่อนขึ้นในลักษณะที่เล็กกว่าเพื่อสร้างโค้ดสำหรับการเลื่อนลงที่รันไทม์มากกว่าที่จะเขียนโค้ดของตัวเอง สิ่งนี้ทำได้โดยการคัดลอกรหัสเพื่อเลื่อนขึ้นและนำออก / แทนที่อักขระสองสามตัว
  • การอัพเดต "หน่วยความจำคอลัมภ์" นั้นทำได้ตามเงื่อนไขโดยใช้หลักพา ธ หารด้วย 3 แทนที่จะเป็นโค๊ดในตรรกะของการดำเนินการ สิ่งนี้ยังช่วยให้การเริ่มต้นของหน่วยความจำคอลัมน์โดยการเพิ่มการ5ดำเนินการจำลองไปยังจุดเริ่มต้นของสตริงเส้นทางซึ่งเกิดขึ้นกับการใช้0ตรรกะ no-op เนื่องจากการทำดัชนีอาร์เรย์แบบวงกลมและมีการดำเนินการที่กำหนดไว้เพียง 5 รายการ

โดยรวมแล้วฉันมีความสุขมากกับสิ่งที่เกิดขึ้น นี่เป็นงานที่ดีที่สุดที่ฉันเคยใส่ลงไปในคำตอบของกอล์ฟ (สำหรับบางสิ่งที่เหมาะกับทวีต!?) ถึงแม้ว่าเวลาในการทำงานจะค่อนข้างแย่ CJam ไม่ใช่ภาษาที่เร็วที่สุดที่จะเริ่มต้นด้วยและอัลกอริธึมนี้มีความซับซ้อนของบางอย่างเช่นO (m * 5 n )โดยที่mคือขนาดของอินพุตและnคือขนาดของเอาต์พุต ความเร็วที่ดีไม่นับ!


ดี :) ฉันรู้สึกผิดเล็กน้อยที่ทำให้คุณใช้เวลากับเรื่องนี้มาก: p
aditsu เลิกเพราะ SE นั้นชั่วร้าย

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เป็นฐาน5แต่ใช้เฉพาะรายการที่ไม่ใช่ศูนย์ 1ขึ้น, 2ลง, 3อยู่ซ้ายและ4ถูก

ผมเก็บตำแหน่งปัจจุบันของเคอร์เซอร์ใน 3 ตัวแปรx, และy คือบรรทัดตำแหน่งคอลัมน์และตำแหน่งคอลัมน์'ซ่อน' หากคุณขึ้นหรือลงและบรรทัดนั้นสั้นเกินไป ifs จำนวนมากตัดสินใจว่าจะเปลี่ยนแปลงตัวแปรอย่างไรในระหว่างการย้ายzxyz

การประมวลผลล่วงหน้ามีความยาวจริง ๆ 4 บรรทัดแรกดำเนินการเฉพาะงานนี้

ตู้ทดสอบยาวใช้เวลานานมาก อัลกอริทึมมีความซับซ้อนของ O (N * 5 ^ N) โดยที่ N คือความยาวของวิธีแก้ปัญหาที่สั้นที่สุด

การใช้งาน: ป้อนบรรทัดเป็นสตริงเดียว (บรรทัดแยกตาม\n) เช่น"Alp$habet^\nSong"


1

CJam - 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/ ... ยกเว้นสำหรับแมรี่ตัวอย่างหรือสิ่งที่มีขนาดที่คุณอาจจะต้องการล่ามภาษาจาวา



@Optimizer ฮ่า ๆ ๆ ๆ ฉันเสียเวลาไปมากแล้วไปข้างหน้าและตีมันให้มากขึ้นถ้าคุณต้องการ: p
aditsu เลิกเพราะ SE นั้นเลวร้าย
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.