> <> Из воды

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). Рыба начинает анализировать команды, начиная с первой команды, которую видит, и меняет свое направление, если команда соответствует одному из вышеупомянутых переключателей направления.

Рыба перестает двигаться, когда видит ;и завершает программу.

вход

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

Входные данные даны в виде строки с символами новой строки, разделяющими каждую строку в программе.

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

Выход

Вывод будет линеаризован программой. То есть вы должны вернуть все символы (включая переключатели направления), которые рыба увидит, если она запускает программу «нормально». Это все персонажи на своем пути к ;.

Если на входе есть линии неравной длины, и рыба в конечном итоге движется по линии, которая короче, чем длина самой длинной линии, вы должны рассматривать это так, как если бы рыба двигалась в пространстве (см. Контрольные примеры).

Те, кто знаком с> <>, будут знать, что переключатели направления - не единственный способ сделать движение в нем, но для простоты трактуйте входные данные так, как будто они - единственный способ повлиять на движение.

правила

  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
Можем ли мы предположить, что первый символ (верхний левый) не будет точкой с запятой?
Критиси Литос
1
@KritixiLithos хороший вопрос, я хочу сказать, что вы не можете этого допустить. Я добавлю тестовый пример.
Коул
1
@ Луки, вы можете принять входные данные в виде массива строк, если очень сложно или невозможно работать с форматом ввода (строка со строками, разделенными символами новой строки). См. Добавленное сейчас Правило 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 в конце, которые оборачивают программу вокруг левого и верхнего краев
Kritixi Lithos
источник
Я думаю, что вы можете сэкономить несколько байтов, используя 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

Python 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 за понимание того, что я могу заполнять столько, сколько хочу на правой стороне, потому что дополнительная будет игнорироваться
(без изменения байтов); исправлена ​​ошибка, связанная с тем, что извлеченная переменная находилась вне цикла
байтов -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
HyperNeutrino
источник
Вы можете tryfind-1
наркоман по математике
@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]??' ';
chocochaos
источник
Я считаю 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}

Попробуйте онлайн!

fənɛtɪk
источник
Вы можете сохранить 13 символов, если вы возьмете строку в виде массива. Спецификации были изменены.
Не то чтобы Чарльз