Wprowadzenie
Więc marnuję swój czas, ponownie badając algorytmy sortowania sufiksów, oceniając nowe pomysły ręcznie i w kodzie. Ale zawsze staram się zapamiętać rodzaj moich sufiksów! Czy możesz mi powiedzieć, jakiego typu są moje sufiksy?
Najbardziej lewe co?
Wiele algorytmów sortowania sufiksów (SAIS, KA, mój własny daware) grupuje sufiksy do różnych typów w celu ich posortowania. Istnieją dwa podstawowe typy: typu S i L typu przyrostki. Sufiksy typu S to sufiksy, które są leksykograficznie mniejsze ( S maller) niż następujący sufiks i typ L, jeśli jest leksykograficznie większy ( L arger). Najbardziej lewy typ S ( typ LMS ) to po prostu: sufiks typu S poprzedzony sufiksem typu L.
Cechą szczególną tych sufiksów typu LMS jest to, że po ich posortowaniu możemy posortować wszystkie pozostałe sufiksy w czasie liniowym! Czy to nie jest niesamowite?
Wyzwanie
Podany ciąg znaków zakłada, że jest zakończony znakiem specjalnym, który jest mniejszy niż jakikolwiek inny znak w tym ciągu (np. Mniejszy niż nawet bajt zerowy). Wypisuje znak typu corrosponding dla każdego przyrostka.
Można dowolnie wybrać, które char do użytku, do którego typu, ale wolałbym L, S and *
na L-, S- and LMS-type
tak długo, jak są one wszystkie do druku ( 0x20 - 0x7E
).
Przykład
Biorąc pod uwagę ciąg mmiissiissiippi
wyjściowy (przy użyciu L, S and *
):
LL*SLL*SLL*SLLL
Na przykład pierwszy L
wynika z faktu, że mmiissiissiippi$
jest leksykograficznie większy niż miissiissiippi$
( $
reprezentuje dodany minimalny znak):
L - mmiissiissiippi$ > miissiissiippi$
L - miissiissiippi$ > iissiissiippi$
* - iissiissiippi$ < issiissiippi and preceeded by L
S - issiissiippi$ < ssiissiippi$
L - ssiissiippi$ > siissiippi$
L - siissiippi$ > iissiippi$
* - iissiippi$ < issiippi$ and preceeded by L
S - issiippi$ < ssiippi$
L - ssiippi$ > siippi$
L - siippi$ > iippi$
* - iippi$ < ippi$ and preceeded by L
S - ippi$ < ppi$
L - ppi$ > pi$
L - pi$ > i$
L - i$ > $
Kilka innych przykładów:
"hello world" -> "L*SSL*L*LLL"
"Hello World" -> "SSSSL*SSLLL"
"53Ab§%5qS" -> "L*SSL*SLL"
Cel
Nie jestem tu po to, by drażnić Petera Cordesa (kiedyś zrobię to przy przepełnieniu stosu); Jestem po prostu bardzo leniwy, więc to jest oczywiście golf golfowy ! Najkrótsza odpowiedź w bajtach wygrywa.
Edycja: Kolejność znaków jest podana według wartości bajtów. Oznacza to porównanie powinno być jak C użytkownika strcmp
.
Edycja2: Jak podano w komentarzach, wyjście powinno być pojedynczym znakiem dla każdego znaku wejściowego. Chociaż założyłem, że byłoby to rozumiane jako „zwróć ciąg”, wydaje się, że co najmniej 1 odpowiedź zwraca listę pojedynczych znaków. Aby nie unieważniać istniejących odpowiedzi, pozwolę ci zwrócić listę pojedynczych znaków (lub liczb całkowitych, które po wydrukowaniu dają tylko 1 znak).
Wskazówki dotyczące czasu liniowego:
- Można to zrobić w 2 równoległych iteracjach do przodu lub w jednej iteracji do tyłu.
- Stan każdego sufiksu zależy tylko od pierwszych 2 znaków i rodzaju drugiego.
- Skanując dane wejściowe w odwrotnym kierunku, możesz określić L lub S w następujący sposób:
$t=$c<=>$d?:$t
(PHP 7), gdzie$c
jest obecny znak$d
poprzedniego i$t
poprzedniego typu. - Zobacz moją odpowiedź na PHP . Jutro przyznam nagrodę.
c++
ciągów stylów. Pomyśl o tym jak o danych binarnych.*
znaczy*
oznacza, że odpowiedni sufiks jest typuleft most s-type
.A S-type suffix that is preceeded by a L-type suffix.
.Odpowiedzi:
Haskell ,
64534842 bajtówWypróbuj online!
Bez golfa, z
Char
zamiastInt
:źródło
z=
można je usunąć.go
funkcja przyjmuje dwa argumenty. Pierwszy to znak reprezentujący to, co powinno być użyte do opisaniaS
sytuacji. Drugi to ciąg. Przechodzi rekurencyjnie przez ten ciąg, usuwając pierwszy znak na każdym kroku (właśnie totail
robi). Sztuczka polega na tym, że pierwszy argument jest ustawiony,*
gdy poprzedni wynik był aL
, lub wS
inny sposób. W ten sposób, w przypadku,*
gdyS
należy użyć an lub an , pierwszy argument można zastosować bezpośrednio. Mam nadzieję, że to ma sens.Galaretka ,
25 23 21 2019 bajtówPełny program, który drukuje listę znaków, używając:
(Jako link zwraca listę, w której wszystkie elementy są znakami, z wyjątkiem ostatniego, który wynosi zero.)
Wypróbuj online! lub zobacz pakiet testowy (z konwersją na
LS*
).W jaki sposób?
źródło
+
o strun wydaje vectorise ale efekty bazowe nie są faktycznie Jelly iterables ale struny (np spróbować (!)+@/L€
Lub+@/L€€
lub ...)+
produkuje ciąg znaków. Jest to nieudokumentowana funkcja lub coś, co nazywacie błędem.Python 3,
9287746965 bajtówUżywa
0
doL
,1
doS
i2
do*
. Zawiń łańcuch wejściowy w znaki cudzysłowu; Wierzę, że jest to dozwolone przez konwencję.Wypróbuj online!
Przykładowe zastosowanie:
zapisano 5 bajtów dzięki Leaky Nun, 4 bajty dzięki ovs
źródło
JavaScript (ES6),
5145 bajtówZaoszczędź 6 bajtów dzięki @Neil.
Rekurencyjne rozwiązanie ćwiczenia.
źródło
f=(c,d)=>c&&(d<(d=c<(c=c.slice(1))))+d+f(c,d)
JavaScript (ES6), 52 bajty
Port odpowiedzi @ L3viathan.
źródło
c=1
jakoc=0
...C (clang) , 88 bajtów
Wypróbuj online!
źródło
Haskell ,
7775 bajtów, czas liniowyWypróbuj online!
Jak to działa
Wykorzystuje rekurencję, usuwając jeden znak na raz od początku łańcucha. (Typ łańcucha Haskell jest pojedynczo połączoną listą znaków, więc każdy z tych kroków ma charakter stały).
źródło
S, L and *
?[1,1,2,0,1,1,2,0,1,1,2,0,1,1,1]
to lista liczb jednocyfrowych, a nie lista pojedynczych znaków. W moim przypadku wydaje mi się, że podanie listy liczb nie uratuje mi żadnych bajtów.Python 2 ,
6555 bajtówWersja rekurencyjna, oparta na odpowiedzi L3viathan , wykorzystująca
012
jakoLS*
:Wypróbuj online!
Python 3 ,
6559 bajtówRoztwór rekurencyjne użyciu
L
,S
i*
:Prowadzi ciąg od przodu i zastępuje wszystkie wystąpienia
LS
zL*
Wypróbuj online!
źródło
blah if s else''
→s and blah
zapisuje sześć bajtów. W Pythonie 2str(blah)
→`blah`
zapisuje kolejne trzy bajty na drugim rozwiązaniu.PHP, 82 bajty, czas liniowy
Przechodzi nad wejściem od prawej do lewej i zamienia każdy znak na typ.
Oblicza typ na podstawie bieżącego i poprzedniego znaku (-1 lub 1). Jeśli równy, typ się nie zmienia.
źródło
strtr
PHP , 70 bajtów
L = 1, S = 0, * = 2
Obsługa wielobajtowa jest potrzebna w ostatnim Testcase z
§
+3 Bytesmb_substr
zamiastsubstr
Wypróbuj online!
PHP , 71 bajtów
L = 1, S = 0, * = 2
Wypróbuj online!
PHP , 74 bajty
Wypróbuj online!
źródło
$s=&$argn
całkiem sprytne! Jestem prawie pewien, że jest lepsza odpowiedź;) Mam nadzieję, że ktoś ją wymyśli :)mb_substr
zamiast,substr
jeśli dane wejściowe nie są w prostym zakresie ascii. Czy konieczne jest wsparcie ostatniej skrzynki testowej?§