Erweitern Sie komprimierte Hirnschuppen

26

Diese Challenge wurde im Rahmen der LotM-Challenge im April 2018 sowie zum 2. Geburtstag von Brain-Flak veröffentlicht


Ich dachte darüber nach, wie man Brain-Flak-Programme am effizientesten codieren könnte. Da es nur 8 gültige Zeichen gibt, ist es naheliegend, jedes Zeichen einer 3-Bit-Sequenz zuzuordnen. Dies ist sicherlich sehr effektiv, aber es ist immer noch sehr redundant. Es gibt einige Funktionen von Brain-Flak-Code, die wir nutzen könnten, um die Codierung zu verkürzen.

  • Die Nullen, die alle durch 2 übereinstimmende Klammern dargestellt werden, fungieren tatsächlich als einzelne Informationseinheit anstatt als 2. Wenn wir jede Klammer durch ein einzelnes Byte-Zeichen ersetzen, würden die Codierungen viel kleiner, ohne dass Daten verloren gehen.

  • Dieser ist weniger offensichtlich, aber die abschließenden Bytes der Monaden sind auch redundant. Denken Sie, Sie könnten erraten, was die '?'Zeichen im folgenden Ausschnitt darstellen?

     {(({}?<>?<>?
    

    Wenn wir davon ausgehen, dass die Eingabe ein gültiger Brain-Flak-Code ist, gibt es für jedes dieser Fragezeichen nur eine Option. Dies bedeutet, dass wir eindeutig ein enges Monadenzeichen verwenden können, um jede schließende Klammer darzustellen. Dies hat den zusätzlichen Vorteil, dass der Zeichensatz klein gehalten wird, was sehr hilfreich wäre, wenn wir eine Huffman-Codierung verwenden möchten. Da das enge Monadenzeichen mit großer Wahrscheinlichkeit das am häufigsten vorkommende Zeichen ist, könnte es durch ein einzelnes Bit dargestellt werden, was äußerst effizient ist.

Mit diesen beiden Tricks können wir Brain-Flak-Code mithilfe des folgenden Algorithmus komprimieren:

  1. Ersetzen Sie jede schließende Klammer einer Monade durch |. Oder mit anderen Worten, ersetzen Sie jede schließende Klammer, der kein Eröffnungsspiel vorausgeht, durch einen Balken. So...

    (({})<(()()())>{})
    

    würde werden

    (({}|<(()()()||{}|
    
  2. Ersetzen Sie jeden Nilad mit seiner schließenden Klammer. Daher verwenden übereinstimmende Klammern, in denen sich nichts befindet, die folgende Zuordnung:

    () --> )
    {} --> }
    [] --> ]
    <> --> >
    

    Jetzt lautet unser letztes Beispiel:

    ((}|<()))||}|
    
  3. Entfernen Sie nachfolgende |Zeichen. Da wir wissen, dass die Gesamtzahl der Balken der Gesamtzahl der ({[<Zeichen entsprechen sollte, können wir auf fehlende Balken am Ende schließen. Also ein Beispiel wie:

    ({({})({}[()])})
    

    würde werden

    ({(}|(}[)
    

Ihre Herausforderung für heute ist es, diesen Prozess umzukehren.

(){}[]<>|Erweitern Sie eine Zeichenfolge aus komprimiertem Brain-Flak, die nur die Zeichen enthält , in den ursprünglichen Brain-Flak-Code. Sie können davon ausgehen, dass die Eingabe immer zu gültigem Brain-Flak erweitert wird. Dies bedeutet, dass kein Präfix der Eingabe mehr |als ({[<Zeichen enthält.

Die Eingabe enthält keine nachgestellten |Zeichen. Diese müssen aus dem Kontext abgeleitet werden.

Wie üblich können Sie entweder ein vollständiges Programm oder eine Funktion einreichen, und Eingabe- / Ausgabeformate sind zulässig. Und da dies ein , wird Ihr Code durch die Länge des Quellcodes in Bytes bewertet. Je kleiner die Punktzahl, desto besser.

Testfälle

Hier sind einige Testfälle. Wenn Sie mehr möchten, können Sie mit diesem Python-Skript und dem Brain-Flak-Wiki , aus dem die meisten dieser Testfälle stammen , Ihre eigenen Testfälle generieren .

#Compressed code
#Original code

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


([([}()||||(>||{(})|>|}{((<}|||>}|}>}
([([{}(())])](<>)){({}())<>}{}{((<{}>))<>{}}{}<>{}

({(}|(}[)|||}
({({})({}[()])}{})


(((()))||(](((}}||(}([(((}))||||(]((}}|}|}}|||]||]|[))||(}))|}(}|(}]]|}
((((()()()))([]((({}{}))({}([((({}()())))]([](({}{}){}){}{})))[]))[])[()()])({}()()){}({})({}[][]){}
DJMcMayhem
quelle
4
Genius. absolut genial. Sie sollten eine abgeleitete Sprache erstellen.
NH.
8
@NH. Persönlich finde ich Sprachen, die sich nur in der Kodierung unterscheiden, wirklich langweilig.
DJMcMayhem
1
@dj aber dieser würde weniger Bytes belegen und wäre daher besser zum Golfen.
NH.
5
Brain-Flak war nicht dafür gedacht, gut Golf zu spielen.
DJMcMayhem

Antworten:

32

Brain-Flak , 952 916 818 Bytes

{(({})[(((()()()()()){}){}){}])((){[()](<{}>)}{}){{}(({})()<>)(<>)}{}(<>)<>(({})[(((()()()){}){}()){({}[()])}{}])((){[()](<{}>)}{})({}<>{})<>(({})[((((()()()()()){}){})){}{}])((){[()](<{}>)}{})({}<>{})<>(({})[(((((()()()()()){}){}){}())){}{}])((){[()](<{}>)}{})({}<>{}){{}(<(<>({})()()<>)>)}{}<>(({})[(((()()()()()){}){}){}()])((){[()](<{}>)}{}){{}(({})[()])(<>)<>(<({}<{({}<>)<>}{}>)>)<>{({}<>)<>}{}(<>)}{}(<>)<>(({})[(((((()()()()()){})){}{}())){}{}])((){[()](<{}>)}{})({}<>{})<>(({})[((((()()()()()){}){})()){}{}])((){[()](<{}>)}{})({}<>{})<>(({})[(((((()()()()()){}){}){}())()){}{}])((){[()](<{}>)}{})({}<>{}){{}<>(<(({})[()()])(<>)<>(<({}<{({}<>)<>}{}>)>)<>{({}<>)<>}{}>)}{}<>(({})[(((((()()()()()){}){})()){}{}){}])((){[()](<{}>)}{}){{}{}(<(<>{}<>)>)}{}(<>)<>(<({}<{({}<>)<>}{}>)>)<>{({}<>)<>}{}<>}{}{({}<>)<>}<>

360 Bytes gespart, indem entgegengesetzte Klammern relativ und nicht von Grund auf neu berechnet werden (zB ')'= '(' + 1statt (((5 * 2) * 2) * 2) + 1)

34 Bytes mit einigen direkten Ersetzungen von DJMcMayhem gespeichert

10 Byte durch Überlappung des >]}Bearbeitungscodes eingespart

118 Bytes durch Deduplizieren von Rollen eingespart

40 Bytes gespart, indem der leere Stapel genutzt wird, um die erste Rolle zu vereinfachen

Durch Markieren von EOF mit -1 wurden 48 Bytes gespart, was einen präziseren Rollcode ermöglicht

36 Bytes gespart durch Verwendung der " stock equals" -Logik anstelle meiner eigenen

98 Bytes gespart, da Jo King eine effizientere Methode zum Erstellen der Ausgabe gefunden hat

Probieren Sie es online!

Das erste Mal Golf spielen in Brain-Flak, also gibt es wahrscheinlich einige wirklich große Verbesserungen, aber es funktioniert. Viel Kopieren / Einfügen für jeden Bracket-Typ und groß dank des automatischen Ganzzahlgenerators und des Roll-Snippets von hier .

Erklärung hier , TIO formatiert es einfacher

Bonusantwort:

Komprimiertes Brain-Flak 583 Bytes

{((}|[((()))))|}|}|}||(){[)|(<}|||}|{}((}|)>|(>||}(>|>((}|[((()))|}|})|{(}[)|||}||(){[)|(<}|||}|(}>}|>((}|[(((()))))|}|}||}}||(){[)|(<}|||}|(}>}|>((}|[((((()))))|}|}|})||}}||(){[)|(<}|||}|(}>}|{}(<(>(}|))>||||}>((}|[((()))))|}|}|})||(){[)|(<}|||}|{}((}|[)||(>|>(<(}<{(}>|>|}||||>{(}>|>|}(>||}(>|>((}|[((((()))))|}||}})||}}||(){[)|(<}|||}|(}>}|>((}|[(((()))))|}|}|)|}}||(){[)|(<}|||}|(}>}|>((}|[((((()))))|}|}|})|)|}}||(){[)|(<}|||}|(}>}|{}>(<((}|[))||(>|>(<(}<{(}>|>|}||||>{(}>|>|}|||}>((}|[((((()))))|}|}|)|}}|}||(){[)|(<}|||}|{}}(<(>}>||||}(>|>(<(}<{(}>|>|}||||>{(}>|>|}>|}{(}>|>|>

Probieren Sie es online!

(Beachten Sie, dass der obige Link nicht funktioniert, da TIO keinen Compressed Brain-Flak-Interpreter hat. Einen Transpiler für Brain-Flak finden Sie hier. )

Ich habe überprüft, ob dies gültig ist, indem ich mit diesem Tool auf Brain-Flak transpiliere. Es ist jetzt so effizient, dass ein Timeout unwahrscheinlich ist.

Kamil Drakari
quelle
4
Das erste Mal Golf spielen in Brain-Flak, und das Ergebnis ist das? Wow.
Erik der Outgolfer
Sie können immer ersetzen <>(<()>)mit (<>). Sie können auch (<>{}<>)(<()>)zu(<(<>{}<>)>)
DJMcMayhem
1
@JoKing Ich würde nicht wissen, wie, ich habe es kaum geschafft, die Rolle am Ende der Schleife zu extrahieren, anstatt eine zusätzliche
Rolle
1
Das ist jenseits des Golfspiels. Das ist purer Wahnsinn. Herzliche Glückwünsche !
Arthur Attout
1
@JoKing Die Änderung war einfacher und effektiver als erwartet und jetzt in der Antwort enthalten
Kamil Drakari
7

Retina 0.8.2 , 103 98 Bytes

[])}>]
$&;
T`])}>|`[({<;
r`(.*)((;)|(?<-3>.))*
$&$.1$*;
(?<=(.)((;)|(?<-3>.))*);
;$1
T`;-{`_>-}`;.

Probieren Sie es online! Link enthält Testfälle. Bearbeiten: 5 Bytes mit Inspiration von @MartinEnder gespeichert. Erläuterung:

[])}>]
$&;
T`])}>|`[({<;

Setzen Sie ;nach jeder schließenden Klammer ein und ändern Sie alle Klammern in offene Klammern. Ändern Sie auch das |s in ;s.

r`(.*)((;)|(?<-3>.))*
$&$.1$*;

Zählen Sie die Anzahl nicht übereinstimmender offener Klammern und addieren Sie diese Anzahl ;s.

(?<=(.)((;)|(?<-3>.))*);
;$1

Kopieren Sie jede öffnende Klammer in die entsprechende ;.

T`;-{`_>-}`;.

Klappen Sie die kopierten Klammern um und löschen Sie die ;s.

Neil
quelle
1
Sie könnten alle ausgeblendeten Balken vermeiden, wenn Sie |in etwas wie übersetzen !. Es wäre nicht einmal Bytes kosten , wenn Sie übersetzen >-}zu <-{(was meiner Meinung nach gibt zfür |).
Martin Ender
@MartinEnder Ich bin mir nicht sicher, ob ich deinen Standpunkt zum verstehe, zaber ich habe mir trotzdem eine Möglichkeit ausgedacht, ein paar Bytes mehr zu sparen.
Neil
5

TIS , 670 666 Bytes

-4 Bytes für den Sprung vorwärts, um zurückzuspringen

Code:

@0
MOV UP RIGHT
@1
MOV ANY ACC
SUB 41
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
MOV ACC DOWN
@2
NOP
MOV 124 LEFT
@3
MOV ANY DOWN
@4
MOV UP ACC
JGZ O
MOV 40 LEFT
JLZ (
MOV 41 LEFT
JRO 3
O:SUB 21
MOV ACC DOWN
JRO -8
(:MOV 41 RIGHT
@5
MOV ANY DOWN
@6
MOV ANY DOWN
@7
MOV UP ACC
JGZ O
MOV 60 LEFT
JLZ <
MOV 62 LEFT
JRO 3
O:SUB 31
MOV ACC DOWN
JRO -8
<:MOV 62 RIGHT
@8
MOV ANY DOWN
@9
MOV ANY DOWN
@10
S:MOV UP ACC
JGZ O
MOV 91 LEFT
JLZ [
MOV 93 LEFT
JRO 3
O:SUB 31
MOV ACC DOWN
JRO -8
[:MOV 93 RIGHT
@11
MOV ANY DOWN
@12
MOV ANY DOWN
@13
MOV UP ACC
JEZ |
MOV 123 LEFT
JLZ {
MOV 125 LEFT
JRO 2
|:MOV DOWN LEFT
JRO -7
{:MOV 125 RIGHT
@14
MOV ANY DOWN
@15
MOV UP DOWN
@16
MOV UP LEFT

Layout:

6 3
CCCCCCCCCCCCCCCCSC
I0 ASCII -
O0 ASCII -

Probieren Sie es online!

Ich bezweifle, dass dies das kleinste ist, aber ich sehe keinen Weg, es kleiner zu machen. Leider NOPscheinen alle s für das Timing notwendig zu sein, und ich kann den Stack nicht dort platzieren, wo er sich @14gerade befindet, da von dort eingelesen ANYwurde @11.

Die Struktur dieser Lösung ist wie folgt:

Input
  |
  V
  0    1:synchro  2:EOF
  3    4:parens     5
  6    7:angles     8
  9   10:squares   11
 12   13:curlies   14
 15      stack     16
  |
  V
Output

Wenn eine offene Klammer angezeigt wird, wird die offene Klammer entlang der linken Spalte gesendet, um ausgegeben zu werden, und die schließende Klammer wird entlang der rechten Spalte an den Stapel gesendet.

Wenn eine schließende Klammer angezeigt wird, werden sowohl das Öffnen als auch das Schließen entlang der linken Spalte gesendet, um ausgegeben zu werden.

Beim Erkennen einer Pipe wird der Stapel abgelegt und an die Ausgabe gesendet.

Bei EOF @1wird @2anstelle des Eingabestreams von mit dem Lesen von begonnen @0. @2erzeugt einen endlosen Strom von Rohren, so dass der Stapel abgelassen wird.

Sobald sowohl die Eingabe als auch der Stapel erschöpft sind, wird das Programm angehalten.

Warnung: Aufgrund der Einschränkungen von TIS ist die Stapelgröße auf 15 begrenzt. Wenn etwas tiefer verschachtelt ist, führt diese Implementierung zu einem falschen Ergebnis.

Phlarx
quelle
4

JavaScript (ES6), 107 Byte

Nimmt die Eingabe als Array von Zeichen. Gibt eine Zeichenfolge zurück.

a=>a.map(c=>(n=(S='|()[]{}<>').indexOf(c))?n&1?(s=[S[n+1],...s],c):S[n-1]+c:s.shift(),s=[]).join``+s.join``

Probieren Sie es online!

Arnauld
quelle
102 Bytes durch Rückgabe eines Zeichenarrays.
Shaggy
@ Shaggy Danke! Aber ist es wirklich erlaubt, 1-Zeichen- und 2-Zeichen-Zeichenfolgen gemischt zurückzugeben?
Arnauld
Hmm ... ja, vielleicht ist das die "permissive" Ausgabe.
Shaggy
@DJMcMayhem Schauen Sie sich bitte das neue Ausgabeformat an und lassen Sie uns wissen, ob dies akzeptabel ist.
Arnauld
1
@arnauld Huh, aus irgendeinem Grund hat mich das nicht angesprochen. Ich denke, ich würde nein sagen. Ein Array von Zeichen oder eine Zeichenfolge sind beide Standardformate, aber ein Array von Zeichenfolgen scheint mir nicht gültig zu sein
DJMcMayhem
3

Rubin , 104 Bytes

a=[];$<.chars{|c|r="|[{(<>)}]";i=r.index(c);i<1||(i<5?a:$>)<<r[-i];$>.<<i<1?a.pop: c};$><<a.reverse.join

Dies ist ein vollständiges Programm, das auf der Konsole ausgegeben wird. (i<5?a:$>)<<r[-i]muss einer der coolsten Golfplätze sein, die ich je gemacht habe.

Probieren Sie es online!

Rubin , 106 Bytes

->s{a=[];(s.chars.map{|c|r="|>)}][{(<";d=r[-i=r.index(c)];i<5||a<<d;i<1?a.pop: i<5?d+c:c}+a.reverse).join}

Dies ist meine erste Lösung. Eine anonyme Lambda-Funktion, die Zeichenfolgen akzeptiert und zurückgibt.

Probieren Sie es online!

MegaTom
quelle
3

Brain-Flak , 606 548 496 418 394 390 Bytes

{((({})))(<>)(((((((([(())()()()]){}){}){}())(()))(((())()())()){}{})){}[()])({<(({}<>{}[()]))>(){[()](<{}>)}{}<>}{}<><{}>){({}({})<>)(<>)}{}({}<>)(<>)(((((((([(())()()()]){}){}){}())(()))(((())()){}()){})){})({<(({}<>{}[()]))>[()]{()(<{}>)}{}<>}{}<>){(<({}(<()>)<>({})<{({}<>)<>}>)>)<>{({}<>)<>}}{}({}()<>){{}({}<>)((<>))}{}{}<>(<({}(<()>)<><{({}<>)<>}>)>)<>{({}<>)<>}{}<>}{}{({}{}<>)<>}<>

Probieren Sie es online!

Ich habe dies damit begonnen, dass ich Kamil Drakaris Antwort golfen habe , aber sie ist mir bis zu dem Punkt entgangen , an dem ich beschlossen habe, sie als separate Antwort zu veröffentlichen.

Erläuterung:

{ #While input on stack
	((({})))(<>)	#Preserve copy of the character
	(((((		#Push the differences between start bracket characters
	((([(())()()()]){}){}){}())	#Push -31, 1
	(()))				#Push -30, 1
	(((())()())()){}{})		#Push -19, 1
	){}[()])			#Push -39
	({<(({}<>{}[()]))>(){[()](<{}>)}{}<>}{}<><{}>)	#If the character is any of the start brackets
	{({}({})<>)(<>)}{}					#Push the current character + TOS to the other stack

	({}<>)(<>)
	(((((		#Push the differences between end bracket characters
	((([(())()()()]){}){}){}())	#Push -31, 1
	(()))				#Push -30, 1
	(((())()){}()){})		#Push -19, 1
	){})				#Push -40
	({<(({}<>{}[()]))>[()]{()(<{}>)}{}<>}{}<>)	#If the character is any of the end brackets
	{(<({}(<()>)<>({})<{({}<>)<>}>)>)<>{({}<>)<>}}{}	#Push the character + TOS to the output

	({}()<>)	#If the character is not a |
	{{}({}<>)((<>))}{}	#Move current character to the other stack and push a zero
	{}		#Pop the top value of the stack, either the | or a 0
	<>(<({}(<()>)<><{({}<>)<>}>)>)<>{({}<>)<>}{}<>	#And push top of other stack to the output
}{}
{({}{}<>)<>}<>	#Reverse output and append the excess end brackets

Und natürlich...

Komprimierte Gehirnflocken, 285 Bytes:

{(((}|||(>|(((((((([()|)))||}|}|})|()||((()|))|)|}}||}[)||({<((}>}[)||||){[)|(<}|||}>|}><}||{(}(}|>|(>||}(}>|(>|(((((((([()|)))||}|}|})|()||((()|)|})|}||}|({<((}>}[)||||[)|{)(<}|||}>|}>|{(<(}(<)||>(}|<{(}>|>|||||>{(}>|>||}(})>|{}(}>|((>|||}}>(<(}(<)||><{(}>|>|||||>{(}>|>|}>|}{(}}>|>|>
Scherzen
quelle
1
Sehr beeindruckendes Golfen! Ich bin enttäuscht, dass ich das nicht früher bemerkt habe. Ich muss mich später damit befassen, um zu verstehen, wie es funktioniert.
Kamil Drakari
2

Java 10, 424 Bytes

s->{int i=0;for(var c:s.toCharArray()){if("(<[{".indexOf(c)>-1)i++;if(c=='|')i--;}for(;i-->0;)s+='|';s=s.replace(")","()").replace(">","<>").replace("]","[]").replace("}","{}");char[]c=s.toCharArray(),r=new char[124];r[40]=41;r[60]=62;r[91]=93;r['{']='}';var o="";for(;++i<c.length ;){if(c[i]=='|'){c[i]=o.charAt(0);o=o.substring(1);}if("(<[{".indexOf(c[i])>-1&")>]}".indexOf(i+1<c.length?c[i+1]:0)<0)o=r[c[i]]+o;}return c;}

Es ist etwas langwierig, aber ich konnte nicht herausfinden, wie ich es weiter verkürzen kann. Dies ist jedoch eine schöne Herausforderung.

Probieren Sie es hier online aus .

Ungolfed-Version:

s -> { // lambda taking a String argument and returning a char[]
    int i = 0; // used for counting the number of '|'s that have been removed at the end of the input
    for(var c : s.toCharArray()) { // look at every character
        if("(<[{".indexOf(c) > -1) // if it's an open monad character
            i++; // we will need one more '|'
        if(c == '|') // if it's a close monad character
            i--; // we will need one '|' less
    }
    for(; i-- > 0; ) // add as many '|'
        s += '|';    // as necessary
    s = s.replace(")", "()").replace(">", "<>").replace("]", "[]").replace("}", "{}"); // replace compressed nilads with their uncompressed versions
    char[] c = s.toCharArray(), // from now on working on a char[] is more efficient since we will only be comparing and replacing
    r = new char[124]; // map open monad characters to their counterparts:
    r[40] = 41;   // '(' to ')'
    r[60] = 62;   // '<' to '>'
    r[91] = 93;   // '[' to ']'
    r['{'] = '}'; // '{' to '}'
    var o = ""; // we use this String as a kind of stack to keep track of the last open monad character we saw
    for(; ++i < c.length ;) { // iterate over the length of the expanded code
        if(c[i] == '|') { // if the current character is a close monad character
            c[i] = o.charAt(0); // replace it with the top of the stack
            o = o.substring(1); // and pop the stack
        }
        if("(<[{".indexOf(c[i]) > -1 // if the current character is an open monad/nilad character
         & ")>]}".indexOf(i+1 < c.length ? c[i+1] : 0) < 0) // and it's not part of a nilad (we need to test for length here to avoid overshooting)
            o = r[c[i]]+o; // using the mapping we established, push the corresponding character onto the stack
    }
    return c; // return the uncompressed code
}
OOBalance
quelle
2

Python 2, 188 184 180 177 174 173 Bytes

p,q='([{<',')]}>'
d,s,a=dict(zip(p,q)),[],''
for c in input():
 if c in d:a+=c;s+=[c]
 elif'|'==c:a+=d[s.pop()]
 else:a+=dict(zip(q,p))[c]+c
for c in s[::-1]:a+=d[c]
print a

4 Bytes gespart dank DJMcMayhem.
Probieren Sie es online!


quelle
180
DJMcMayhem
168 Bytes durch das Durcheinander mit der vorletzten Zeile
DJMcMayhem
@DJMcMayhem Das funktioniert nur wenn s es leer ist. Andernfalls befinden sich die zusätzlichen Zeichen am falschen Ende.
2

Python 3 , 122 Bytes

D='()<>[]{} '
def f(x):
 a=s=''
 for c in x:i=D.find(c);a+=i<0and s[0]or D[i-(i&1):i+1];s=D[i+1][i&1:]+s[i<0:]
 return a+s

Probieren Sie es online!

RootTwo
quelle
1

Haskell , 152 Bytes

fst.p
m c="> < ] [)(} {"!!mod(fromEnum c-6)27
p(c:r)|elem c")]}>",(s,t)<-p r=(m c:c:s,t)|c/='|',(s,'|':t)<-p$r++"|",(u,v)<-p t=(c:s++m c:u,v)
p e=("",e)

Probieren Sie es online! oder überprüfen Sie alle Testfälle . pImplementiert einen rekursiven Parser, der für die einfache Grammatik möglicherweise überflüssig ist.

Laikoni
quelle
1
Schöne Funktion m, um die passende Halterung zu finden.
Nimi
1

Python 2 , 244 Bytes

s=input()
B='([{<'
C=')]}>'
Z=zip(B,C)
P=sum(map(s.count,B))-s.count('|')
for i,j in Z:s=s.replace(j,i+j)
s+=P*'|'
b=[0]
for i in s:[b.pop()for j,k in Z if j==b[-1]<k==i];b+=[i][:i in B];s=i=='|'and s.replace(i,C[B.find(b.pop())],1)or s
print s

Probieren Sie es online!

Es dauerte weit mehr als ein oder zwei Stunden, um das zum Laufen zu bringen ...

Erik der Outgolfer
quelle