> <> Без води


20

Улюблену рибу, яка плаває за кодом > <> (езотерична мова програмування) , вивели з природного середовища. Ця зміна зробила його нездатною рухатись так, як вона звикла: те, що було тороїдальним рухом, було обмежено простим рухом вліво-вправо. Але> <> програми все ще пишуться так, ніби риба здатна рухатися через них. Ваше завдання, шановний програміст, написати програму для лінеаризації програми> <>. І робити це в якомога менше байтах; риба не має дуже великих спогадів.

Рух у> <>

У> <> рух є тороїдальним і одним символом одночасно. Це означає, що риба (вказівник) може «обернутись» від кінця рядка назад до початку. У> <> риба також здатна рухатися зверху вниз, знизу вгору та праворуч наліво, на відміну від того, як рухається більшість покажчиків. Отже, ця схема руху буде дійсною:

>>>^  >>>v
   >>>^  v

і воно закінчиться на нескінченному циклі (петля назад до верхньої лінії, коли нескінченно пройде повз нижню).

Риба рухається сіткою довжиною, рівною max (довжина рядка) і висотою, що дорівнює кількості рядів.

Як ви зрозумієте, яким шляхом рухається риба? Ці команди змінюють вектор напрямку руху (наприклад, (-1,0)означає, що направо-наліво):

Command | Direction Change
---------------------------
   >    | (1,0) (default)
   <    | (-1,0)
   ^    | (0,1)
   v    | (0,-1)
   /    | (x,y) -> (y,x)
   \    | (x,y) -> (-y,-x)
   |    | (x,y) -> (-x,y)
   _    | (x,y) -> (x,-y)
   #    | (x,y) -> (-x,-y)
   ;    | (0,0)

Як зазначалося, риба починає рухатися зліва направо, тобто з вектором напрямку (1,0). Риба починає розбирати команди, починаючи з першої команди, яку вона бачить, і змінює свій напрямок, якщо команда відповідає одному з вищезгаданих змінників напрямів.

Риба перестає рухатись, коли бачить a ;і припиняє програму.

Вхідні дані

Вхід буде дійсною (наприклад, нескінченно циклічною) програмою, що надається через STDIN. Ви також можете прочитати файл, якщо бажаєте. Рядки кожної програми не обов'язково повинні бути однакової довжини.

Введення подається у вигляді рядка, при цьому нові рядки розділяють кожен рядок програми.

Програми не циклічно, а це означає, що вони завжди закінчуються з a ;.

Вихідні дані

Вихід буде програмою лінеаризований. Тобто, ви повинні повернути всіх символів (включаючи змінні напрямків), які риба побачила б, якщо вона запускає програму "нормально". Це все символи на його шляху до ;.

Якщо вхід має рядки з неоднаковою довжиною, і риба закінчується рухом по лінії, коротшій за довжину найдовшої лінії, слід ставитися до цього, ніби риба рухається через пробіл (див. Тестові випадки).

Знайомі з <<> знають, що зміна напрямів - не єдиний спосіб робити рух в ньому, але для простоти ставляться до вводу так, ніби вони є єдиним способом впливати на рух.

Правила

  1. Застосовуються стандартні лазівки
  2. Ви можете написати або повну програму, або функцію
  3. Вхід подається через STDIN або файл у вигляді рядка, що містить програмні рядки, розділені новими рядками ( \n)
    • Ви можете сприймати інформацію по-різному, в межах причини (не соромтеся запитати мене, чи маєте ви на увазі конкретний вид введення). Ви не можете прошивати вхід пробілами, щоб довжини рядків відповідали.
    • Дивіться цей мета-пост щодо гнучкого введення. Наскільки це є розміщенням, загальний консенсус повинен бути максимально гнучким в межах розуму.
  4. Вихід - це один рядок через STDOUT або повертається функцією (залежно від того, що ви вирішили зробити, див. Правило 2)

Випробування

v     >v
>abcv//;
gfed<^ih

v>abcv<defghi^//>v;



v     >v
>abcv//;
gfed<^

v>abcv<defg  ^//>v;


abcdef;

abcdef;


abcd|;

abcd|dcba;


abcd#;

abcd#dcba;


abcd\;
    _

abcd\_\dcba;


^;
>abcde/
 ^jihg<

^ >abcde/ <ghij^a;


;

;

2
Чи можемо ми взяти вхід як масив рядків?
Лука

2
Чи можна припустити, що перший символ (лівий верхній) не буде крапкою з комою?
Kritixi Lithos

1
@KritixiLithos гарне запитання, я хочу сказати, що ви цього не можете припустити. Додам тестовий випадок.
cole

1
@Luke, ви можете сприймати вхід як масив рядків, якщо працювати з форматом введення дуже важко або неможливо (рядок з рядками, розділеними новими рядками). Дивіться додане Правило 3.
Коул

3
Обов’язкове подання на абсурдне обґрунтування
Патрік Робертс

Відповіді:


13

Röda , 405 393 392 391 371 366 361 236 234 232 230 223 200 байт

F f{L=f()|[#_]|sort|tail
c=""x=0
y=0
X=1
Y=0{l=f[y]l.=[" "]*(L-#l)c=l[x]a=X
[c]
C=indexOf(c,`><v^/\|_#`)X=[1,-1,0,0,-Y,Y,-X,X,-X,X][C]Y=[0,0,1,-1,-a,a,Y,-Y,-Y,Y][C]x+=X
x=x%L
y+=Y
y=y%#f}until[c=";"]}

Спробуйте в Інтернеті!

Перевірте виходи!

Пояснення (застаріле)

F f{                          /* Declares a function F with parameter f */
                              /* Takes a 2D array of single-char Strings as f */
L =                           /* L contains the value of the length of the longest line*/
    f()                       /* Push the contents each element of f to the stream; this pushes each line*/
        | [#_]                /* Pull a line and push its length to the stream*/
               |sort|tail     /* Sort it and get the last value (the largest one) */
c=""                          /* c contains the value of the current char that is being processed */
x=0; y=0                      /* x and y contain the position of the fish */
X=1; Y=0                      /* X and Y contain the direction of the fish */
{ ... }while [c != ";"]       /* While c is not `;` do: */
l=f[y]                        /*  l is the line (row) the fish is at */
c=" " if [x >= #l]            /*  If x is more than or equal to the line's length, set c to a space (so that we don't need to pad spaces to the array at the beginning)*/
else c = l[x]                 /*  Else set c to the character a position x of l*/
[c]                           /*  Push c to the output stream; ie prints c without a trailing newline*/
a = X                         /*  a preserves the value of X before analysing c */
C = indexOf(c,`><v^/\|_#`)    /*  Simple enough */
X=[1,-1,0,0,-Y,Y,-X,X,-X,X][C]/*  Map each value of C to their respective X-direction in the array */
                              /*  If c cannot be found in `><v^/\|_#` then it will be given the value of -1, or in other words, the -1th element of an array its last element */
Y=[0,0,1,-1,-a,a,Y,-Y,-Y,Y][C]/*  Do the same thing for Y */
x += X                        /*  Change the x-pos by the X-direction */
x = x%L                       /*  Wrap around the right edge */
y += Y                        /*  Do the same for y */
y=y%#f                        /*  But wrap around the bottom instead */
x+=L if[x<0]                  /*  Wrap around the left */
y+=#f if[y<0]                 /*  Wrap around the top */
}

Правки

  • 10 байт, збережених завдяки @fergusq, використовуючи %замість того, щоб перевіряти, чи x чи y перевищує межі, що проклало шлях ще на 2!
  • Використовується `\`замість"\\"
  • Перейшов c=""до другого рядка, а після цього видалив новий рядок
  • Перенесли перетворення рядків в односимвольний масив у петлі, а не на початку (надихнувши відповіддю Python)
  • Використовувався синтаксис whileдужок (спасибі @fergusq за те, що помітив це)
  • Перенесено a=Xз if-заяви
  • Завдяки @fergusq знайшов коротший спосіб знайти довжину найдовшої лінії
  • Використовується синтаксис масиву замість операторів if (як відповідь Python) для збереження тонни байтів
  • Видалено код, що додає пробіли, натомість пробіли додаються у міру руху <<>
  • Виправлена ​​помилка завдяки одному гравцю завдяки "@fergusq"
  • Видалено код +1в кінці indexOfта реструктуризований код, щоб зберегти 2 байти
  • Збережено 2 байти, переміщаючи речі (спасибі @fergusq знову)
  • Збережено 1 байт завдяки @fergusq, використовуючи інший метод пробілів
  • Збережено 1 байт, використовуючи until[c=";"]замістьwhile[c!=";"]
  • Завдяки підказці від @fergusq я видалив цикл, який прошиває пробіли, і замінив його l.=[" "]*L
  • Збережено понад 20 байтів, видаливши оператори if на кінці, які обертають програму навколо лівого та верхнього краю

Я думаю, ви можете зберегти кілька байтів, використовуючи x=((x+X)%#l)замість x+=X. На жаль, (-1)%#lвсе одно повертається -1.
fergusq

@fergusq Полюбив вашу пропозицію :)
Kritixi Lithos

Ви можете використовувати його з yдуже: y=y%#f.
fergusq

@fergusq Якраз збирався додати це :)
Kritixi Lithos

Я подумав про це докладніше, ось ще два поради щодо гольфу: використовуйте keyзамість cmpі використовуйте {...}while[...]замість while[...]do ... done.
fergusq

10

Пітон 2, 262 243 237 235 234 233 231 221 219 218 217 байт

Вводиться як " ['<line_1>', '<line_2>', ...]

i=input()
q=max(map(len,i))
i=[k+' '*q for k in i]
x=y=k=0
j=1
o=''
while';'not in o:r=[1,-1,-j,-k,0,0];o+=i[y][x];l='><#\\v^/|_'.find(o[-1]);a=(r+[k,-j,j])[l];k=([k,-k,k,j]+r)[~l];j=a;x=(x+j)%q;y=(y-k)%len(i)
print o

Спробуйте в Інтернеті!

-19 байт завдяки @math_junkie
-6 байтів завдяки @ThisGuy
-2 байтам шляхом вилучення max(map(L,i))змінної (бо теоретично вона використовується двічі).
-1 байт, зменшивши кількість разів i[y][x].
-1 байт, використовуючи, '\x00'тому мені не доведеться виконувати [1:]частину o[1:]у висновку
-2 байти, використовуючи \0замість \x00
-10 байт завдяки @KritixiLithos, зрозумівши, що я можу прокладати стільки, скільки хочу на правій стороні, тому що extra буде проігноровано
(без зміни байтів) виправлена ​​помилка, оскільки вилучена змінна була поза циклом
-2 байтів, тому що зараз я використовую лише len2 рази, тому переназначення займає 2 додаткові байти
-2 байта, використовуючи while';'not in oзамістьwhile o[-1]!=';', і використання o=''замість o='\0'. Це не тільки економить 2 байти, але й позбавляється від провідного нульового байта, який технічно був не дійсний.

Пояснення

i = input()                       # Takes input as an array of strings
q = max(map(len,i))               # Finds the width of the longest line
i = [k + ' ' * q for k in i]      # Makes sure everything is at least that width
x = y = k = 0                     # Set the point to (0, 0). Set the vertical motion to 0
j = 1                             # Set the horizontal motion to 1
o = '\0'                          # Initialize the output to a null byte (this is output as nothing, so it doesn't actually affect output)
while o[-1] != ';':               # While the last character in the output is not ';' (this is why the output needs to be initialized with something, otherwise o[-1] gives an index error)
    r = [1,-1,-j,-k,0,0]          # Some of the vertical and horizontal coordinates correspond in opposite order
    o += i[y][x]                  # Add the current character to the output
    l = '><#\\v^/|_'.find(o[-1])  # Find the index of the current character here (or -1 if it's just a regular character)
    a = (r + [k, -j, j])[l]       # The fancy array contains the horizontal movement for each control character
    k = ([k, -k, k, j] + r)[~l]   # The fancy array contains the vertical movement for each control character. Using ~l to get the right index, because r has the values backwards
    j = a                         # a was a placeholder because otherwise k would not be correct
    x = (x + j) % q               # Adjust the pointer position
    y = (y - k) % len(i)          # Adjust the pointer position
print o                           # Print the output after the loop is finished

Ви можете грати в гольф, tryоскільки findповернення -1не знайдено: TIO
математика наркоман

@math_junkie О добре, дякую!
HyperNeutrino

Ви можете призначити lenзмінну, наприклад, Lзберегти 3 байти та ще 4, змінивши багаторядкове призначення 0на 1 рядок x=y=k=0.
caird coinheringaahing

@ThisGuy Дякую!
HyperNeutrino

2
@Cole У запропонованому нами гольфі я додав j та k в кінці кожного масиву. Це так, що напрямок підтримується
математика наркоман

5

Рубі, 274 200 187 183

Збривають тільки ще кілька символів, знижуючи масив імпульсу, d.

Я дуже пишаюся цим. Це було весело! Він займає масив рядків і повертає належний рядок.

->a{o,x,y='',-1,0
b,m=1,0
(o+=n=a[y=(y+m)%a.size][x=(x+b)%(a.map &:size).max]||' '
b,m=([1]+[0,-1,0]*2+[1,-m]+[-b,m,b]*2+[-m,-b,-m,b,m])[2*('><^v/\\|_#'.index(n)||9),2])until o[?;]
o}

Прокоментовано нижче.

->a{
    o,x,y='',-1,0  # o is the output string, x and y are the positions in the array
    b,m=1,0          # b and m are the direction of momentum
    until o[?;] # until o contains a semicolon
        w=(a.map &:size).max # w is the max width of the arrays
        h=a.size    # h is the height of arrays
        x=x+b % w   # increment cursor position
        y=y+m % h
        o+=n=a[y][x]||' ' # add the new char (or " ") to o
        ix=2*('><^v/\\|_#'.index(n)||9) # find the index new char in the string
        b,m=([1]+[0,-1,0]*2+[1,-m]+[-b,m,b]*2+[-m,-b,-m,b,m])[ix,2] # set momentum to its new value
    end
    o # return output string
}

1

PHP 7, 291 260 байт

for($m=max(array_map(strlen,$z=explode("
",$argv[1]))),$y=0,$r=count($z)-$v=1;';'!=$c;[$v,$w]=[[$v,1,-1,0,0,-$w,$w,-$v,$v,-$v][$o=strpos(' ><^v/\|_#',$c)],[$w,0,0,-1,1,-$v,$v,$w,-$w,-$w][$o]],$x+=$m+$v,$x%=$m,$y=0<=($y+=$w)?$r<$y?:$y:$r)echo$c=$z[$y][$x]??' ';

Я рахую 291 байт / символів.
HyperNeutrino

Ви маєте рацію, я не можу порахувати, мабуть, = P
chocochaos

Га, не хвилюйся, я теж це зробив.
HyperNeutrino

Я знайшов деякі речі для гольфу, знизивши це на 25% до 218 байт. Не перевірена, але, безумовно, варто подивитися .
Тит

2
недолік в одному з моїх гольфів та ще шість байтів у гольфі: оновлений список для гольфу .
Тит

1

JavaScript, 242 236 235 231 220 байт

a=>{n=a.length;m=x=y=p=0;a.map(g=>m=(w=g.length)<m?m:w);q=1,o="";while((t=a[y][x]||" ")!=";")o+=t,h=q,q=[q,1,0,p,-q][(s=">v\\| <^/_#".indexOf(t)+1)%5]*(r=s>5?-1:1),p=[p,0,1,h,p][s%5]*r,x=(x+q+m)%m,y=(y+p+n)%n;return o+t}

Спробуйте в Інтернеті!


ви можете зберегти 13 char, якщо взяти рядок як масив. Характеристики були змінені.
Не те, що Чарльз
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.