> <> Brak wody

20

Ukochana ryba, która przepływa przez kod > <> (ezoteryczny język programowania) została wyjęta ze swojego naturalnego środowiska. Ta zmiana sprawiła, że ​​nie jest w stanie poruszać się tak, jak kiedyś: ruch toroidalny był ograniczony do prostego ruchu od lewej do prawej. Ale programy> <> są nadal pisane tak, jakby ryby mogły się przez nie przemieszczać. Drogi programatorze, Twoim zadaniem jest napisanie programu linearyzującego program> <>. I zrób to w jak najmniejszej liczbie bajtów; ryby nie mają bardzo dużych wspomnień.

Ruch w> <>

W> <> ruch jest toroidalny i jedna postać na raz. Oznacza to, że ryba (wskaźnik) może „owinąć się” od końca linii z powrotem do początku. W> <> ryba może również poruszać się od góry do dołu, od dołu do góry i od prawej do lewej, w przeciwieństwie do ruchu większości wskaźników. Tak więc ten wzór ruchu byłby prawidłowy:

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

i kończy się na nieskończonej pętli (zapętla się z powrotem do górnej linii, gdy nieskończenie minie dno).

Ryba porusza się po siatce o długości równej maksimum (długość rzędu) i wysokości równej liczbie rzędów.

Jak ustalić, w którą stronę porusza się ryba? Te polecenia zmieniają wektor kierunku ruchu (np. (-1,0)Oznaczają od prawej do lewej):

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)

Jak wspomniano, ryba zaczyna się poruszać od lewej do prawej, tj. Z wektorem kierunku (1,0). Ryba rozpoczyna analizowanie poleceń, zaczynając od pierwszego polecenia, które widzi i zmienia kierunek, jeśli polecenie pasuje do jednego z wyżej wymienionych zmieniaczy kierunku.

Ryba przestaje się poruszać, gdy widzi a ;i kończy program.

Wejście

Dane wejściowe będą prawidłowym (np. Nieskończenie zapętlonym) programem podanym przez STDIN. Możesz także przeczytać plik, jeśli chcesz. Linie każdego programu niekoniecznie muszą być tej samej długości.

Dane wejściowe są podawane jako ciąg znaków, z nowymi liniami oddzielającymi każdą linię w programie.

Programy nie zapętlają się, co oznacza również, że zawsze kończą się na ;.

Wynik

Wyjście zostanie zlinearyzowane przez program. Oznacza to, że powinieneś zwrócić wszystkie znaki (w tym zmieniacze kierunku), które ryba zobaczyłaby, gdyby uruchomiła program „normalnie”. To są wszystkie postacie na drodze do ;.

Jeśli dane wejściowe mają linie o nierównej długości, a ryba ostatecznie porusza się wzdłuż linii krótszej niż długość najdłuższej linii, powinieneś traktować to tak, jakby ryba poruszała się po przestrzeni (patrz przypadki testowe).

Osoby zaznajomione z> <> będą wiedzieć, że zmieniacze kierunku nie są jedynym sposobem wykonywania w nim ruchu, ale dla uproszczenia traktuj dane wejściowe tak, jakby były jedynym sposobem wpływania na ruch.

Zasady

  1. Obowiązują standardowe luki
  2. Możesz napisać pełny program lub funkcję
  3. Dane wejściowe są dostarczane przez STDIN lub plik jako ciąg znaków zawierający linie programu oddzielone znakami nowej linii ( \n)
    • Możesz przyjmować dane wejściowe inaczej, w granicach rozsądku (nie wahaj się zapytać mnie, czy masz na myśli konkretny rodzaj danych wejściowych). Nie można dopełniać wejścia spacjami, aby dopasować długości linii.
    • Zobacz ten meta post dotyczący elastycznego wprowadzania danych. W obecnej sytuacji ogólny konsensus powinien być możliwie jak najbardziej elastyczny w granicach rozsądku.
  4. Dane wyjściowe to pojedynczy ciąg znaków przez STDOUT lub zwracany przez funkcję (w zależności od tego, co wybierzesz, patrz Zasada 2)

Przypadki testowe

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;


;

;
kapusta
źródło
2
Czy możemy wziąć dane wejściowe jako tablicę ciągów?
Łukasz
2
Czy możemy założyć, że pierwszy znak (lewy górny) nie będzie średnikiem?
Kritixi Lithos
1
@KritixiLithos dobre pytanie, powiem, że nie możesz tego założyć. Dodam przypadek testowy.
cole
1
@Luke możesz traktować dane wejściowe jako tablicę ciągów, jeśli operacja na formacie wejściowym jest bardzo trudna lub niemożliwa (łańcuch z liniami oddzielonymi znakami nowej linii). Zobacz dodaną teraz zasadę 3
cole
3
Obowiązkowe głosowanie za absurdalnym uzasadnieniem
Patrick Roberts

Odpowiedzi:

13

Röda , 405 393 392 391 371 366 361 236 234 232 230 223 200 bajtów

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=";"]}

Wypróbuj online!

Sprawdź wyjścia!

Wyjaśnienie (nieaktualne)

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 */
}

Edycje

  • 10 bajtów zaoszczędzonych dzięki @fergusq dzięki użyciu %zamiast sprawdzania, czy x lub y przekracza granice, co utorowało drogę dla 2 kolejnych!
  • Używany `\`zamiast"\\"
  • Przeniesiony c=""do drugiego wiersza, a następnie usunięty po nim nowy wiersz
  • Przeniesiono konwersję wierszy na tablicę jednoznakową w pętle zamiast na początku (inspirowane odpowiedzią w języku Python)
  • whileUżyłem składni nawiasów klamrowych (dzięki @fergusq za wykrycie tego)
  • Usunięto a=Xz instrukcji if
  • Dzięki @fergusq za znalezienie krótszego sposobu na znalezienie długości najdłuższej linii
  • Użyto składni tablicowej zamiast instrukcji if (jak odpowiedź Python), aby zaoszczędzić mnóstwo bajtów
  • Usunięto kod wypełniający spacje, zamiast tego spacje są dodawane w miarę przesuwania się klawisza> <>
  • Naprawiono błąd dzięki i grał w jedną postać dzięki @fergusq
  • Usunięto kod +1na końcu indexOfi zrestrukturyzowano, aby zapisać 2 bajty
  • Zaoszczędzono 2 bajty, przenosząc rzeczy (dzięki ponownie @fergusq)
  • Zaoszczędzono 1 bajt dzięki @fergusq, stosując inną metodę wypełniania spacji
  • Zapisano 1 bajt, używając until[c=";"]zamiastwhile[c!=";"]
  • Dzięki podpowiedzi @fergusq usunąłem pętlę wypełniającą spacje i zastąpiłem ją l.=[" "]*L
  • Zaoszczędzono ponad 20 bajtów, usuwając na końcu instrukcje if, które owijają program wokół lewej i górnej krawędzi
Kritixi Lithos
źródło
Myślę, że możesz zaoszczędzić kilka bajtów, używając x=((x+X)%#l)zamiast x+=X. Niestety (-1)%#lwciąż powraca -1.
fergusq
@fergusq Grał w golfa swoją sugestią :)
Kritixi Lithos
Można go używać z yza: y=y%#f.
fergusq
@fergusq Właśnie chciałem to dodać :)
Kritixi Lithos
Pomyślałem o tym więcej, oto dwie inne wskazówki dotyczące gry w golfa: używaj keyzamiast cmpi używaj {...}while[...]zamiast while[...]do ... done.
fergusq
10

Python 2, 262 243 237 235 234 233 231 221 219 218 217 bajtów

Pobiera dane wejściowe jako ['<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

Wypróbuj online!

-19 bajtów dzięki @math_junkie
-6 bajtów dzięki @ThisGuy
-2 bajtów przez wyodrębnienie max(map(L,i))do zmiennej (ponieważ teoretycznie jest używana dwukrotnie).
-1 bajt poprzez zmniejszenie liczby i[y][x]wyświetleń.
-1 bajt przy użyciu, '\x00'więc nie muszę wykonywać [1:]części o[1:]wyjściowej
-2 bajtów przy użyciu \0zamiast \x00
-10 bajtów dzięki @KritixiLithos za uświadomienie sobie, że mogę wstawić tyle, ile chcę po prawej stronie, ponieważ dodatkowe zostaną zignorowane
(bez zmiany bajtów) naprawiony błąd, ponieważ wyodrębniona zmienna była poza pętlą
-2 bajtów, ponieważ teraz używam tylko len2 razy, więc ponowne przypisanie zajmuje 2 dodatkowe bajty
-2 bajty za pomocą while';'not in ozamiastwhile o[-1]!=';'i używanie o=''zamiast o='\0'. To nie tylko oszczędza 2 bajty, ale także pozbywa się wiodącego bajtu zerowego, który technicznie nie był tak naprawdę ważny.

Wyjaśnienie

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
źródło
Można golf off tryod findzwrotów -1jeśli nie znaleziono: TIO
matematyki ćpun
@ mat_junkie Oh dobrze, dziękuję!
HyperNeutrino
Możesz przypisać lendo zmiennej, np. LAby zapisać 3 bajty i kolejne 4, zmieniając przypisanie wielowierszowe 0na 1 linię x=y=k=0.
caird coinheringaahing
@ThisGuy Thanks!
HyperNeutrino
2
@Cole W moim słodzonym golfie dodałem j i k na końcu każdej tablicy. Tak więc kierunek jest utrzymany
ćpun matematyki
5

Rubin, 274 200 187 183

Ogolił zaledwie kilka więcej znaków przez upuszczenie tablicę rozpędu d.

Jestem z tego dość dumny. To była zabawa! Pobiera tablicę ciągów i zwraca odpowiedni ciąg.

->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}

Skomentowano poniżej.

->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
}
Nie ten Charles
źródło
1

PHP 7, 291 260 bajtów

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
źródło
Zliczam 291 bajtów / znaków.
HyperNeutrino
Masz rację, najwyraźniej nie liczę = P
chocochaos
Hah Nie martw się, ja też to zrobiłem.
HyperNeutrino
Znalazłem kilka rzeczy do gry w golfa, zmniejszając to o 25% do 218 bajtów. Nie testowane, ale zdecydowanie warte obejrzenia .
Tytus
2
wada jednego z moich golfów i jeszcze sześć bajtów golfa: zaktualizowana lista golfa .
Tytus
1

JavaScript, 242 236 235 231 220 bajtów

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}

Wypróbuj online!

Fəˈnɛtɪk
źródło
możesz zapisać 13 znaków, jeśli weźmiesz ciąg jako tablicę. Specyfikacje zostały zmienione.
Nie to, że Charles