Twoim zadaniem - jeśli zdecydujesz się to zaakceptować - jest zbudowanie programu, który analizuje i ocenia ciąg (od lewej do prawej i dowolnej długości) tokenów, które podają kierunki - w lewo lub w prawo. Oto cztery możliwe tokeny i ich znaczenie:
> go right one single step
< go left one single step
-> go right the total amount of single steps that you've gone right, plus one,
before you previously encountered this token and reset this counter to zero
<- go left the total amount of single steps that you've gone left, plus one,
before you previously encountered this token and reset this counter to zero
Jest jednak pewien haczyk - tokeny kierunków, które Twój program powinien być w stanie przeanalizować, zostaną przedstawione w tej formie:
<<->-><<->->>->>->
... innymi słowy, są one połączone, a Twoim zadaniem programu jest ustalenie prawidłowego pierwszeństwa wskazówek i liczby kroków do podjęcia (patrząc w przyszłość). Kolejność pierwszeństwa jest następująca (od najwyższej do najniższej):
->
<-
>
<
Jeśli napotkasz <-
gdy od początku lub od ostatniego resetu nie było żadnych kroków w lewo, wykonaj jeden krok w lewo. Ta sama zasada obowiązuje ->
, ale wtedy, gdy idzie się w prawo.
Twój program powinien zaczynać się od 0, a jego wynikiem powinna być liczba całkowita ze znakiem, reprezentująca końcową pozycję końcową.
Możesz oczekiwać, że dane wejściowe będą zawsze prawidłowe (więc nic podobnego <--->>--<
na przykład ).
Przykładowe dane wejściowe:
><->><-<-><-<>>->
Kroki w tym przykładzie:
step | token | amount | end position
------+-------+--------+--------------
1. | > | +1 | 1
2. | < | -1 | 0
3. | -> | +2 | 2
4. | > | +1 | 3
5. | <- | -2 | 1
6. | < | -1 | 0
7. | -> | +2 | 2
8. | <- | -2 | 0
9. | < | -1 | -1
10. | > | +1 | 0
11. | > | +1 | 1
12. | -> | +3 | 4
Dla wyjaśnienia: wyjściem programu powinna być tylko końcowa pozycja końcowa jako liczba całkowita ze znakiem. Powyższa tabela jest tylko po to, aby zilustrować kroki, które podjął mój przykład. Nie trzeba generować takiej tabeli, wiersza tabeli, a nawet samych pozycji krańcowych kroków. Wymagana jest tylko końcowa pozycja końcowa, jako liczba całkowita ze znakiem.
Najkrótszy kod po tygodniu wygrywa.
<-
to jeśli zaraz po nim następuje a<
lub a->
. Nie sposób w tym języku do reprezentowania sekwencji<-
następnie>
- co byłobygo left the total amount of single steps that you've gone left, plus one, then go right one single step
. Czy jest to poprawne i zgodne z projektem?Odpowiedzi:
GolfScript, 46 znaków
Jest to jeden z najbardziej liniowych programów GolfScript, jakie kiedykolwiek napisałem - nie ma w nim ani jednej pętli, ani warunkowego, ani zmiennego przypisania. Wszystko odbywa się za pomocą manipulacji ciągiem:
Po pierwsze, ja zastąpić każde wystąpienie
->
przez)
. Ponieważ dane wejściowe są gwarantowane jako prawidłowe, gwarantuje to, że wszelkie pozostałe wystąpienia-
muszą być częścią<-
.Następnie wykonuję dwie kopie łańcucha. Z pierwszej kopii usuwam postacie
<
i-
pozostawiając tylko>
i)
. Następnie powielam wynik, usuwam wszystkie litery)
s i każdy>
po ostatnim)
z drugiej kopii, łączę je i liczę znaki. Tak więc w efekcie liczę:)
,>
po ostatnim)
, i>
przed ostatnim)
.Następnie robię to samo dla drugiej kopii, z wyjątkiem tego liczenia czasu
<
i<-
zamiast>
i)
oraz usuwanie-
s przed końcową liczbą znaków. Dlatego liczę:<-
,<
po ostatnim<-
, i<
przed ostatnim<-
.Na koniec odejmuję drugą liczbę od pierwszej i wypisuję wynik.
źródło
Python 2.7 -
154147134128 bajtówPoważne zmiany zostały wprowadzone do sposobu działania tego programu. Usunąłem stare wyjaśnienie, które wciąż można znaleźć w historii edycji tej odpowiedzi.
Ten jest obrzydliwy.
Działa prawie tak samo, jak inne odpowiedzi na to pytanie, zastępując znaki w danych wejściowych prawidłowymi instrukcjami w tym języku i wykonując je. Jest jednak jedna zasadnicza różnica:
replace
to długie słowo. Chrzanić to.@ProgrammerDan na czacie wpadł na pomysł
;').replace('
, aby użyć krotki z łańcuchem 4 razy, aby użyć wstępnejstr.format()
metody formatowania tekstu. W%s
drugim wierszu znajdują się cztery wystąpienia ciągu, z których każdy pobiera swoją wartość z powiązanego elementu krotki na końcu. Ponieważ wszystkie są takie same, każdy%s
jest zastępowany przez;').replace('
. Podczas wykonywania operacji otrzymujesz następujący ciąg:Jest to teraz poprawny kod Pythona, który można wykonać
exec
. Zgadza się, kochanie: Nestedexec
pozwala mi używać operacji na łańcuchach, które muszą wykonywać operacje na łańcuchach . Niech ktoś mnie zabije.Reszta jest dość prosta: każde polecenie jest zastępowane kodem, który śledzi trzy zmienne: bieżącą pozycję, liczbę praw od ostatniej
->
i to samo dla leworęcznych i<-
. Wszystko jest uruchamiane, a pozycja jest drukowana.Zauważysz, że tak
raw_input(';')
, używając „;” jako monit, a nieraw_input()
który nie ma monitu. Zapisuje to postacie w nieintuicyjny sposób: Gdybym to zrobiłraw_input()
, musiałbym mieć krotkę wypełnioną).replace('
, a każda instancja%s
miałaby przed nią „; \” z wyjątkiem pierwszej . Otrzymanie monitu tworzy więcej redundancji, dzięki czemu mogę ogólnie zapisać więcej postaci.źródło
list.index()
zwraca,-1
gdy nie uda się znaleźć znaku”… nr. To podnosiIndexError
. Być może pomyliłeś tostr.find
. W rzeczywistości można zastąpić[list('><rl').index(c)]
z['><rl'.find(c)]
.Perl,
134131...9995 bajtówPobiera dane wejściowe jako pojedynczy wiersz na stdin, np .:
lub:
Podzieliłem instrukcje na operatory „prawe” („>” i „->”) oraz „lewe” („<” i „<-”). Zaletą tego jest to, że łatwiej jest wykorzystać równoległość między lewym i prawym operatorem i nie musimy robić nic fantazyjnego, aby tokenizować łańcuch. Każdy „kierunek” traktowany jest jako operacja podstawienia, w której dostosowujemy sumę bieżącą o liczbę kroków wykonanych w tym kierunku, ignorując kierunek odwrotny, który jest realizowany przez inną operację podstawienia. Oto mniej doświadczony przodek tego kodu jako rodzaj dokumentacji:
W poprzedniej iteracji tego kodu wszystkie podstawienia były wykonywane w jednym przebiegu. Miało to tę zaletę, że utrzymywało bezpośrednie odwzorowanie między $ p / $ pos a pozycją, która zostanie zwrócona w dowolnym momencie, ale zajęło więcej bajtów kodu.
Jeśli chcesz użyć () 5.10.0, możesz s / print / say /, aby zgolić kolejne 2 znaki, ale to nie w moim stylu.
źródło
Perl,
8877 bajtówDane wejściowe są oczekiwane przez STDIN, na przykład:
Aktualizacja
Nie ma potrzeby konwertowania ciągu na sumę, ponieważ
s//
już się liczy. :-)Pierwsza wersja
Dane wejściowe są oczekiwane przez STDIN, przykład:
Wyjaśnienie:
Chodzi o to, aby przekonwertować ciąg kierunku na sumę, aby wynik był wyprowadzany za pomocą prostej
print eval
.>
zanim którykolwiek->
zrobi dwa kroki, jeden na raz, a drugi na następny->
. Nie ma znaczenia, który z->
nich podąża za co najmniej jednym z nich. Licznik wewnętrzny jest resetowany po następnym->
, więc>
nie powoduje dalszych kroków, maksimum to dwa kroki. Następnie->
dodaje jeden krok dla siebie, podobnie jak pozostałe>
po ostatnim->
.To samo dotyczy kierunku wstecznego z liczeniem kroków ujemnych zamiast pozytywnych.
Na przykład:
><->><-<-><-<>>->
s/->/+1/
: Zacznij od kierunku do przodu, ponieważ->
ma najwyższy priorytet.Na przykład:
><+1><-<+1<-<>>+1
s/>(?=.*1)/+2/g
: Wzorzec wyprzedzający zapewnia, że konwertowane będą tylko>
przed nim->
.Na przykład:
+2<+1+2<-<+1<-<+2+2+1
s/>/+1/g
: Teraz pozostałe>
są objęte gwarancją.Na przykład:
+2<+1+2<-<+1<-<+2+2+1
s/<-/-1/g
: Analogicznie do tyłu.Na przykład:
+2<+1+2-1<+1-1<+2+2+1
s/<(?=.*-)/-2/g
: We wzorcu przewidywania pełne-1
poprzednie<-
nie jest potrzebne, ponieważ nie ma żadnych-
symboli kierunkowych.Na przykład:
+2-2+1+2-1-2+1-1<+2+2+1
s/</-1/g
: Pozostałe<
po ostatnim<-
są konwertowane.Na przykład:
+2-2+1+2-1-2+1-1-1+2+2+1
print eval
: Oblicz i wyślij wynik.Na przykład:
4
źródło
-p
: 74 bajtów Zmieniłem twójs/>//g
na,y/>//
aby zapisać bajt w każdym przypadku, co pozwoliło również na usunięcie parens w wyrażeniu.Rubin, 141 bajtów
Nie golfowany:
źródło
l=1;r=1
może byćl=r=1
i$><<o
może byćp o
. Myślę, że możesz się dużo golić, zastępując to oświadczenie sprawy mniej masywnym, może coś w stylueval %w(o-=1;l+=1 o+=1;r+=1 o-=l;l=1 o+=r;r=1)['<>LR'.index c]
l=r=1;o=0;gets.gsub('->',??).scan(/<-|./){eval"o+=#{%w[-1;l+ -l;l 1;r+ r;r][$&[-1].ord%4]}=1"};p o
możesz zejść do 94 używającruby -p
D - 243
Gra w golfa :
Bez golfa :
źródło
C,
148141140140:
141:
148:
Z białymi znakami:
Prawdopodobnie dużo więcej miejsca na golfa. W większości zrezygnowałem z próby manipulowania 4 zmiennymi w trójskładnikach, które przechwytywały wartości lv (wciąż wychodziły dłużej i dostawały się później), ale nie było to złe pierwsze przejście. Całkiem proste przejście do tablicy. Pobiera dane wejściowe jako argument wiersza polecenia, dane wyjściowe za pośrednictwem wartości zwracanej.
Potrzebujesz
-std=c99
flagi, aby skompilować ją z gcc.EDYCJA: Tak, jest późno - przegapiłem oczywiste rzeczy.
źródło
main
:main(char*x,char**v)
. Potem masz 138 zamiast 140.>><-
daje 0 zamiast 1 lub><->
daje 0 zamiast 2.char
i*
, i zastąpisz(*(x+1)==45)?(x++,o-=l+2,l=0):(o--,l++)
je(*++x==45)?(o-=l+2,l=0):(x--,o--,l++)
.JavaScript, 136
Unminified:
Jak to działa
Biorąc pod uwagę ciąg znaków
s
tak:Wykorzystuje Regex, aby zastąpić każde polecenie zestawem instrukcji, które modyfikują
z
(położenie końcowe),l
(zapisane ruchy w lewo) ir
zapisane ruchy w prawo. Każdy Regex jest wykonywany w kolejności pierwszeństwa.Powyższe dane wejściowe są konwertowane
s
na:Ładne, prawda?
Na koniec musimy
eval(s)
wykonać instrukcje i ostrzeżenie,z
które zawiera pozycję końcową.źródło
JavaScript (116,
122,130)116:
122:
130:
źródło
JavaScript [217 bajtów]
Prawdopodobnie można go nieco skrócić ...
źródło
PHP,
284282Brak wyrażenia regularnego.
Nie golfowany:
źródło
str_split($i)
(1
domyślnie jest to drugi argument).$i
Prawdopodobnie powinno być$c
, prawda?$i
): P Naprawiono!Kolejne rozwiązanie perla, 113 znaków
Istnieją już dwie odpowiedzi, które to pokonały, to tylko na chichoty. Wykorzystuje podejście oparte na obserwacji Ilmari dotyczącej wartości tokenów:
Trochę eksplodował:
źródło