Załóżmy, że naciągasz sznur Froot Loops na naszyjnik, bransoletę, sznurowadło lub cokolwiek innego. Dostępnych jest 6 kolorów pętli: r ed, o range, y ellow, g reen, b lue i p urple. Chcesz, aby twoje pasmo zaczynało się od czerwieni po lewej stronie i kręciło się w tęczowej kolejności w prawo, kończąc na fioletowym. Oznacza to, że chcesz to zrobić, aby twój łańcuch mógł być reprezentowany przez ciąg roygbp
powtórzony kilka razy (być może 0).
Problem polega na tym, że już naciągnąłeś pętle, a nie w określonej kolejności. Które pętle należy jeść, a nie jeść, aby zmaksymalizować liczbę prawidłowych cykli tęczy od lewej do prawej, przy pierwszej czerwonej pętli i ostatniej fioletowej pętli?
Napisz program lub funkcję, która pobierze dowolny ciąg znaków roygbp
i wypisze lub zwróci ciąg o tej samej długości z e
zamiast pętli do zjedzenia i n
zamiast pętli do zjedzenia.
Na przykład, jeśli wyglądało twoje pasmo Pętli Froota
wejście byłoby
gorboypbgbopyroybbbogppbporyoygbpr
i przechodząc od lewej do prawej możemy znaleźć 3 kompletne roygbp
sekwencje tęczy, ale niektóre pętle muszą zostać zjedzone. Tak więc wynik byłby
eenenneennenennneeeeneennenennnnne
w wyniku czego powstaje idealny 3-cyklowy ciąg:
Jeśli na wejściu nie ma pełnych cykli tęczy, wówczas wynik byłby cały e
i nici skończyłyby się bez pętli. np. wejście proygb
ma wyjście eeeeee
. I odwrotnie, proygbp
ma wynik ennnnnn
.
Możesz założyć, że wszystkie łańcuchy wejściowe mają co najmniej jedną pętlę.
Najkrótszy kod w bajtach wygrywa.
r
czyoygbproygbpr
też może się kwalifikować?Odpowiedzi:
Pyth, 31 bajtów
Niesamowicie nieefektywne, wyjaśnienia wkrótce.
yUlz
generuje wszystkie możliwe podzbiory wszystkich możliwych wskaźnikówz
(wejściowych) w kolejności. Np. Jeśli dane wejściowe toabc
:Następnie
hf!
znajduje pierwsząT
z powyższej listy, która:jk.DzT"roygbp"k
jest fałszywa..D
pobiera ciąg i listę indeksów i usuwa elementy z tych indeksów. Tak.D"abcd",1 3
jest"ac"
. Ponieważ.D
zwraca listę (która nie powinna tak być, zostanie naprawiona w przyszłych wersjach Pytha), używamjk
(k
is""
), aby połączyć ją z powrotem w ciąg.:_"roygbp"k
Część zastąpi każde wystąpienie cyklu z pustym ciągiem.Ponieważ pusty ciąg jest fałszywy, powyższe akapity wyjaśniają, w jaki sposób znajduję najmniejszy zestaw wskaźników potrzebnych do zjedzenia, aby uzyskać ciąg składający się tylko z cykli.
:*lz\n_\e
następnie zamienia tę listę indeksów wnnnneeennene
ciąg.źródło
Sześciokąt ,
920722271 bajtówMówisz, że jest sześć różnych rodzajów pętli owocowych? To, co Hexagony została wykonana za.
Okej, nie było. O Boże, co ja sobie zrobiłem ...
Ten kod jest teraz sześciokątem o długości boku 10 (zaczął od 19). Prawdopodobnie może być jeszcze trochę w golfa, może nawet do rozmiaru 9, ale myślę, że moja praca została wykonana tutaj ... Dla odniesienia, w źródle znajduje się 175 faktycznych poleceń, z których wiele jest potencjalnie niepotrzebnymi kopiami lustrzanymi (lub zostały dodane, aby anulować wydać polecenie ze ścieżki krzyżowej).
Pomimo pozornej liniowości kod jest w rzeczywistości dwuwymiarowy: sześciokąt przekształci go w zwykły sześciokąt (co jest również poprawnym kodem, ale wszystkie białe znaki są opcjonalne w sześciokącie). Oto rozwinięty kod w całym ... no cóż, nie chcę mówić „piękno”:
Wyjaśnienie
Nie będę nawet próbował wyjaśniać wszystkich zawiłych ścieżek wykonania w tej wersji golfowej, ale algorytm i ogólny przepływ sterowania są identyczne z tą wersją bez golfa, która może być łatwiejsza do nauki dla naprawdę ciekawych po wyjaśnieniu algorytmu:
Szczerze mówiąc, w pierwszym akapicie żartowałem tylko w połowie. Fakt, że mamy do czynienia z cyklem sześciu elementów, był naprawdę wielką pomocą. Model pamięci Hexagony jest nieskończoną heksagonalną siatką, w której każda krawędź siatki zawiera liczbę całkowitą o dowolnej dokładności, zinicjalizowaną do zera.
Oto schemat układu pamięci, której użyłem w tym programie:
Długi prosty bit po lewej stronie jest używany jako ciąg zakończony 0
a
o dowolnym rozmiarze, który jest powiązany z literą r . Linie przerywane na innych literach reprezentują ten sam rodzaj struktury, każda obrócona o 60 stopni. Początkowo wskaźnik pamięci wskazuje krawędź oznaczoną 1 , zwróconą na północ.Pierwszy, liniowy bit kodu ustawia wewnętrzną „gwiazdę” krawędzi na litery,
roygbp
a także ustawia początkową krawędź na1
, tak abyśmy wiedzieli, gdzie cykl się kończy / zaczyna (pomiędzyp
ir
):Następnie wracamy do krawędzi oznaczonej jako 1 .
Ogólna idea algorytmu jest następująca:
e
na brzegu etykietę ? , ponieważ dopóki cykl się nie zakończy, musimy założyć, że będziemy musieli także zjeść tę postać. Następnie przejdziemy przez pierścień do następnej postaci w cyklu.e
z pola ? krawędzie zn
s, ponieważ teraz chcemy, aby ten cykl pozostał na naszyjniku. Następnie przechodzimy do drukowania kodu.e
in
). Następnie szukamy 1 krawędzi (aby pominąć pozostałą część potencjalnie niepełnego cyklu) przed przejściem do drukowania kodu.e
dla każdego znaku. Następnie przenosi się do ? krawędź związana z postacią. Jeśli jest ujemny, po prostu kończymy program. Jeśli jest pozytywny, po prostu go drukujemy i przechodzimy do następnej postaci. Po zakończeniu cyklu wracamy do kroku 2.Inną rzeczą, która może być interesująca, jest to, jak zaimplementowałem łańcuchy o dowolnym rozmiarze (ponieważ po raz pierwszy użyłem nieograniczonej pamięci w Hexagony).
Wyobraźmy sobie, że jesteśmy w pewnym momencie, dokąd jeszcze czyta znaki dla R (tak, możemy użyć schemat jak jest) i A [0] i 1 zostały już wypełnione znaków (wszystko na północny-zachód z nich jest nadal zerem ). Np. Może właśnie przeczytaliśmy pierwsze dwa znaki wejścia do tych krawędzi i teraz czytamy a .
og
y
Nowy znak jest odczytywany w na krawędzi. Używamy ? krawędzi, aby sprawdzić, czy ten znak jest równy
r
. (Jest tu sprytna sztuczka: sześciokąt może łatwo rozróżniać między dodatnim i dodatnim, więc sprawdzanie równości poprzez odejmowanie jest denerwujące i wymaga co najmniej dwóch gałęzi. Ale wszystkie litery są mniejsze niż współczynnik 2, więc możemy porównać wartości, biorąc modulo, który da zero tylko wtedy, gdy będą równe.)Ponieważ
y
różni się odr
, przechodzimy do (nie znakowanych) od lewej krawędzi w i skopiowaćy
tam. Przechodzimy teraz bliższe okolice sześciokąta, kopiując znak jedną krawędź dodatkowo za każdym razem, dopóki mamyy
na przeciwległej krawędzi w . Ale teraz w [0] jest już postać, której nie chcemy zastępować. Zamiast tego, „drag” THEy
wokół następnego sześciokąta i sprawdzić się 1 . Ale jest tam też postać, więc idziemy o kolejny sześciokąt dalej. Teraz [2] wciąż wynosi zero, więc kopiujemyy
w tym. Wskaźnik pamięci przesuwa się teraz wzdłuż sznurka w kierunku pierścienia wewnętrznego. Wiemy, kiedy osiągnęliśmy początek łańcucha, ponieważ (nieznakowane) krawędzie między a [i] są zerowe, podczas gdy ? jest pozytywny.Prawdopodobnie będzie to przydatna technika do pisania nietrywialnego kodu w Hexagony w ogóle.
źródło
Sześciokąt , 169 bajtów
Zainspirowałem się odpowiedzią Martina Büttnera (to także jego esolang) i zdecydowałem, że mogę to zrobić w rozmiarze 8. (Jestem przekonany, że jest to również możliwe w rozmiarze 7, ale jest to bardzo trudne. Spędziłem już cztery dni -stop na tym.)
Rozłożony sześciokątnie:
Program tak naprawdę nie korzysta z
#
instrukcji, więc użyłem tego znaku, aby pokazać, które komórki są faktycznie nieużywane. Co więcej, każda komórka no-op, która jest przemierzana tylko w jednym kierunku, jest lustrem (np._
Jeśli przemierzana jest poziomo), więc wiesz, że wszystkie.
postacie są przemierzane w więcej niż jednym kierunku.Wyjaśnienie
Na początku wykonujemy sekwencję instrukcji
r''o{{y''g{{b''p"")"
. Są one rozrzucone nieco przypadkowo w całym kodzie, ponieważ wcisnąłem je po napisaniu wszystkiego innego. Używam]
kilka razy, aby przejść do wskaźnika następnej instrukcji; w ten sposób mogę zasadniczo teleportować się do innego rogu sześciokąta. Cała reszta programu jest wykonywana za pomocą wskaźnika instrukcji nr 3.Pamięć wygląda teraz następująco, z ważnymi krawędziami oznaczonymi nazwami, których użyję w tym objaśnieniu:
Oznaczone krawędzie oznaczają:
in
: Używamy tej krawędzi do przechowywania znaku, który czytamy ze STDIN.%
: Używamy tej krawędzi, aby wykonać operację modulo na charakter czytać ze standardowego wejścia (in
) i aktualną „ważny” charakter (r
,o
etc.), co będzie0
, jeśli są one równe. Ukradłem tę sztuczkę z odpowiedzi Martina Büttnera, ale reszta programu jest inna.#
: Dopóki czytamy „nieprawidłowe” znaki (tj. Kolory, które musimy jeść), zwiększamy tę krawędź. Zatem ta krawędź pamięta, ilee
s potrzebujemy później.r?
: Zawsze0
oprócz miejsca, w którym znajduje sięr
(czerwona) część. To informuje nas o zakończeniu cyklu.Program przebiega w ten sposób:
#
. W przeciwnym razie przejdź do następnego segmentu pamięci w kolejności zgodnej z ruchem wskazówek zegara.r?
jest pozytywny, dokonaliśmy całej rewolucji. Zrób kompletną rundę i wyjdź#
e
si 1n
na segment. Spowoduje to#
przywrócenie każdego z nich do0
. (Thee
umieszcza się na nieoznakowanego krawędzi, ale dlan
nas sprzeniewierzeniu się#
przewagę, którą ustawiony0
przy użyciu*
(mnożenie), który działa później, bo wiemy, że wszystkie%
krawędzie są równe zero w tym czasie).#
+1e
s, aż wrócisz do miejsca, w którymr?
jest dodatni, a następnie wyjdź.Po zakończeniu uruchomienia pamięć na końcu wygląda mniej więcej w następujący sposób. Zauważysz krawędzie zawierające
101
(kod ASCIIe
); jedna zin
krawędzi to-1
(EOF); wszystkie#
krawędzie mają wartość 0; i wskaźnik pamięci kończy się na dodatniejr?
krawędzi.źródło
Retina ,
1488579 bajtówMożesz uruchomić to z jednego pliku źródłowego z
-s
flagą interpretera.Wyjaśnienie
Najpierw usuńmy proste rzeczy:
Dołącza
#roygbp
na końcu ciągu, którego użyjemy do dynamicznego obliczenia cyklu liter.Kolejny (długi) krok wymyśla, które pętle należy zachować, i zastępuje je
n
. Za chwilę przyjrzymy się, jak to działa.Pozbywa się to naszego pomocnika wyszukiwania na końcu łańcucha.
Zastępuje to wszystkie postacie, które nie zostały zastąpione w drugim kroku
e
, kończąc transformację.Wróćmy teraz do drugiego kroku.
Podstawowa struktura wykorzystuje sztuczkę, którą odkryłem kilka miesięcy temu, aby zastąpić wybrane postacie w globalnym dopasowaniu:
gdzie
...
odpowiada dowolnie złożonemu wzorowi. To pasuje do znaku, który ma zostać zamieniony,.
a następnie zaczyna szukać (za co należy przeczytać od prawej do lewej). Lookbehind przechwytuje wszystko, aż do dopasowanej postaci w grupieprefix
. Następnie przełącza się na spojrzenie w przyszłość , które zaczyna się od początku łańcucha i może zawierać złożony wzór. Po znaku, który chcemy zastąpić w tej strukturze, kładziemy opcjonalnego wygląd tyłek , który sprawdza, czyprefix
grupa pasuje tutaj. Jeśli tak, przechwytuje pusty ciąg doflag
Grupa. Jeśli nie, ponieważ jest opcjonalny, w ogóle nie wpływa na stan silnika wyrażeń regularnych i jest ignorowany. Wreszcie, po pomyślnym dopasowaniu lookahead pozostaje tylko\k<flag>
koniec, który pasuje tylko wtedy, gdy flaga została ustawiona w pewnym momencie podczas obliczeń.Teraz cofnijmy trochę długi regex, używając nazwanych grup i trybu wolnego miejsca:
Mam nadzieję, że rozpoznajesz ogólny zarys z góry, więc musimy tylko spojrzeć na to, co wpisałem
...
.Chcemy uchwycić następną postać z cyklu do grupy
char
. Robimy to poprzez zapamiętywanie ciągu od#
do bieżącego znaku wcycle
. Aby uzyskać następną postać, używamy lookahead do wyszukiwania#
. Teraz próbujemy dopasować,cycle
a następnie dopasować następny znak wchar
. Zazwyczaj będzie to możliwe, chyba żechar
jest to ostatni znakp
. W takim przypadku\k<cycle>
dopasuje całą pozostałą część łańcucha i nie pozostanie żadna postać do przechwyceniachar
. Tak więc silnik cofa się, pomija odniesienie docycle
i po prostu dopasowuje pierwszy znakr
.Teraz mamy kolejną postać w cyklu
char
, szukamy następnego możliwego wystąpienia tej postaci za pomocą.*?\k<char>
. Są to postacie, które chcemy zastąpić, więcprefix
sprawdzamy po nim. Te kroki (znajdź następnychar
w cyklu, wyszukaj następne jego wystąpienie, ustaw flagę, jeśli to właściwe) są teraz po prostu powtarzane za pomocą+
.To właściwie wszystko, aby znaleźć cykliczną podsekwencję, ale musimy również upewnić się, że zakończymy na
p
. Jest to dość łatwe: wystarczy sprawdzić, czy wartość przechowywana obecnie w jestchar
zgodna z wartościąp
na końcu ciągu z.*\k<char>$
. Zapewnia to również, że nasz ciąg wyszukiwania nie jest używany do zakończenia niekompletnego cyklu, ponieważp
do tego sprawdzenia potrzebujemy znaku końca .źródło
Python 2,
133 130 126121 bajtówPierwsza pętla otrzymuje cykle, a druga usuwa niepełny cykl
Zaoszczędzono 3 bajty dzięki JF i 5 z DLosc
źródło
r
in
takr=n=''
:?R=r.count
nie działa jako ciągi są niezmienne takR
jest''.count
, nawet jeślir
zostanie zmieniony.Perl 5,
7665 bajtówSzczypta czystych nierozcieńczonych wyrażeń regularnych.
Najpierw znajduje to, czego nie należy jeść. To, co pozostaje, jest do zjedzenia.
Test
źródło
[^o]*
itp. Czy możesz użyć.*?
(niepochodni kwantyfikator)?\s
zamiast\n
w klasie znaków ujemnych pierwszej wersji.r(.*?)o(.*?)y(.*?)g(.*?)b(.*?)p
n$1n$2n$3n$4n$5n
[^n\s]
e
(4 pliki, 57 bajtów).Lua, 101 bajtów
Kreatywnie wykorzystuje wzory Lua; Myślę, że to ciekawe podejście.
Zastępuje wszystkie niejedzone znaki „*”, zastępuje wszystkie znaki alfanumeryczne „e”, a następnie zastępuje wszystkie „*” s „n”.
źródło
JavaScript (ES6), 118
Skrzypce przetestowane w przeglądarce Firefox. Słyszę, że Chrome obsługuje teraz funkcje strzałek, ale nie przetestowałem tego jeszcze w Chrome.
Nie golfowany:
źródło
...
jeszcze notacji.gawk, 96
Konstruuje wzorzec wyszukiwania
"([^r]*)r([^o]*)o([^y]*)y([^g]*)g([^b]*)b([^p]*)p"
i zamienia"\\1n\\2n\\3n\\4n\\5n\\6n"
. Po tej zamianie deklaruje wszystko jedzenie („e”), co nie jest częścią kompletnej tęczy.Ta kombinacja automatycznie zapewnia, że podczas tej operacji nie zostaną uszkodzone żadne tęcze, a na końcu nie pojawią się odcięte tęcze.
źródło
Pyth, 42 bajty
Wypróbuj online: Demonstracja
źródło
CJam, 41 bajtów
Podejście brutalnej siły, które wypróbowuje wszystkie odmiany jedzenia / niejedzenia i wybiera tę, która daje najdłuższy, prawidłowy naszyjnik.
Wypróbuj online w interpretatorze CJam .
źródło
CJam, 50 bajtów
Wypróbuj online
Jest to nieco dłużej niż w przypadku niektórych innych zgłoszeń, ale jest bardzo wydajne przy liniowej złożoności. Skanuje ciąg wejściowy i dopasowuje znaki jeden po drugim.
Podstawowa część algorytmu jest w rzeczywistości dość zwarta. Około połowa kodu służy do usunięcia niepełnego cyklu na końcu.
źródło
C90, 142-146 bajtów (do 119, zależnie)
Działa w czasie liniowym, aby skutecznie zjeść te pętle owocowe, które nie mogą być częścią ładnej tęczy. Następnie postproces zabija każdą częściową pętlę na końcu.
Oto cztery wersje:
Wersja 1 (146 bajtów), połączenie z
[name] [string]
:main(int a,char**b){char*v=b[1],*s="roygbp",i=0,k=0;for(;v[i];++i)if(s[k]==v[i]){++k;k%=6;v[i]='n';}else v[i]='e';while(k-->0)v[--i]='e';puts(v);}
Wersja 2 (142 bajty), wywołaj z
[name] [string] [rainbow order]
:main(int a,char**b){char*v=b[1],*s=b[2],i=0,k=0;for(;v[i];++i)if(s[k]==v[i]){++k;k%=6;v[i]='n';}else v[i]='e';while(k-->0)v[--i]='e';puts(v);}
To pozwala zdefiniować własne uporządkowanie tęczy z dowolnymi kolorami, o ile nie są
n
lube
. To sprawia, że kod jest krótszy!Wersja 3 (123 bajty), zadzwoń jak wersja 1:
main(int a,char**b){char*v=b[1],*s="roygbp",i=0,k=0;for(;v[i];++i)if(s[k]==v[i]){++k;k%=6;v[i]='n';}else v[i]='e';puts(v);}
ta daje jak najwięcej tęczy! Niekompletne opadające tęcze obiecują! Nie powinniśmy ich jeść!
Wersja 4 (119 bajtów), wywołanie jak wersja 2:
main(int a,char**b){char*v=b[1],*s=b[2],i=0,k=0;for(;v[i];++i)if(s[k]==v[i]){++k;k%=6;v[i]='n';}else v[i]='e';puts(v);}
Taki sam jak wersja 3, ale TYPY MOAR RAINBOW!
Niewielkie ograniczenie: maszyna musi mieć podpisane znaki (ogólny przypadek), a ciąg znaków musi być dość krótki. Wyprowadza końcowe
\n
dla jasności.Wersja 1 jest jedyną, która wyraźnie spełnia wymagania, chociaż wersja 2 jest dyskusyjna. Wersje 3 i 4 są mniej poprawną (ale wciąż zabawną) interpretacją pytania.
źródło
Pyth, 38 bajtów
Wiem, że jest to znacznie dłużej niż odpowiedź orlp, ale ta działa w czasie liniowym: o)
Wypróbuj tutaj .
W skrócie, ten program zastępuje wszystkie znaki po ostatnim „p” spacjami, a następnie iteruje każdy znak w powstałym ciągu. Jeśli znak jest następnym w sekwencji „roygbp”, wypisz „n”, w przeciwnym razie wypisz „e”.
Z trudem znajdowałem krótszy sposób przetwarzania ciągu wejściowego.
_>_zJ
w szczególności czuje się niezręcznie, ale<Jz
nie podaje wymaganego ciągu, kiedyJ == 0
, tj. gdy wejście kończy się na „p”.źródło
Haskell, 138 bajtów
g
czy to.źródło
f
iz
jako infiks:'n'%'n'='n'
itd. Niektóre nawiasy w definicjig
można usunąć za pomocą$
.JavaScript (ES6),
8582 bajtówReguła „naszyjnik musi kończyć się fioletem” była początkowo wielką przeszkodą, podnosząc mój wynik z 66 do 125, ale znalazłem krótszą drogę (na szczęście!).
Wyjaśnienie:
Ten kod zapętla każdy znak na wejściu i zastępuje każdy z tą logiką
r
lube
z nią:p
, ORAZ postać jest następną w tęczy, zachowaj ją (zamień nan
).e
).Nie golfowany:
Sugestie mile widziane!
źródło
Python 2, 254 bajty
Pętle!
Przepraszam za kalambur. : P
źródło