Zrównoważony ciąg to ciąg nawiasów, ()
dzięki czemu każdy nawias można dopasować do drugiego. Bardziej rygorystycznie są to struny łączone przez tę gramatykę:
S → (S)S | ε
Możemy obrócić ciąg „na lewą stronę” przez:
Przełączanie wszystkich wystąpień
(
i)
ze sobąPrzenoszenie znaków od przodu sznurka do tyłu, aż sznurek zostanie ponownie zrównoważony.
Zróbmy przykład.
Zaczynamy od zbalansowanego ciągu:
(()(())())
Następnie zmieniamy pareny, aby zrobić
))())(()((
Następnie przesuwaj postacie z przodu łańcucha na tył łańcucha, aż łańcuch zostanie zrównoważony.
))())(()((
)())(()(()
())(()(())
))(()(())(
)(()(())()
(()(())())
To nasz wynik!
Pamiętaj, że niektóre ciągi znaków można odwrócić na wiele sposobów, na przykład ciąg
(()())
Po wywróceniu na lewą stronę może być:
()(())
lub
(())()
Jednak każdy ciąg ma co najmniej jedno rozwiązanie .
Zadanie
Napisz program, który pobierze zbalansowany ciąg znaków jako wejście i wyjście tego łańcucha wywróconego na lewą stronę. W przypadkach, gdy może istnieć wiele prawidłowych wyników, potrzebujesz tylko jednego z nich. Można użyć innego typu nawiasów ( <>
, []
lub {}
) jeśli sobie tego życzą.
To zawody w golfa kodowego, dlatego powinieneś dążyć do zminimalizowania rozmiaru kodu źródłowego, mierzonego w bajtach.
Przypadki testowe
(()()) -> ()(()), (())()
(()(())()) -> (()(())())
((())())() -> (()(()()))
źródło
Odpowiedzi:
Haskell ,
12412011911711311010910610510410198 bajtów4 bajty zapisane dzięki bartavelle!
3 bajty zapisane dzięki Zgarb
1 bajt zaoszczędzony dzięki Peterowi Taylorowi
Oto rozwiązanie, które wypracowałem w Haskell. W
tej chwili jest ok,całkiem niezłe dzięki pomocy, którą otrzymałem, ale chcę to skrócić, więc opinie i sugestie są mile widziane.Wypróbuj online!
Wyjaśnienie
Ten program definiuje 4 funkcje, pierwsza
(!)
określa, czy łańcuch jest zrównoważony. Jest zdefiniowany w następujący sposób:Ta kontrola zakłada, że dane wejściowe mają taką samą liczbę otwartych i zamkniętych części, dzięki sugestii Petera Taylora.
Kolejny
g
raz obróci łańcuch.Mamy więc,
d
który po prostu bierze paren i odzwierciedla goWreszcie mamy funkcję, którą się zajmujemy. Tutaj używamy bezcelowej reprezentacji
until(!0)g
złożonej zmap d
, która odwzorowujed
dane wejściowe i obowiązuje,g
dopóki wynik nie zostanie zrównoważony. Jest to dokładny proces opisany w pytaniu.źródło
g x@(a:b)|x!0=x|1>0=g$b++[a]
i usunąć pareny dlad '('=')'
.d
powoduje błąd kompilatora, uwierz mi próbowałem. Ale pierwsza sugestia jest mile widziana. Dzięki!!
, ponieważ nie trzeba obsługiwać przypadki, w których ciąg ma nierówną liczbę otwartych i zamkniętych nawiasach, więc można zamienić dwa pierwsze przypadki i mają_!1=1<0
[]!_=0<1
until
aby skrócićg
: TIOd
mapę'('
do(-1)
i nic innego1
, a następnie dwa najdłuższe przypadki!
mogą być łączone(i:a)!x=a!(x+i)
. Struktura najwyższego poziomu wymaga następnie przeróbki, aby wprowadzić jąmap d
wuntil
stan, i muszę biec, więc nie mam teraz czasu, aby dowiedzieć się, jakie kombinatory są potrzebne, aby skleić to wszystko razem.SOGL V0.12 ,
1211 bajtówWypróbuj tutaj!
Wyjaśnienie:
Uwaga:
l{
można go zastąpić ( dla 10 bajtów, ale niestety nie jest zaimplementowany.źródło
CJam (20 znaków)
Demo online
lub dla tej samej liczby znaków
Demo online
Sekcja
Dwie wersje mają wspólny nagłówek i stopkę
Następnie bit pośrodku oczywiście oblicza, jak daleko trzeba się obrócić. Obaj używają oceny i polegają na
(
tym, że są operatorem dekrementacji CJam i)
operatorem inkrementacji.vs
źródło
JavaScript (ES6),
111105 bajtów(Zapisano 2 bajty dzięki @CraigAyre, 2 bajty dzięki @PeterTaylor, 2 bajty dzięki @Shaggy.)
Nie golfowany:
Przypadki testowe:
Pokaż fragment kodu
źródło
Siatkówka ,
4638 bajtówWypróbuj online! Link zawiera przypadki testowe. Edycja: Zapisano 8 bajtów przy pomocy @MartinEnder. Pierwszy etap po prostu transponuje nawiasy, podczas gdy drugi etap szuka najdłuższego sufiksu, który jest prawidłowym zrównoważonym prefiksem, który najwyraźniej jest wystarczającym warunkiem pełnego zrównoważenia obrotu. Równoważenie jest wykrywane za pomocą grup bilansujących. Konstrukt
((\()|(?<-4>\)))+
pasuje do dowolnej liczby(
s plus dowolnej liczby)
s, o ile widzieliśmy już (<-4>
) tyle(
s. Ponieważ szukamy tylko poprawnego prefiksu, nie musimy dopasowywać pozostałych)
s.źródło
((\()|(?<-2>\)))
. Ale twoja próba właśnie zainspirowało mnie znaleźć zupełnie nowe podejście, które pozwala zaoszczędzić kolejne dwa:(?<-1>(\()*\))+
. To z pewnością przyda się w przyszłości, więc dziękuję. :)(?<-1>(\()*\))+
działa, ponieważ wydaje się, że chce wyskoczyć ze1
stosu, zanim faktycznie coś dopasuje ...\(*
.PHP,
110108 bajtówUruchom jako potok
-nR
lub przetestuj go online .awaria
źródło
Python 3 ,
112103101 bajtów-2 bajty dzięki @ Mr.Xcoder
Wypróbuj online!
źródło
Oktawa, 62 bajty
Wypróbuj online!
Funkcja, która pobiera ciąg jako dane wejściowe i drukuje wszystkie wyniki.
Wyjaśnienie:
źródło
Mathematica, 78 bajtów
źródło
JavaScript (ES6), 97 bajtów
Działa poprzez rekurencyjne obracanie łańcucha wejściowego, aż jego transpozycja zostanie zrównoważona, a następnie transpozycja.
źródło
APL (Dyalog Unicode) ,
3530 bajtówGrał w golfa nowe podejście dzięki @ Adám
Wypróbuj online!
Gra w golfa jest w toku.
Wyjaśnienie
źródło
Python 2 , 99 bajtów
Wypróbuj online!
W formie funkcji dla łatwych przypadków testowych:
Python 2 , 108 bajtów
Wypróbuj online!
Stosuje to nieco inne podejście - zamiast rekurencyjnego obracania struny, jeśli myślimy o parenach jako o zwiększaniu i zmniejszaniu pewnego licznika bilansu, wtedy zrównoważony łańcuch nigdy nie może mieć całkowitej sumy przyrostów - ubytków, które są mniejsze niż 0.
Więc bierzemy
odwróć parens:
i przekonwertować na listę sum przyrostów / spadków:
-3 to minimum przy indeksie 4 (oparte na zerach); więc chcemy przesunąć się o ten indeks + 1. Gwarantuje to, że skumulowany przyrost / spadek nigdy nie będzie mniejszy niż 0; i sumuje się do 0.
źródło
r=0,
zamiastr=[0]
?r+=[r[-1]+2*b-1]
zr+=r[-1]+2*b-1,
tak dobrzeClojure, 118 bajtów
Zwraca ciąg znaków, więc nazwałbym to tak:
Najpierw odwraca nawiasy, a następnie zapętla tak długo, jak skumulowana suma liczby nawiasów spadnie w pewnym momencie sekwencji.
źródło
pieprzenie mózgu , 82 bajty
Wypróbuj online!
Wyjaśnienie
Po każdym odczytaniu znaku licznik jest modyfikowany w następujący sposób:
)
licznik zwiększa się o 1.(
licznik zmniejsza się o 1, chyba że licznik wynosił 0, w którym to przypadku licznik pozostaje niezmieniony.Każdy prefiks jest poprawnym sufiksem zbalansowanego łańcucha (po inwersji) wtedy i tylko wtedy, gdy licznik ma wartość 0. Ten kod używa najdłuższego takiego prefiksu do utworzenia wyniku.
źródło