Переміщення тексту за допомогою клавіш зі стрілками


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<>символів, яка показує один з найкоротших шляхів. Ви можете додатково припустити додатковий новий рядок в кінці кожного, але він не входить до складу тексту навігації.

Ви можете написати програму або названу функцію. Переможцем стане найкоротший подання, виміряне в байтах.

Приклад вводу / виводу

^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 - EVIL

У кожному рядку є два кінці. Відредаговано "до кінця".
PhiNotPi

Vim дозволяє стрілки. У мене у вікні AIX справжній vi, який не є (я додав заяви до карти до мого запуску файлу). "На півдорозі пристойний" ... так
Джеррі Єремія

Вихід першого прикладу також може бути 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логіка неоперації внаслідок індексації кругового масиву, і існує лише 5 визначених операцій.

В цілому я дуже задоволений тим, як це вийшло. Це, безумовно, найбільше роботи, яку я вклав на сьогоднішній день у відповідь на гольф коду (за те, що вписується в твіт !?). Час запуску досить неприємний, хоча. CJam - це не найшвидша мова для початку, і цей алгоритм має складність приблизно на зразок O (m * 5 n ) , де m - розмір вводу, а n - розмір виводу. Гарна швидкість не враховується!


Приємно :) Я відчуваю трохи вини за те, що опосередковано змусив витратити на це стільки часу: p
aditsu кинь, тому що SE - EVIL

2

Пітон 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і z. x- це рядок, yположення стовпця та z"приховане" положення стовпця, якщо ви піднімаєтеся вгору чи вниз, а лінія занадто коротка. Багато ifs вирішують, як змінювати змінну під час переміщення.

Попередня обробка дійсно тривала, перші 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/ ... окрім прикладу Мері чи чогось такого розміру, ви, мабуть, захочете інтерпретатора Java .


1
WTF? 274 !!!!!!
Оптимізатор

@Optimizer hahaha, ну, я витратив на це достатньо часу, продовжуй і гольфу більше, якщо хочеш: p
aditsu кинь, тому що SE - EVIL
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.