Dane wejściowe będą się składały z następujących znaków:
^
: Idź w góręv
: Zejdź jeden▲
lubk
: Idź o dwa wyżej▼
lubj
: Zejdź dwa
Na przykład następujące dane wejściowe:
^^▲^v▼▲^^v
dałoby następujące dane wyjściowe:
^
^ ^ v
▲ v ▲
^ ▼
^
Sekwencje specjalne, które poruszają kursorem, takie jak \e[B
są niedozwolone. Musisz wygenerować wynik za pomocą spacji i znaków nowej linii.
Oto kilka innych przypadków testowych.
▲v^v^v^v^v^v^v^v▲
▲
▲ ^ ^ ^ ^ ^ ^ ^
v v v v v v v v
^^^^^^^▲▲▲▼▼▼vvvvvv
▲
▲ ▼
▲ ▼
^ ▼
^ v
^ v
^ v
^ v
^ v
^ v
v^^vv^^vvv^v^v^^^vvvv^^v^^vv
^ ^ ^
^ v ^ v ^ v ^
v v v ^ ^ ^ v ^ ^ v
v v v v ^ v v
v
j
na dwa razy w dół ik
na dwa razy w górę.Odpowiedzi:
Pyth, 27 bajtów
Wypróbuj online: pakiet demonstracyjny lub testowy
Używam
k
ij
zamiast▲
i▼
. Istnieje wiele wiodących i końcowych pustych linii. Musisz znaleźć sporo, aby znaleźć obraz. Oto 34-bajtowa wersja, która usuwa wszystkie wiodące i końcowe puste linie.Wypróbuj online: Demonstracja lubpakiet testowy
Wyjaśnienie:
źródło
Nieczytelny ,
219921452134210420872084 bajtówObsługuje zarówno
k
/j
jak i▲
/▼
składnię.Zgodnie z dobrą Nieczytelną tradycją program jest sformatowany czcionką proporcjonalną, aby zaciemnić różnicę między apostrofami a podwójnymi cudzysłowami:
To było niesamowite wyzwanie. Dziękujemy za wysłanie wiadomości!
Wyjaśnienie
Aby poczuć, co Nieczytelne może, a czego nie może zrobić, wyobraź sobie, że Brainfuck ma nieskończoną taśmę w obu kierunkach, ale zamiast wskaźnika pamięci przesuwającego się o jedną komórkę na raz, możesz uzyskać dostęp do dowolnej komórki pamięci, usuwając odwołanie ze wskaźnika. Jest to bardzo przydatne w tym rozwiązaniu, chociaż inne operacje arytmetyczne - w tym modulo - muszą być wykonywane ręcznie.
Oto program jako pseudokod z komentarzem reżysera:
Tyle o logice programu. Teraz musimy przetłumaczyć to na Nieczytelne i zastosować kilka ciekawszych sztuczek golfowych.
Zmienne są zawsze dereferencyjne numerycznie w Nieczytelne (np. Stają
a = 1
się czymś podobnym*(1) = 1
). Niektóre literalne liczby są dłuższe niż inne; najkrótsza to 1, następnie 2 itd. Aby pokazać, o ile dłuższe są liczby ujemne, oto liczby od -1 do 7:Oczywiście chcemy przypisać zmienną nr 1 do tej, która występuje najczęściej w kodzie. W pierwszej pętli while jest to zdecydowanie
mod5
, co pojawia się 10 razy. Ale nie potrzebujemymod5
już po pierwszej pętli while, więc możemy ponownie przydzielić tę samą lokalizację pamięci do innych zmiennych, których będziemy używać później. To sąptr2
iptr3
. Teraz zmienna odnosi się w sumie 21 razy. (Jeśli próbujesz samodzielnie policzyć liczbę wystąpień, pamiętaj o policzeniu czegoś takiego jaka++
dwa razy, raz dla uzyskania wartości i raz dla jej ustawienia).Jest tylko jedna zmienna, której możemy użyć ponownie; po obliczeniu wartości modulo
ch
nie jest już potrzebne.up
idn
pojawiają się tyle samo razy, więc albo jedno jest w porządku. Połączmy sięch
zup
.To pozostawia w sumie 8 unikalnych zmiennych. Możemy przypisać zmienne od 0 do 7, a następnie uruchomić blok pamięci (zawierający znaki i numery wierszy) na 8. Ale! Ponieważ 7 ma taką samą długość w kodzie jak -1, równie dobrze możemy użyć zmiennych od -1 do 6 i rozpocząć blok pamięci od 7. W ten sposób każde odniesienie do początkowej pozycji bloku pamięci jest nieco krótsze! To pozostawia nam następujące zadania:
Teraz to wyjaśnia inicjalizacji na samej górze: to 5 bo to 7 (początek bloku pamięci) minus 2 (obowiązkowy przyrost pierwszy podczas stanu). To samo dotyczy pozostałych dwóch wystąpień 5 w ostatniej pętli.
Zauważ, że ponieważ 0 i 4 mają taką samą długość w kodzie
ptr
iminLine
mogą być przydzielane w obie strony. ... Czy mogliby?Co powiesz na tajemniczą 2 w pętli while last-last? Czy nie powinno to być 6? Chcemy tylko zmniejszać liczby w bloku danych, prawda? Gdy osiągniemy 6, jesteśmy poza blokiem danych i powinniśmy przestać! Byłaby to luka bezpieczeństwa związana z błędem błędu przepełnienia bufora!
Zastanów się, co się stanie, jeśli nie przestaniemy. Zmniejszamy zmienne 6 i 4. Zmienna 6 to
mod4
. Jest to używane tylko w pierwszej pętli while i nie jest już tutaj potrzebne, więc nie wyrządzisz żadnej szkody. Co ze zmienną 4? Jak myślisz,ptr
jaka powinna być zmienna 4, czy powinna byćminLine
? Zgadza się,minLine
w tym momencie nie jest już używany! Zatem zmienna nr 4 jestminLine
i możemy ją bezpiecznie zmniejszać i nie wyrządzać żadnych szkód!AKTUALIZACJA 1! Golfed od 2199 do 2145 bajtów przez świadomość, że
dn
mogą również zostać połączone zmod5
, choćmod5
nadal jest używana do obliczania wartości dladn
! Nowe przypisanie zmiennych to teraz:AKTUALIZACJA 2! Gra w golfa od 2145 do 2134 bajtów, zdając sobie sprawę, że ponieważ
mod5
jest teraz w tej samej zmiennej codn
, która jest liczona do 0 w pętli while,mod5
nie musi już być jawnie inicjowana na 0.AKTUALIZACJA 3! Grał w golfa od 2134 do 2104 bajtów, realizując dwie rzeczy. Po pierwsze, mimo że „negatywne modulo” Chodziło o to, warto na
mod5
, to samo rozumowanie nie dotyczymod4
, bo nigdy Test przeciwkomod4+2
etc. Dlatego zmieniamod4 ? mod4+1 : -3
sięmod4 ? mod4-1 : 3
przenosi nas do 2110 bajtów. Po drugie, ponieważmod4
zawsze wynosi 0 lub 2, możemy zainicjowaćmod4
na 2 zamiast 0 i odwrócić dwie trójki (mod4 ? 3 : 1
zamiastmod4 ? 1 : 3
).AKTUALIZACJA 4! Gra w golfa od 2104 do 2087 bajtów, zdając sobie sprawę, że pętla while, która oblicza wartości modulo, zawsze działa co najmniej raz, aw takim przypadku Nieczytelny pozwala ponownie użyć wartości ostatniej instrukcji w innym wyrażeniu. Zatem zamiast tego
while --ch: [...]; up = (mod5 ? mod5+1 ? [...]
mamy terazup = ((while --ch: [...]) ? mod5+1 ? [...]
(a wewnątrz tej pętli while obliczamymod4
najpierw, więcmod5
jest to ostatnia instrukcja).AKTUALIZACJA 5! Grał w golfa od 2087 do 2084 bajtów, zdając sobie sprawę, że zamiast zapisywać stałe
32
i10
(spację i nową linię ), mogę zapisać liczbę 10 w (teraz nieużywanej) zmiennej nr 2 (nazwijmy toten
). Zamiastptr3 = 5
pisaćten = (ptr3 = 5) + 5
,32
staje sięten+22
iprint 10
stajeprint ten
.źródło
CJam, 37 bajtów
Wyświetla puste linie przed i po żądanym wyjściu, na co zezwolił OP .
Wypróbuj online w interpretatorze CJam .
Jak to działa
źródło
Python 2, 102
Drukuje linia po linii.
Pętla przechodzi przez znaki na wejściu i śledzi bieżącą wysokość. Wysokość jest aktualizowana przez jeden z
+2, +1, -1, -2
obliczonych przez'kv_^j'.find(c)-2
. Prawdopodobnie istnieje krótszy łańcuch modówGdy bieżąca wysokość jest równa numerowi linii (która może być ujemna), dodajemy bieżący znak do linii, a w przeciwnym razie dodajemy spację. Następnie drukujemy linię. W rzeczywistości krócej jest rozpocząć wysokość od bieżącego numeru linii i odjąć zmiany wysokości, dodając znak, gdy wartość osiągnie wartość
0
.Numery linii obejmują wystarczająco duży zakres, że sekwencja dwóch w górę lub w dół dwóch pozostanie w nim. W rzeczywistości istnieje spora nadwyżka. Gdybyśmy mieli górną granicę długości wejściowej, powiedzmy, że pisanie byłoby krótsze
j=999
.Co zaskakujące,
i and' 'or c
był krótszy niż zwykle[' ',c][i==0]
. Zauważ, żei
może być negatywne, co eliminuje niektóre zwykłe sztuczki.źródło
MATLAB, 116
To poczatek.
j
Ik
sprawiają, że ból w szyi, jak nie mogę znaleźć sposób matematycznie Mapa odj^vk
do[-2 -1 1 2]
i z MATLAB nie uznając widocznie Unicode (zarówno w górę iw dół mają wartość 26 w MATLAB. Domyśl!), Istnieje wiele bajtów zmarnowało się podczas mapowania.Czerpiąc inspirację z rozwiązania @xnors, można zmniejszyć kod o kolejne 14 znaków, odwzorowując znak kontrolny wewnątrz pętli for.
Istnieje również wiele bajtów zmarnowanych na próbę uwzględnienia, czy ciąg wejściowy odsyła wzorzec z powrotem poniżej indeksu, przy którym się zaczął (być może, jeśli istnieje ograniczenie długości łańcucha, mógłbym uprościć ten bit).
I w czytelnej formie:
źródło
b=[-2 -1 1 2](a==[106 107 94 118])
zadziała? Działa w Octave. A nawetb=[-2 -1 1 2](a-94==[12 13 0 24])
jeśli chcesz zgolić jeszcze jeden bajt!==
przystanków, które działają, a także w MATLAB nie można umieścić()
po[]
.+=
, fwiw.)JavaScript (ES6), 140
Test running the snippet below in a EcmaScript 6 compliant browser (tested on Firefox) .
źródło
GS2, 34 bytes
This one correctly calculates the output bounds so no excess whitespace is produced. Here's my solution in hex
A little explanation is in order. On the stack we have user input as an array of ascii codes. The program starts in a string literal because of the
05
. Here we go.GS2, 24 bytes
I also have a 24 byte solution that doesn't take as much care calculating output size, and ends up with extra whitespace. I prefer the one with the whitespace kept to a minimum though.
źródło
Crayon, 13 bytes (non-competing)
Try it online! Uses the real arrows because why not.
Non-competing because Crayon is way newer than this challenge.
How it works
Crayon is a stack-based language designed to be killer at ASCII-art challenges. It is built around the basis of a 2-dimensional output "canvas", and a "crayon", a cursor that travels around this canvas. Anything that is sent to output is drawn on the canvas at the position of the crayon, and in the direction the crayon is facing. By default, the crayon points East (to the right).
źródło
pb - 136 bytes
Uses
k
andj
instead of▲
and▼
.A couple of notes:
Escape sequences that move the cursor such as \e[B are not allowed. You must produce the output using spaces and newlines.
I do follow this rule! pb uses the concept of a "brush" to output characters. The brush moves around the "canvas" and can print a character immediately below it. However, the actual implementation prints the character using spaces and newlines.You are allowed trailing spaces and/or empty lines
. This is for a couple of reasons:n
it starts atY=3n+1
. The-1
is because it's going down3n
fromY=-1
, and starting atY=2n-1
fails for an input of allk
.You can watch this program in action on YouTube! This version is slightly modified in that it only goes down to
n-1
. It works for this input, but will fail for others. It does, however, capture a lot nicer.With comments:
źródło
Ceylon, 447 bytes
Or with line breaks for "readability":
import ceylon.language{o=null,v=variable,s=shared}s void y(){v L c;v L f;v L l;v Integer i=0;class L(v L?p,v L?n){s v String t="";s L u=>p else(f=p=L(o,this));s L d=>n else(l=n=L(this,o));s void a(Character c)=>t=t+" ".repeat(i-t.size)+c.string;}f=l=c=L(o,o);for(x in process.readLine()else""){switch(x)case('^'){c=c.u;}case('v'){c=c.d;}case('▲'|'k'){c=c.u.u;}case('▼'|'j'){c=c.d.d;}else{}c.a(x);i++;}print(f.t);while(f!=l){f=f.d;print(f.t);}}
This works with both the ▲/▼ and the j/k input (If we had to support just one of them, the program would be 8 bytes shorter). The last output line is empty when the starting position was on it (i.e. the first input was a
▲
or^
and we never got below that again later). Input which is not one of the specified characters will simply be printed as-is, without switching the line:→
Here is a formatted version (753 bytes):
This is an almost straight-forward "object-oriented" program ... the (local) class
L
(line buffer) stores a line of text (int
), as well as (nullable) pointers to the next (n
) and previous (p
) line. The (not nullable) attributesu
(for up) andd
(for down) initialize those if needed (with a reverse pointer to itself), and in this case also keep track of the first and last line overall (in thef
andl
variables).The
a
(append) method appends a character to this line, including some spaces eventually necessary.c
is the current line. We parse the input string (usingreadLine
as the input should be on one line) using a switch statement which updates the current line, and then calls the append method.After parsing is done, we iterate over the lines from the first to the last, printing each of them. (This destroys the
f
pointer, if it were needed afterwards, we should have used a separate variable for this.)Some used tricks for golfing:
Some stuff which in other languages would be keywords are actually just identifiers in the
ceylon.language
package, and can be renamed with an alias import – we used this for the annotationsshared
(used 5×) andvariable
(used 6×), as well as for the objectnull
(used 4×):(Trivia: The Formatter in the Ceylon IDE formats some built-in language annotations, between them
variable
andshared
, by putting them in the same line as the annotated declaration, contrasted to custom annotations, which are put on a separate line above the declaration. This makes the formatted version of the golfed program unreadable, therefore I changed the alias-imports back for this version.)this
,void
,case
,else
are actual keywords and cannot be renamed this way, andInteger
,String
andCharacter
appear just once each, so there is nothing to be gained by importing.Originally I also had a separate ScreenBuffer class (which kept track of the linked list of line buffers, the current index, and so on), but as there was only ever one object of it, it was optimized away.
That Screenbuffer class also had
up
anddown
methods, which were called from the parser (and just didcurrentLine = currentLine.up
respectivelycurrentLine = currentLine.down
). It showed that directly doing this in the parser's switch is shorter. It also allowed to writecurrentLine = currentLine.up.up
(which later becamec = c.u.u
) instead ofcurrentLine = currentLine.up;currentLine = currentLine.up
.Originally we did pass the current index as an argument into the append method (and even to the parser from the loop) – having it a variable in the containing function is shorter.
Originally my printAll method used the current pointer and moved it first up until the current line was empty, and then down while printing each line. This broke when using ▲ and ▼ to jump over lines, so we had to explicitly append something in those jumped lines instead. Keeping track of first/last line proved easier (though it made it necessary to use two print statements, because there is no do-while-loop in Ceylon).
Originally I had something like this:
process.readLine
returnsnull
if there is no line which can be read (because the input has been closed), and the Ceylon compiler requires me to checkfor that before I accessinput
. As in this case I want to do nothing, I can equivalently use theelse
operator which returns its first argument if not null, and otherwise its second argument, saving the variable and the if-statement. (This also would allow us to encode a default input for testing:for (x in process.readLine() else "^^▲^v▼▲^^v") {
)źródło
JavaScript (ES6), 228 bytes
Well, here is a (rather long) recursive solution that passes all of the test cases given. It was a nice challenge. This uses
k
andj
in place of▼
and▲
.Test Snippet
Although the submission itself can only handle
k,j
, the following snippet can handle bothk,j
and▼,▲
.źródło