tło
(Na podstawie prawdziwej, budzącej grozę historii)
W swoim czasie często bawiłem się Lispem i podobnymi językami. Pisałem z nimi, prowadziłem je, interpretowałem, projektowałem i zmuszałem maszyny, aby pisały z nimi dla mnie ... A jeśli coś mnie niepokoi, to widzi Lisp, który nie jest zgodny z moim specyficznym stylem formatowania.
Niestety, niektóre edytory tekstowe ( kaszel XCode kaszel ) wydają się rozebrać moje piękne karty i spacji, gdy kod jest skopiowany i wklejony ... Weź to pięknie rozmieszczone Lisp podobną składnię:
(A
(B
(C)
(D))
(E))
(Gdzie ABCDE
są arbitralne funkcje)
NIEKTÓRE edytory tekstu rzeźą ten piękny kod w następujący sposób:
(A
(B
(C)
(D))
(E))
Co za bałagan! To nieczytelne!
Pomóż mi tutaj?
Wyzwanie
Twoim celem w tym wyzwaniu jest przejęcie szeregu funkcji oddzielonych znakami nowej linii w formacie opisanym poniżej i zwrócenie piękniejszej aranżacji podkreślającej czytelność i elegancję.
Wejście
Definiujemy funkcję argumentów F
arity N
jako konstrukcję podobną do następującej:
(F (G1 ...) (G2 ...) (G3 ...) ... (GN ...))
gdzie G1, G2, ..., GN
wszystkie funkcje są same w sobie. Arity 0
funkcja A
jest po prostu (A)
, natomiast arity 2
funkcja B
jest postaci(B (...) (...))
Twój kod powinien przyjmować dane wejściowe jako serię funkcji z pojedynczym znakiem nowej linii przed nawiasiem wiodącym każdej funkcji (z wyjątkiem pierwszej funkcji). Powyższy przykład jest prawidłowym wejściem.
Możesz założyć:
- Nawiasy są zrównoważone.
- Funkcja nigdy nie będzie musiała być wcięta więcej niż 250 razy.
- KAŻDA funkcja jest otoczona nawiasami:
()
- Nazwa funkcji będzie zawierać tylko drukowalne znaki ASCII.
- Nazwa funkcji nigdy nie będzie zawierać nawiasów ani spacji.
- Istnieje opcjonalny końcowy znak nowej linii na wejściu.
Wyjście
Twój kod powinien wypisywać ten sam zestaw funkcji, a jedynymi wprowadzonymi zmianami są dodawanie spacji lub tabulatorów przed nawiasami wiodącymi funkcji. Dane wyjściowe powinny być zgodne z następującymi zasadami:
- Pierwsza podana funkcja (a później funkcje najwyższego poziomu) nie powinna zawierać poprzedzających spacji
- Argumentem do poziomego położenia funkcji jest dokładnie jedna zakładka po prawej stronie poziomego położenia tej funkcji.
- Zakładka jest zdefiniowana w implementacji, ale musi mieć co najmniej 3 spacje.
- Opcjonalnie możesz wydrukować maksymalnie dwie spacje po każdej linii.
Zasady
- Oto kod-golf: wygrywa najkrótszy kod!
- Standardowe luki są niedozwolone.
Przykłady
Wkład:
(A
(B
(C)
(D))
(E))
Wydajność:
(A
(B
(C)
(D))
(E))
Wkład:
(!@#$%^&*
(asdfghjklm
(this_string_is_particularly_long
(...))
(123456789)))
(THIS_IS_TOP_LEVEL_AGAIN
(HERE'S_AN_ARGUMENT))
Wydajność:
(!@#$%^&*
(asdfghjklm
(this_string_is_particularly_long
(...))
(123456789)))
(THIS_IS_TOP_LEVEL_AGAIN
(HERE'S_AN_ARGUMENT))
Wkład:
(-:0
(*:0
(%:0
(Arg:6)
(Write:0
(Read:0
(Arg:30))
(Write:0
(Const:-6)
(Arg:10))))
(%:0
(Const:9)
(/:0
(Const:-13)
(%:0
(Arg:14)
(Arg:0)))))
(WriteArg:22
(-:0
(Const:45)
(?:0
(Arg:3)
(Arg:22)
(Arg:0)))))
Wydajność:
(-:0
(*:0
(%:0
(Arg:6)
(Write:0
(Read:0
(Arg:30))
(Write:0
(Const:-6)
(Arg:10))))
(%:0
(Const:9)
(/:0
(Const:-13)
(%:0
(Arg:14)
(Arg:0)))))
(WriteArg:22
(-:0
(Const:45)
(?:0
(Arg:3)
(Arg:22)
(Arg:0)))))
źródło
()
?Odpowiedzi:
Pyth,
24201918 bajtówZwiększa licznik dla każdej linii, zlicza całkowitą liczbę napotkanych do tej pory nawiasów zamykających i odejmuje ją od licznika. Następnie wciskamy
counter
tabulatory.źródło
*4
jest to sztywno określona i zbędna preferencja.FN.z+*ZC9N~Z-1/N\)
pozwala użyć szerokości wcięcia edytora i oszczędza jeden bajt.\<tab>
lubC9
.Common Lisp -
486414 bajtów (wersja Rube Goldberg)Podejście
Zamiast robić jak wszyscy inni i liczyć nawiasy ręcznie, przywołajmy czytnik Lisp i zróbmy to we właściwy sposób :-)
(
,)
lub odstępu jako ciągi.read
aby zbudować rzeczywiste listy.p
każdą z tych list, które rekurencyjnie zapisują je na standardowe wyjście w żądanym formacie. W szczególności ciągi są drukowane bez cudzysłowu.W wyniku tego podejścia:
Przykład
Odczytywanie z pliku przy użyciu tego opakowania:
Oto wynik:
(wygląda na to, że tabulatory są tutaj zamieniane na spacje)
Całkiem drukowane (wersja golfowa)
W przeciwieństwie do bezpieczniejszej wersji oryginalnej oczekujemy, że dane wejściowe będą prawidłowe.
źródło
Retina ,
8983 bajtówGdzie
<tab>
oznacza rzeczywisty znak tabulacji (0x09) i<empty>
oznacza pusty wiersz. Po dokonaniu tych zamian możesz uruchomić powyższy kod za pomocą-s
flagą. Jednak nie liczę tej flagi, ponieważ można również po prostu umieścić każdą linię we własnym pliku źródłowym, w którym to przypadku 7 nowych linii zostanie zastąpionych 7 bajtami kary za dodatkowe pliki źródłowe.Jest to pełny program, który pobiera dane wejściowe do STDIN i wypisuje wynik do STDOUT.
Wyjaśnienie
Każda para linii definiuje podstawienie wyrażenia regularnego. Podstawową ideą jest wykorzystanie grup równoważących .NET do policzenia bieżącej głębokości do określonej
(
, a następnie wstawienie tylu zakładek(
.Najpierw przygotowujemy dane wejściowe. Naprawdę nie możemy zapisać warunkowej liczby zakładek, jeśli nie możemy ich znaleźć gdzieś w ciągu wejściowym, aby je przechwycić. Zaczniemy więc od skopiowania całego wejścia, oddzielonego tabulatorem. Zauważ, że
s`
just aktywuje modyfikator jednowierszowy (lub „kropka-wszystko”), który zapewnia, że.
również pasuje do nowych linii.Teraz zamieniamy każdą postać po tej zakładce w zakładkę. To daje nam wystarczającą liczbę zakładek na końcu łańcucha, bez modyfikacji dotychczasowego łańcucha.
To jest mięso rozwiązania.
m
Is
włączyć tryb multi-wiersza (tak, że^
pasuje początki wierszy) i tryb pojedynczej linii. The+
Mówi Retina aby powtarzać to podstawienie aż wyjście przestaje zmianę (w tym przypadku, to znaczy dopóki wzorzec nie pasuje ciąg).Sam wzorzec dopasowuje prefiks wejścia do nieprzetworzonego
(
(to znaczy,(
że nie ma przed nim żadnych kart, ale powinien). Jednocześnie określa głębokość prefiksu z grupami równoważącymi, tak że wysokość stosu2
będzie odpowiadać bieżącej głębokości, a zatem liczbie zakładek, które musimy dołączyć. To jest ta część:Albo dopasowuje a
(
, pchając go na2
stos, albo dopasowuje a)
, wyskakując z ostatniego przechwytywania z2
stosu, lub dopasowuje coś innego i pozostawia stos nietknięty. Ponieważ nawiasy mają gwarancję zrównoważenia, nie musimy się martwić próbą wyskoczenia z pustego stosu.Po przejściu przez taki ciąg znaków i znalezieniu nieprzetworzonego
(
do zatrzymania się, lookahead przeskakuje do przodu do końca ciągu i przechwytuje tabulatory w grupie3
, wyskakując ze2
stosu, aż będzie pusty:Używając
+
tam, zapewniamy, że wzorzec pasuje tylko do czegokolwiek, jeśli do dopasowania należy wstawić co najmniej jedną zakładkę - pozwala to uniknąć nieskończonej pętli, gdy istnieje wiele funkcji na poziomie administratora.Wreszcie, po prostu pozbywamy się tych zakładek pomocniczych na końcu łańcucha, aby oczyścić wynik.
źródło
C:
9594 znakówNie jest jeszcze bardzo golfowy, a z pytania nie jestem pewien, czy zakładki są dopuszczalne, i to tutaj używam.
Nie golfowany:
Edycja: Sprawiło, że wychodzi z EOF.
źródło
if(c<11)
zamiastif(c==10)
?Julia,
10399979488 bajtówDefiniuje nienazwaną funkcję, która akceptuje ciąg i drukuje wciętą wersję. Aby to nazwać, nadaj mu nazwę, np
f=p->...
. Zauważ, że wejście musi być poprawnym ciągiem Julii, więc znaki dolara ($
) muszą być poprzedzone znakiem ucieczki.Niegolfowane + wyjaśnienie:
Przykładem udawania każdego zestawu czterech spacji jest tabulator:
Wszelkie sugestie są mile widziane!
źródło
Haskell,
8381bardzo darmowe rozwiązanie.
źródło
h=
.Perl, 41
40
znaki+1
dla-p
.Biegnij z:
źródło
Python 2 -
8878 bajtówDość proste (i niezbyt krótkie) rozwiązanie:
źródło
'\t'
zamiast' '
i zapisać jeden bajt; 2) nie trzeba przypisywaćinput.split()
zmiennej, ponieważ jest ona używana tylko raz (to samo dlac
, jak i -d
wystarczy przenieśćprint
instrukcję); 3) pierwszeństwo operatora oznacza, że nawiasy wokółl*c
nie są potrzebne. Wygląda też na to, żef
do niczego nie służy - czy to relikt poprzedniej wersji?raw_input
zamiast niegoinput
(i nie zapomnij po nim nawiasów!).CJam, 20 bajtów
Wypróbuj online w interpretatorze CJam .
Jak to działa
źródło