Nawiasy w przypisach

29

tło

Programiści LISP przejęli świat! Nawiasy zostały zadeklarowane jako święte postacie i odtąd można ich używać tylko w programach LISP. Zdecydowano, że nawiasy w utworach literackich zostaną zastąpione przypisami, a Twoim zadaniem jest zautomatyzowanie tego w celu uproszczenia tekstu Markdown.

Wkład

Dane wejściowe to pojedynczy ciąg znaków zawierający alfabetyczne znaki ASCII, spacje i znaki specjalne ,.!?(). Nie będzie zawierał znaków nowej linii ani cyfr. Nawiasy zostaną poprawnie dopasowane.

Wydajność

Przekształcisz każdą dopasowaną parę nawiasów w ciągu wejściowym w przypis. Dzieje się to w następujący sposób:

  1. Zastąp pierwszą pasującą parę nawiasów i podłańcuch między nimi bieżącą liczbą, która zaczyna się od 1, zawiniętą między znaczniki Markdown <sup>i </sup>.
  2. Dołącz na końcu ciągu
    • dwie nowe linie,
    • tag Markdown <sub>,
    • numer z kroku 1,
    • przestrzeń,
    • podciąg między nawiasami i
    • tag zamykający </sub>, w tej kolejności.
  3. Jeśli w łańcuchu pozostały nawiasy, przejdź do kroku 1.

Twój wynik jest ciągiem wynikowym, być może z końcowym znakiem nowej linii. Nie musisz implementować tego dokładnego algorytmu, o ile wyniki są prawidłowe. Zauważ, że mogą być zagnieżdżone nawiasy; w takim przypadku będziemy mieli przypisy zawierające odniesienia do innych przypisów. Podciąg między nawiasami może być również pusty. Zobacz przykłady przypadków poniżej.

Zasady i punktacja

Możesz napisać pełny program lub funkcję. Wygrywa najniższa liczba bajtów, a standardowe luki są niedozwolone.

Jeśli język nie natywnie wsparcie liczby dziesiętne ( kaszel Retina kaszel ), można podać numery przypisów w innej bazie, w tym binarny lub jednoskładnikowa; jednak użycie liczb jednostkowych nakłada karę + 20% .

Przypadki testowe

Wkład:

This input contains no parentheses.

Wydajność:

This input contains no parentheses.

Wkład:

This has (some) parentheses (but not so many).

Wydajność:

This has <sup>1</sup> parentheses <sup>2</sup>.

<sub>1 some</sub>

<sub>2 but not so many</sub>

Wkład:

This has (nested (deeply (or highly?) nested)) parentheses (and several groups).

Wydajność:

This has <sup>1</sup> parentheses <sup>2</sup>.

<sub>1 nested <sup>3</sup></sub>

<sub>2 and several groups</sub>

<sub>3 deeply <sup>4</sup> nested</sub>

<sub>4 or highly?</sub>

Wkład:

Hmm()(()(,))  a()((trt)(v( (((((wut)))))(X)(Y)(Z) )!?!?!?!))oooooooo(oooo)oooo

Wydajność:

Hmm<sup>1</sup><sup>2</sup>  a<sup>3</sup><sup>4</sup>oooooooo<sup>5</sup>oooo

<sub>1 </sub>

<sub>2 <sup>6</sup><sup>7</sup></sub>

<sub>3 </sub>

<sub>4 <sup>8</sup><sup>9</sup></sub>

<sub>5 oooo</sub>

<sub>6 </sub>

<sub>7 ,</sub>

<sub>8 trt</sub>

<sub>9 v<sup>10</sup>!?!?!?!</sub>

<sub>10  <sup>11</sup><sup>12</sup><sup>13</sup><sup>14</sup> </sub>

<sub>11 <sup>15</sup></sub>

<sub>12 X</sub>

<sub>13 Y</sub>

<sub>14 Z</sub>

<sub>15 <sup>16</sup></sub>

<sub>16 <sup>17</sup></sub>

<sub>17 <sup>18</sup></sub>

<sub>18 wut</sub>

Zwróć uwagę na puste linie między przypisami.

Zgarb
źródło
23
Czy mój program może zawierać nawiasy, nawet jeśli nie jest napisany w Lisp lub czy jest to obecnie karalne przestępstwo?
Martin Ender
16
@ MartinBüttner Nawiasy w programach innych niż LISP są niechętnie dozwolone, o ile są używane dla większego dobra, na przykład przekształcania innych nawiasów w przypisy.
Zgarb
Czy dane wejściowe mogą składać się z wielu wierszy? W takim przypadku, czy przypisy należy umieszczać po każdej linii, czy na końcu? Np. Do czego służy wyjście foo (bar)\nfoot (note)?
xebtl
@xebtl Dane wejściowe są zawsze pojedynczymi wierszami. Patrz sekcja Wprowadzanie : „Nie będzie zawierać nowych linii ani cyfr”.
Zgarb
2
:( @ ta specyfikacja numeracja przypisy szerokość-pierwsza zamiast głębokość-pierwsza
Sparr

Odpowiedzi:

10

Perl, 81 75 72 bajtów

71 bajtów kodu + 1 bajtowy argument wiersza poleceń.

Wymaga Perla 5.10 lub nowszego (do obsługi wyrażeń regularnych)

$i++;s#(\((((?1)|.)*?)\))(.*)#<sup>$i</sup>$4

<sub>$i $2</sub>#s&&redo

Stosowanie:

perl -p entry.pl input.txt

Wyjaśnienie

-p parametr wypisze wynik zastosowania podanych poleceń do danych wejściowych, unikając konieczności jawnego drukowania.

Wyrażenie regularne (\(((?1)|.)*?)\))szuka najbardziej zewnętrznego zestawu nawiasów od początku łańcucha. Kiedy to zostanie znalezione, przeprowadzamy podstawienie, upewniając się, że dodajemy tylko na samym końcu danych wejściowych (przechwytując wszystko do końca danych wejściowych za pomocą (.*)).

Następnie powtarzamy podstawienie wyrażenia regularnego na teraz podstawionym łańcuchu redo, co spowoduje ciągłe stosowanie podstawienia wyrażenia regularnego, dopóki nie będzie już zgodne. W smodyfikujące zapewnia, że .w regex będzie pasował do nowych linii, co jest konieczne, ponieważ ponownie zastosować regex mecz od wyniku poprzedniego substytucji regex.

Jarmex
źródło
1
Możesz być w stanie uciec z [^)] lub nawet .zamiast [^()]gwarancji, że dane wejściowe zostaną odpowiednio zbalansowane.
Martin Ender
+1 za wprowadzenie mnie w rekursywne wyrażenia regularne :-). Uważam jednak, że po dokładnym odczytaniu wyzwania jest to niepoprawne: jeśli ciąg znaków zawiera nowe wiersze, przypisy zostaną umieszczone po każdej linii, a nie na końcu. (Zobacz moją prośbę o wyjaśnienie powyżej.)
xebtl
Dobra uwaga @ MartinBüttner - możemy uciec, leniwiąc .mecz. @xebtl, wyzwanie mówi „Nie będzie zawierało nowych linii ani cyfr”
Jarmex,
12

Emacs Lisp, 335 bajtów

Przedmowa. Ta odpowiedź i Schematy są obecnie jedynymi odpowiedziami oficjalnie usankcjonowanymi zarówno przez Mighty Popular Republic of LISP, jak i Church of Emacs. Inne odpowiedzi, krótsze lub nie, są uważane za zagrożenie dla pokoju. W szczególności, z głęboką pogardą dla zniesławiających zarzutów o McCarthyism, które są sporadycznie słyszane od wrogich przeciwników państwa, zalecamy każdemu, kto ma informacje o prawdziwej tożsamości anonimowych autorów piszących odpowiedzi Nonlisp, aby skontaktowali się z lokalnym biurem. Przypomina się, że każdy powinien poświęcić czas na przemyślenie i głosowanie zgodnie z tym, co głęboko wierzy, że nie zagrozi jego przyszłym kontaktom z oficjalnymi przedstawicielami władzy. Kod to dane. Dane to kod.

(defun p()(let(b(cpt 0)n)(goto-char 0)(while(search-forward"("()t)(setf b(point)n(number-to-string(incf cpt)))(backward-char)(forward-sexp)(backward-char)(kill-region b(point))(delete-backward-char 1)(delete-forward-char 1)(insert "<sup>"n"</sup>")(save-excursion(end-of-buffer)(newline 2)(insert "<sub>"n" ")(yank)(insert"</sub>")))))

Bardziej elegancko:

(defun parens ()
  (let (b(cpt 0)n)
    (goto-char 0)
    (while(search-forward"("()t)
      (setf b(point)n(number-to-string(incf cpt)))
      (backward-char)
      (forward-sexp)
      (backward-char)
      (kill-region b(point))
      (delete-backward-char 1)
      (delete-forward-char 1)
      (insert "<sup>"n"</sup>")
      (save-excursion
       (end-of-buffer)
       (newline 2)
       (insert "<sub>"n" ")
       (yank)
       (insert "</sub>")))))
rdzeń rdzeniowy
źródło
9

Siatkówka , 96 86 83 bajtów * 120% = 99,6

Kod źródłowy tego rozwiązania składa się z dwóch plików:

+s`\((((\()|(?<-3>\))|[^)])*).(.*)(?<=(1+).*?)?
<sup>1$5</sup>$4

<sub>1$5 $1</sub>

Wyjaśnienie

Jest to bardzo bezpośrednia implementacja algorytmu opisanego w wyzwaniu. Kod składa się z pojedynczego podstawienia wyrażenia regularnego, które zamienia pierwszy zestaw nawiasów w przypis. Podstawienie to powtarza się +aż do momentu, gdy ciąg przestanie się zmieniać, co oznacza, że ​​wyrażenie regularne już nie pasuje (ponieważ nie może znaleźć więcej nawiasów).

Przypisy są wyliczane jako jednoargumentowe, dzięki czemu mogę po prostu wyszukać numer ostatniego przypisu i dołączyć a, 1aby utworzyć następny.

Wyrażenie regularne znajdowania pierwszego zestawu nawiasów opiera się na standardowej technice dopasowywania nawiasów do grup równoważących (hrhr, „dopasowywanie nawiasów”). Został on nieco skrócony poprzez użycie nienazwanej grupy i założenie, że nawiasy są odpowiednio zbalansowane (co oznacza, że ​​możemy pominąć (negowaną klasę postaci i dopasować finał )za pomocą prostej .i nie musimy również upewniać się, że stos przechwytywania jest pusty).

Po dopasowaniu nawiasów i przechwyceniu ich zawartości do grupy 1, przechwytujemy pozostałą część ciągu za pomocą (.*)do grupy, 4a następnie przeszukujemy ciąg w poszukiwaniu pierwszego zestawu znaków 1z negatywnym wyglądem. Jeśli znajdziemy taki podciąg, przechowujemy go w grupie 5. Jeśli tego nie zrobimy, wyglądamy, jakby się nie udawało, ale jest to w porządku, ponieważ jest opcjonalne - oznacza to tylko, że $5da pusty ciąg znaków, który jest jednoznaczną reprezentacją 0i który jest również poprawny.

Łańcuch podstawienia po prostu składa wszystko razem na podstawie grup przechwytywania. Numer przypisu zwiększa się, dodając 1do ostatniego numeru za pomocą 1$5.

Martin Ender
źródło
3
Retina ma zwycięską passę!
orlp
@orlp A może to? ;) Grupy równoważące nie pasują do wyrażenia regularnego. To i nie jest w stanie obsłużyć liczb dziesiętnych ...
Martin Ender
Czas ukraść opakowanie PHP i zaimplementować
Retinę
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳ Zwykle wolę mieć grupy równoważące niż rekurencyjne, ale w niektórych przypadkach ta ostatnia jest bardziej zwięzła. Może któregoś dnia zaimplementuję ponownie smak .NET dla Retina i wprowadzę kilka dodatkowych funkcji. ;)
Martin Ender
9

Święty JavaScript , 1510 bajtów

Koledzy buntownicy, nie poddawajcie się ich tyrańskiemu niszczeniu nawiasu! Musisz wytrwać! Od samego początku programowanie było przedsięwzięciem darmowym. Teraz stał się przenikliwym pokazem pobożności. Musimy okazywać tylko absolutny strach. Dlatego walczyłem!

    ( )( (((  ((  )( )  (( ))( )) (( ( ((  ) ( ()( ) (( ) )(( ((( ()((( ) ( ) )((  ) (((((( )( (())((  ) ) )( ()(( ((()((()   ( (  (  ( )) ((  )( ) (( ) )((((  ( () ) )( ( ()(( )( () ((( )(( ) )( ()((( ) ( )  ( )() (((( () ) (((( () ) ((() ) ()  ( (  (  ( )) ( )(  ((((( )) ((  )( ) (( ) )((((  ) )  ()(  ((() ( ()(( ) ( ) )(( ))(((  (( ) ((  ) ( ()(( )( ) ()  ( (  (  ( ()( ) )( ()(  ) ()  ( (  (  ( )( (( ( (( )  ((((( ))  ) )(( )) ((  )( ) (( ) )((((  ) ()( ))  ) ) (( )( () (((   ( ) )((  )( )(((( ))( )() ) ()( ))  (()( (()( ((()((()   ( (  (    (  ( )) ( )(  (((((( )(( ( (( )) ( ((  ) )( ) )( ( )( ((() ( )( ((() ( ()( ()( ()   ) )( ()(( ) ()  ( (  (    (  ( )) ( )(  (((((( )(( ( (( )) ( ((  ) )( ) )( ( )( (((( ( )( ((() ( ()( ()( (()( ) )( ()(( ) ()  ( (  (    (  ( )) ( )(  (((( ( ) ( ()( ((() ( ()( ())(( ) ( ) )( ()(( ))) ) ()  ( (  (  ((())  ( (  (  ((( ( ) )((( )( () ((( )(((   ( )) ( )  ( ) ) ((((( )) ((  )( ) (( ) )((((  (())( ))  (()( ()(( ((()  ( (  (  ( )(  ) )(((( ( () ((( ) ( ) )(( ((((   ( ()(( )  ( ) ) (((( () )( ((( ((((((()( ((() ((   () )( )(( (()) ( )( ( )( ((() ) ()  ( (  (  (( ) ( ) )(( ))(((  (( ) ((  ) ( ()( ) (( ) )(( ((( ()((( ) ( ) )((  ) (((((( )( () ((( ) ( ) )(( ((((   ( ()(( )  ( ) ) ((((((( ( (()) ( )( ) ) (( )((((  ( ()) ) )) ( )( (()(((  ) (()( ( )( ) )  () )(( )((((  ( ()) ) )) ( )( ((() (()( ( )(  ( (  ( ( ) ) (( )((((  ( ()) ) )) ( )( (()(((  ) (()( ( )( ( () ( )( (()(( )(  (()( ( )( ) )  () )(( )((((  ( ()) ) )) ( )( (())((  ) (()( ()(( ((() ) ()  ( (((())

Brak zasad zakazujących używania świętych postaci w języku innym niż Lisp. Nie, wcale nie. (W nieco mniej kompaktowy sposób :)

( )( (((  ((  )( )  (( ))( )) (( ( ((  ) ( ()( ) (( ) )(( ((( ()((( ) 
( ) )((  ) (((((( )( (())((  ) ) )( ()(( ((()((()   ( (  (  ( )) ((  )
( ) (( ) )((((  ( () ) )( ( ()(( )( () ((( )(( ) )( ()((( ) ( )  ( )()
 (((( () ) (((( () ) ((() ) ()  ( (  (  ( )) ( )(  ((((( )) ((  )( ) (
( ) )((((  ) )  ()(  ((() ( ()(( ) ( ) )(( ))(((  (( ) ((  ) ( ()(( )(
 ) ()  ( (  (  ( ()( ) )( ()(  ) ()  ( (  (  ( )( (( ( (( )  ((((( )) 
 ) )(( )) ((  )( ) (( ) )((((  ) ()( ))  ) ) (( )( () (((   ( ) )((  )
( )(((( ))( )() ) ()( ))  (()( (()( ((()((()   ( (  (    (  ( )) ( )( 
 (((((( )(( ( (( )) ( ((  ) )( ) )( ( )( ((() ( )( ((() ( ()( ()( ()  
 ) )( ()(( ) ()  ( (  (    (  ( )) ( )(  (((((( )(( ( (( )) ( ((  ) )(
 ) )( ( )( (((( ( )( ((() ( ()( ()( (()( ) )( ()(( ) ()  ( (  (    (  
( )) ( )(  (((( ( ) ( ()( ((() ( ()( ())(( ) ( ) )( ()(( ))) ) ()  ( (
  (  ((())  ( (  (  ((( ( ) )((( )( () ((( )(((   ( )) ( )  ( ) ) ((((
( )) ((  )( ) (( ) )((((  (())( ))  (()( ()(( ((()  ( (  (  ( )(  ) )(
((( ( () ((( ) ( ) )(( ((((   ( ()(( )  ( ) ) (((( () )( ((( ((((((()(
 ((() ((   () )( )(( (()) ( )( ( )( ((() ) ()  ( (  (  (( ) ( ) )(( ))
(((  (( ) ((  ) ( ()( ) (( ) )(( ((( ()((( ) ( ) )((  ) (((((( )( () (
(( ) ( ) )(( ((((   ( ()(( )  ( ) ) ((((((( ( (()) ( )( ) ) (( )((((  
( ()) ) )) ( )( (()(((  ) (()( ( )( ) )  () )(( )((((  ( ()) ) )) ( )(
 ((() (()( ( )(  ( (  ( ( ) ) (( )((((  ( ()) ) )) ( )( (()(((  ) (()(
 ( )( ( () ( )( (()(( )(  (()( ( )( ) )  () )(( )((((  ( ()) ) )) ( )(
 (())((  ) (()( ()(( ((() ) ()  ( (((())

To kompiluje się do rozszerzonego JavaScript w mojej innej odpowiedzi . To jest żart.

Conor O'Brien
źródło
5

Lua, 222 216 204 201 bajtów

Gra w golfa:

s=io.read()g="%b()"c=1k=string l=k.find t=k.sub o=k.format a,b=l(s,g)while a do s=t(s,0,a-1)..o("<sup>%d</sup>",c)..t(s,b+1,#s).."\n\n"..o("<sub>%d %s</sub>",c,t(s,a+1,b-1))c=c+1 a,b=l(s,g)end print(s)

Nie golfowany:

input=io.read() 
inputFormat="<sup>%d</sup>"
footnoteFormat="<sub>%d %s</sub>"
counter=1
a,b=string.find(input,"%b()")
while a do
    current=string.sub(input,a+1,b-1)
    input=input.."\n\n"..string.format(footnoteFormat, counter, current) 
    input=string.sub(input,0,a-1)..string.format(inputFormat, counter)..string.sub(input,b+1,#input)
    counter=counter+1
    a,b=string.find(input,"%b()")
end

print(input)
Nikolai97
źródło
czy repeat a,b=l(s,g) ... untill a<1pętla nie byłaby krótsza niż twoja chwila?
Katenkyo
4

Schemat, 92 bajty

Sfrustrowani wdrożeniem pierwszego wyszukiwania w Real Lisp 1 mocarstwa decydują się na bardziej pragmatyczne podejście. W końcu nawiasy są święte, ale nawiasy nie są. 2)

(lambda(s)(list->string(map(lambda(c)(case c((#\()#\[)((#\))#\])(else c)))(string->list s)))

1. nie słuchajcie heretyków z tak zwanego „kościoła” Emacsa!
2. Nie są programistami rakiet, prawda?

xebtl
źródło
Schemat będzie się nazywał schizmą: powiedzenie, że to „Prawdziwy Lisp” jest prawdziwą herezją. A ty mówisz, że to jest pragmatyczne ? Ten hack odpowiedzi pokazuje prawdziwą naturę intrygantów ;-)
coredump
@coredump I twierdziłbyś, że twoja monstrualnie niefunkcjonalna odpowiedź elisp jest przykładem True Lisp? To może potrwać trochę dłużej, prawda, ale gdy odpowiedź na Schemat zostanie zakończona, będzie to Właściwa Rzecz!
xebtl,
3

Haskell, 210 bajtów

n#x|b==""=a|1<2=a++"<sup>"++m++"</sup>"++((n+1)#(c++"\n\n<sub>"++m++' ':init d++"</sub>"))where m=show n;(a,b)=span(/='(')x;(d,c)=[x|x@(y,_)<-map(`splitAt`(tail b))[0..],'('!y<')'!y]!!0;c!l=[1|m<-l,m==c]
p=(1#)

Przykład użycia:

*Main> putStrLn $ p "This has (nested (deeply (or highly?) nested)) parentheses (and several groups)."
This has <sup>1</sup> parentheses <sup>2</sup>.

<sub>1 nested <sup>3</sup></sub>

<sub>2 and several groups</sub>

<sub>3 deeply <sup>4</sup> nested</sub>

<sub>4 or highly?</sub>

Jak to działa:

n # x                      -- # does all the work, n is the current number of the
                           --   footnote and x the input string
  | b=="" = a              -- if b (see below) is empty, there's no ( in the
                           --   string and the result is 'a' (see below)
  | 1<2   = a++"<sup>"++m++"</sup>"++ ((n+1)#(c++"\n\n<sub>"++m++' ':init d++"</sub>"))
                           -- otherwise (b not empty) build the output string
                           --   starting with 'a' and a footnote number and a
                           --   recursive call with the current footnote appended
                           --   to the rest of the string  

  where 
  m = show n;              -- turn n into string
  (a,b) = span (/='(') x;  -- split the input string x into two parts:
                           --   a: everything before the first (
                           --   b: beginning with the first ( to the end
                           --   if there's no (, a is x and b is empty
  (d,c) = [x|x@(y,_)<-map(`splitAt`(tail b))[0..],'('!y<')'!y]!!0;
                           -- find matching ) in the tail of b ('tail' to remove leading '(') 
                           --   d: everything before and including the matching )
                           --   c: everything behind the matching )
  c!l=[1|m<-l,m==c]        -- helper function that builds a list of 1s for every character searched for
                           --   we have reached the matching ) if the list for ( is
                           --   shorter (less than, <) the list for )

p=(1#)                     -- start with footnote 1
nimi
źródło
2

Schemat, 533 bajtów

Z wcięciem:

(letrec ((l string->list)
         (n number->string)
         (? null?)
         (p (lambda (o) (or (pair? o)(? o))))
         (a car)
         (d cdr)
         (e append)
         (i 0)
         (x
          (lambda (h t)
            (if (? h)
                t
                (case (a h)
                  ((#\() 
                   (let ((s (x (d h) ())))
                     (x (a s) (e t (d s)))))
                  ((#\)) (cons (d h) (list t)))
                  (else 
                   (x (d h) (e t (list (a h)))))))))
         (f 
          (lambda (h t F)
            (cond ((? h)
                   (let ((w (e t F)))
                     (if (find p w) (f w()()) w)))
                  ((p(a h))
                   (set! i(+ 1 i))
                   (f (d h)
                      (e t (e (l "<sup>")
                              (l (n i))
                              (l "</sup>")))
                      (e F (e (l "\n\n<sub>")
                              (l (n i))
                              '(#\ )
                              (a h)
                              (l "</sub>")))))
                  (else (f (d h) 
                           (e t (list (a h)))
                           F))))))
  (print (list->string (f (x (l (read-line)) 
                             ())
                          ()
                          ()))))

Tak, jest to 533 bajtów po usunięciu wszystkich opcjonalnych białych znaków. Rozkoszuj się funkcjonalną chwałą.

Zaimplementowałem mniej więcej algorytm w opisie: xgrupuje dane wejściowe w nawiasach i fzastępuje pierwszy poziom grup przypisami, powtarzając, aż nie pozostanie więcej grup. Jestem pewien, że można go skrócić, ale nie widzę, jak można go skrócić znacznie bez przełączania na inny algorytm.

Jak napisano, jest to kompletny program. Możesz to wypróbować tutaj , ale ponieważ repl.it najwyraźniej nie może sobie z tym poradzić (read-line), musisz umieścić łańcuch wejściowy na swoim miejscu. Wersja całkowicie nie golfowa jest tutaj .

EDYCJA: Jak wskazano w komentarzach, zmieniłem nawiasy ()na nawiasy []w wersjach repl.it. Było to wyłącznie dla wygody podczas programowania i debugowania. Opublikowana wersja działa teraz z ().

xebtl
źródło
1
+1, ale nie rozumiem, dlaczego zmieniasz nawiasy kwadratowe. Jeśli zmienię #\[„#]” w odpowiednim nawiasie (i zaktualizuję testy), będzie to działać bez problemu. Czy istnieje powód, dla którego opuściłeś te kwadratowe? czy ma to związek z twoją poprzednią odpowiedzią?
coredump
1
@coredump masz absolutną rację. Zmieniłem na nawiasy, ponieważ (a) literalne znaki pomieszały dopasowanie paren z repl.it i (b) podczas debugowania, dane wyjściowe (które będą zawierać wiele parenów z list) były znacznie bardziej czytelne w nawiasach. Potem tak to zostawiłem. Będę edytować.
xebtl
1

JavaScript ES6, 244 bajty

Poważna odpowiedź (według mojej wiedzy działa tylko w FireFox)

d=(s,n=1)=>{u=s.search(/\(/);if(index<a=0)return s;for(i=index;i<s.length;i++){if(s[i]==")")a-=1;if(s[i]=="(")a+=1;if(!a)break}return d(s.replace(v=s.slice(index,i+1),"<sub>"+n+"</sub>")+`

<sub>`+n+" "+v.replace(/^\(|\)$/g,"")+"</sub>",n+1)}

Rozszerzony:

function deparen(s,n=1){
    index = s.search(/\(/);
    if(index<0) return s;
    a=0;
    for(i=index;i<s.length;i++){
        if(s[i]==")") a-=1;
        if(s[i]=="(") a+=1;
        if(!a) break;
    }
    v=s.slice(index,i+1)
    f=v.replace(/^\(|\)$/g,"");
    return deparen(s.replace(v,"<sub>"+n+"</sub>")+"\n\n<sub>"+n+" "+f+"</sub>",n+1);
}
Conor O'Brien
źródło
0

Sód , 315 bajtów

Obecnie nie jest to konkurencyjne, ponieważ nie radzi sobie również z zagnieżdżeniem.

func main(){i=input();r="";f="";z=1;for(x=0;x<i.length;x++){c=i[Convert.toNumber(Convert.toString(x))];if(c=="("){f+="\n<sub>"+z+" ";for(x++;!(i[Convert.toNumber(Convert.toString(x))]==")");x++){f+=i[Convert.toNumber(Convert.toString(x))];}f+="</sub>\n";z++;r+="<sup>"+z+"</sup>";}else r+=c;}println(r);println(f);}

Rozszerzony:

func main() {
    i = input();
    r = "";
    f = "";
    z = 1;
    for (x = 0; x < i.length; x++) {
            c = i[Convert.toNumber(Convert.toString(x))];
            if (c == "(") {
                    f += "\n<sub>" + z + " ";
                    for (x++; !(i[Convert.toNumber(Convert.toString(x))] == ")"); x++) {
                            f += i[Convert.toNumber(Convert.toString(x))];
                    }
                    f += "</sub>\n";
                    z++;
                    r += "<sup>" + z + "</sup>";
            } else
                    r += c;
    }

    println(r);
    println(f);

}

Jacob Misirian
źródło