Just 4 Fun: BrainFuck-Text-Interpreter (BF2Ascii und Ascii2BF)

    • Offizieller Beitrag

    Hi,
    einige von euch werden wohl auch durch L3viathans Rätsel, wie ich, erstmalig mit der Programmiersprache Brainfuck Kontakt gehabt haben.
    Ich finde diese recht originell, wenn auch nicht unbedingt sehr sinnvoll, wird dem Namen gerecht. Wenn man das Prinzip verstanden hat, ist die Sprache nicht mal schwer, nur extrem unübersichtlich. Ich habe mal einen BF-Text-Interpreter geschrieben, der in BF-Code dargestellten Text in eine lesbare Ausgabe verwandelt.
    Der erste String ist optimiert erstellt (relativ adressiert), der zweite ist ohne jede Optimierung. Ein deutlicher Unterschied.
    Viel Spaß damit. :)

    Edit:
    Kleiner Nachtrag noch. Der Interpreter arbeitet nicht mit geschachtelten Schleifen. Diese sollten aber selbst bei super-optimierten Texten nicht auftreten.

    Edit 2:
    Einen Bug gefixt (Pointerinitialisierung).

    Edit 3: NEU
    Erweitert um die Funktion _AsciiToBFcode(). Hiermit läßt sich normaler Text in BrainFuck-Code ausgeben.
    Es gibt unendlich viele Möglichkeiten von BF-Code, der letztlich denselben Ascii-String ausgibt.
    Ich habe mir folgendes Verfahren entwickelt:
    - Ermitteln der Ascii-Werte für jedes Zeichen
    - Runden der Ascii-Werte auf glatte Zehner
    - für jeden unterschiedlichen glatten Zehnerwert wird eine Zelle belegt und mit diesem Wert befüllt
    jetzt wird Zeichen für Zeichen durchgegangen:
    - Pointer auf Zelle mit zugehörigem gerundeten Zehnerwert
    - je nach Differenz zum tatsächlichem Ascii-Wert in/dekrementieren
    - Zeichenausgabe
    - Zelle auf den vorigen Wert zurücksetzen
    Sicher kann man noch weiter optimieren, aber für den Anfang finde ich es schon recht gut gelungen. :rolleyes:

    Edit 4:
    Ich habe die Ascii-to-BF Funktion noch 2-mal verbessert. Bei langen Texten nun eine Verkürzung des Codes um 50-70 % im Vergleich zur ersten Variante.
    Ich setzte jetzt in den Referenzzellen den Wert nach Nutzung nicht zurück, sondern speichere den zuletzt genutzten Wert. Wird die Referenzzelle wieder genutzt bildet sich der Wert zum In/Dekrementieren aus Differenz Ascci-Wert und letztem in der Zelle genutzten Wert. Das ist doch wesentlich effektiver als in den alten Varianten.
    Ich habe alle 3 Versionen im Skript belassen, da könnt ihr ja vergleichen.
    Einen Bug habe ich auch noch gefixt in der Interpreter-Hilfsfunktion. Waren mehrere gleiche Zeichen am Stringende, trat ein Indexfehler auf.

    BF-Text-Interpreter
    [autoit]

    #cs
    Der C-Sourcecode eines in Brainfuck geschriebenen Programms hat nur eine minimallänge von 1055 Bytes - also rund 1KB. Brainfuck arbeitet (standardmäßig) auf einem 30000 Bytes großen Array und einem Pointer, der irgendwo in das Array zeigt. Der Pointer kann vor- und zurückgesetzt werden, die Werte unter dem Counter können hoch- und runtergezählt, eingelesen und ausgegeben werden. Außerdem gibt es ein sehr hübsches Schleifenkonstrukt.

    [/autoit] [autoit][/autoit] [autoit]

    Befehle

    [/autoit] [autoit][/autoit] [autoit]

    Brainfuck kommt mit sage und schreibe 8 Befehlen aus. Daher kommt auch die Bezeichnung "minimalistische" Programmiersprache da die Sprache über ein Minimum an Befehlen - in diesem Fall 8 - verfügt.

    [/autoit] [autoit][/autoit] [autoit]

    Befehl C Equivalent Beschreibung
    > ++ptr; Setzt den Pointer um 1 weiter
    < --ptr; Setzt den Pointer um 1 zurück
    + ++*ptr; Den Wert des Elements im Array um 1 erhöhen
    - --*ptr; Den Wert des Elements im Array um 1 verringern
    [ while(*ptr){ Starte einer Schleife - Abbruchbedingung ist, das der Wert des Elements im Array unter dem Pointer 0 beträgt
    ] } Ende einer Schleife
    . putchar(*ptr); ASCII-Code des Wertes unter dem Pointer ausgeben
    , *ptr=getchar(); Zeichen einlesen und im Array unter dem Pointer speichern

    [/autoit] [autoit][/autoit] [autoit]

    Jedes Array und jedes Element eines Arrays wird, mit dem ersten Setzen des Pointers auf dieses Element mit 0 initialisiert. Der Pointer selbst steht zu Beginn ebenfalls immer auf 0.
    #ce
    #include-once
    #include <Array.au3>
    #include <String.au3>

    [/autoit] [autoit][/autoit] [autoit]

    Local $sBF_1 = '>++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.'
    Local $sBF_2 = '>++++++++++[>+>+++>+++++>+++++++>++++++++++>+++++++++++>++++++++++++<<<<<<<-]>>>>-----.>>>---.-.<+.<<++++++++.>>>.<<<<<++.>>>>--.<+..>>.-.<<<<<.>>-------.>>+++++.<----.>---------.+++++.<<++++.>>>++.<<++.>---.<<<----.<<+++.---.'
    ConsoleWrite('$sBF_1 & $sBF_2:' & @CRLF)
    ConsoleWrite(_BFtextInterpreter($sBF_1) & _BFtextInterpreter($sBF_2) & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    $BFcode = _AsciiToBFcode( _
    'Befehl C Equivalent Beschreibung' & @CRLF & _
    '> ++ptr; Setzt den Pointer um 1 weiter' & @CRLF & _
    '< --ptr; Setzt den Pointer um 1 zurück' & @CRLF & _
    '+ ++*ptr; Den Wert des Elements im Array um 1 erhöhen' & @CRLF & _
    '- --*ptr; Den Wert des Elements im Array um 1 verringern' & @CRLF & _
    '[ while(*ptr){ Starte einer Schleife - Abbruchbedingung ist, das der Wert des Elements im Array unter dem Pointer 0 beträgt' & @CRLF & _
    '] } Ende einer Schleife' & @CRLF & _
    '. putchar(*ptr); ASCII-Code des Wertes unter dem Pointer ausgeben' & @CRLF & _
    ', *ptr=getchar(); Zeichen einlesen und im Array unter dem Pointer speichern' & @CRLF )
    ConsoleWrite('BF-Beschreibung als BF-Code:' & @CRLF & $BFcode & @crlf)
    ConsoleWrite('und zurück:' & @crlf & _BFtextInterpreter($BFcode) & @CRLF)
    ConsoleWrite('ASCII-to-BF in 3 Versionen:' & @CRLF)
    ConsoleWrite(_AsciiToBFcode_1('Hello World!') & @CRLF)
    ConsoleWrite(_AsciiToBFcode_2('Hello World!') & @CRLF)
    ConsoleWrite(_AsciiToBFcode('Hello World!') & @CRLF) ; aktuelle Version

    [/autoit] [autoit][/autoit] [autoit]

    Func _BFtextInterpreter($sBFcode)
    Local $aCode = StringSplit(StringStripWS($sBFcode, 8), '', 2)
    Local $sOut = '', $index = 0, $count, $iLoop = -1
    Local $a[30000], $pt = 0
    Do
    If $index < UBound($aCode) -1 Then
    $count = __CountEvenNeighbour($aCode, $index)
    Else
    $count = 0
    EndIf
    Switch $aCode[$index]
    Case '>'
    $pt += 1 + $count
    $index += 1 + $count
    Case '<'
    $pt -= (1 + $count)
    $index += 1 + $count
    Case '+'
    $a[$pt] += 1 + $count
    $index += 1 + $count
    Case '-'
    $a[$pt] -= 1 + $count
    $index += 1 + $count
    Case '['
    $iLoop = $index +1
    $index += 1 + $count
    Case ']'
    If $a[$pt] = 0 Then
    $iLoop = -1
    $index += 1 + $count
    Else
    $index = $iLoop
    EndIf
    Case '.'
    $sOut &= Chr($a[$pt])
    $index += 1
    Case ',' ; erwartet Input von Standardeingabe
    ;~ $a[$pt] = Asc('Input')
    ;~ $index += 1
    EndSwitch
    Until $index = UBound($aCode)
    Return $sOut
    EndFunc ;==>_BFtextInterpreter

    [/autoit] [autoit][/autoit] [autoit]

    Func __CountEvenNeighbour(ByRef $aCode, $iStart)
    Local $counter = 0
    While $aCode[$iStart +$counter +1] == $aCode[$iStart]
    $counter += 1
    If $iStart +$counter +1 = UBound($aCode) Then ExitLoop
    WEnd
    Return $counter
    EndFunc ;==>__CountEvenNeighbour

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _AsciiToBFcode($sString) ; Version 3
    Local $aString = StringSplit($sString, '', 2)
    Local $aWork[UBound($aString)][3], $aRounded[1][2]
    ; === ASCII-Werte ermitteln und die zugehörigen gerundeten Zehner-ASCII-Werte
    For $i = 0 To UBound($aString) -1
    $aWork[$i][0] = Asc($aString[$i]) ; ASCII-Wert des Zeichens
    $aWork[$i][1] = Round($aWork[$i][0] /10) *10 ; auf Zehnerwert auf/abgerundeter ASCII-Wert
    $aWork[$i][2] = $i ; Position im Ausgangsstring
    Next
    ; === nach ASCII-Werten aufsteigend sortieren
    _ArraySort($aWork)
    ; === gerundete Zehner-ASCII-Werte zusammenfassen
    $aRounded[0][0] = $aWork[0][1] ; gerundeter Zehner-ASCII-Wert
    $aRounded[0][1] = $aWork[0][1] ; momentan genutzter Wert
    For $i = 0 To UBound($aWork) -1
    If $i < UBound($aWork) -1 Then
    If $aWork[$i][1] <> $aWork[$i+1][1] Then
    ReDim $aRounded[UBound($aRounded)+1][2]
    $aRounded[UBound($aRounded)-1][0] = $aWork[$i+1][1]
    $aRounded[UBound($aRounded)-1][1] = $aWork[$i+1][1]
    EndIf
    EndIf
    Next
    ; === wieder nach Reihenfolge Zeichen sortieren
    _ArraySort($aWork, 0, 0,0,2)
    ; === je eine Zelle auf einen einmal vorkommenden gerundeten Zehner-ASCII-Wert setzen
    Local $sBF = '>++++++++++[' ; Faktor 10 vor der Schleife erstellen
    For $i = 0 To UBound($aRounded) -1
    $sBF &= '>' & _StringRepeat('+', $aRounded[$i][0]/10) ; Faktor für Zehner-Multiplikation
    Next
    $sBF &= _StringRepeat('<', UBound($aRounded)) & '-]' ; zurück auf Schleifenzähler und dekrementieren
    $sBF &= '>' ; Pointer auf erste Wertezelle
    Local $index, $index_last = 0, $step = 0, $diff = 0, $nextStep
    For $i = 0 To UBound($aString) -1 ; durch Eingabestring iterieren
    $index = _ArraySearch($aRounded, $aWork[$i][1])
    $diff = $index - $index_last
    $index_last = $index
    Select
    Case $diff < 0
    $nextStep = _StringRepeat('<', Abs($diff))
    Case 0
    $nextStep = ''
    Case Else
    $nextStep = _StringRepeat('>', $diff)
    EndSelect
    $sBF &= $nextStep
    $diff = $aWork[$i][0] - $aRounded[$index][1] ; Differenz zw. tatsächlichem Wert und zuletzt genutztem Wert
    ; === Zelle unter Pointer um $diff in/dekrementieren, Zeichen ausgeben
    Select
    Case $diff < 0
    $nextStep = _StringRepeat('-', Abs($diff))
    Case 0
    $nextStep = ''
    Case Else
    $nextStep = _StringRepeat('+', $diff)
    EndSelect
    $aRounded[$index][1] += $diff ; zuletzt genutzten Wert in Zelle aktualisieren
    $sBF &= $nextStep & '.'
    Next
    Return $sBF
    EndFunc ;==>_AsciiToBFcode

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _AsciiToBFcode_2($sString) ; Version 2
    Local $aString = StringSplit($sString, '', 2)
    Local $aWork[UBound($aString)][3], $aRounded[1][2]
    ; === ASCII-Werte ermitteln und die zugehörigen gerundeten Zehner-ASCII-Werte
    For $i = 0 To UBound($aString) -1
    $aWork[$i][0] = Asc($aString[$i]) ; ASCII-Wert des Zeichens
    $aWork[$i][1] = Round($aWork[$i][0] /10) *10 ; auf Zehnerwert auf/abgerundeter ASCII-Wert
    $aWork[$i][2] = $i ; Position im Ausgangsstring
    Next
    ; === nach ASCII-Werten aufsteigend sortieren
    _ArraySort($aWork)
    ; === gerundete Zehner-ASCII-Werte zusammenfassen
    $aRounded[0][0] = $aWork[0][1]
    $aRounded[0][1] = 1
    For $i = 0 To UBound($aWork) -1
    If $i < UBound($aWork) -1 Then
    If $aWork[$i][1] <> $aWork[$i+1][1] Then
    ReDim $aRounded[UBound($aRounded)+1][2]
    $aRounded[UBound($aRounded)-1][0] = $aWork[$i+1][1]
    $aRounded[UBound($aRounded)-1][1] = 1
    Else
    $aRounded[UBound($aRounded)-1][1] += 1
    EndIf
    EndIf
    Next
    ; === wieder nach Reihenfolge Zeichen sortieren
    _ArraySort($aWork, 0, 0,0,2)
    ; === je eine Zelle auf einen einmal vorkommenden gerundeten Zehner-ASCII-Wert setzen
    Local $sBF = '>++++++++++[' ; Faktor 10 vor der Schleife erstellen
    For $i = 0 To UBound($aRounded) -1
    $sBF &= '>' & _StringRepeat('+', $aRounded[$i][0]/10) ; Faktor für Zehner-Multiplikation
    Next
    $sBF &= _StringRepeat('<', UBound($aRounded)) & '-]' ; zurück auf Schleifenzähler und dekrementieren
    $sBF &= '>' ; Pointer auf erste Wertezelle
    Local $index, $index_last = 0, $step = 0, $diff = 0, $nextStep, $backStep, $lastback, $nextIsSame = False
    For $i = 0 To UBound($aString) -1 ; durch Eingabestring iterieren
    $index = _ArraySearch($aRounded, $aWork[$i][1])
    $diff = $index - $index_last
    $index_last = $index
    Select
    Case $diff < 0
    $nextStep = _StringRepeat('<', Abs($diff))
    Case 0
    $nextStep = ''
    Case Else
    $nextStep = _StringRepeat('>', $diff)
    EndSelect
    $sBF &= $nextStep
    $diff = $aWork[$i][0] - $aWork[$i][1] ; Differenz zw. tatsächlichem Wert und Round-Wert
    ; === Zelle unter Pointer um $diff in/dekrementieren, Zeichen ausgeben, Wert zurücksetzen
    ; === nur wenn Folgezeichen <> aktuellem Zeichen
    If Not $nextIsSame Then
    Select
    Case $diff < 0
    $nextStep = _StringRepeat('-', Abs($diff))
    $backStep = _StringRepeat('+', Abs($diff))
    Case 0
    $nextStep = ''
    Case Else
    $nextStep = _StringRepeat('+', $diff)
    $backStep = _StringRepeat('-', $diff)
    EndSelect
    $lastback = $backStep
    EndIf
    $aRounded[$index][1] -= 1
    ; === wenn Zelle letztmalig verwendet wurde, Wert in Zelle nicht mehr zurücksetzen
    If $aRounded[$index][1] = 0 Then $backStep = ''
    ; === wenn Folgezeichen identisch, dann Wert auch nicht zurücksetzen
    If ($i < UBound($aString) -2) And ($aString[$i] == $aString[$i+1]) Then
    $nextIsSame = True
    $lastback = $backStep
    $backStep = ''
    ElseIf ($i < UBound($aString) -2) And ($aString[$i] <> $aString[$i+1]) Then
    $nextIsSame = False
    $backStep = $lastback
    EndIf
    $sBF &= $nextStep & '.' & $backStep
    Next
    Return $sBF
    EndFunc ;==>_AsciiToBFcode

    [/autoit] [autoit][/autoit] [autoit]

    Func _AsciiToBFcode_1($sString) ; Version 1
    Local $aString = StringSplit($sString, '', 2)
    Local $aWork[UBound($aString)][3], $sUniqueRounded
    ; === ASCII-Werte ermitteln und die zugehörigen gerundeten Zehner-ASCII-Werte
    For $i = 0 To UBound($aString) -1
    $aWork[$i][0] = Asc($aString[$i]) ; ASCII-Wert des Zeichens
    $aWork[$i][1] = Round($aWork[$i][0] /10) *10 ; auf Zehnerwert auf/abgerundeter ASCII-Wert
    $aWork[$i][2] = $i ; Position im Ausgangsstring
    Next
    ; === nach ASCII-Werten aufsteigend sortieren
    _ArraySort($aWork)
    ; === gerundete Zehner-ASCII-Werte zusammenfassen
    $sUniqueRounded = $aWork[UBound($aWork)-1][1]
    For $i = UBound($aWork) -1 To 0 Step -1
    If $i > 0 Then
    If $aWork[$i][1] <> $aWork[$i-1][1] Then $sUniqueRounded = $aWork[$i-1][1] & ',' & $sUniqueRounded
    EndIf
    Next
    ; === wieder nach Reihenfolge Zeichen sortieren
    _ArraySort($aWork, 0, 0,0,2)
    Local $aUnique = StringSplit($sUniqueRounded, ',', 2) ; Array mit gerundeten Zehner-ASCII-Werten
    ; === je eine Zelle auf einen einmal vorkommenden gerundeten Zehner-ASCII-Wert setzen
    Local $sBF = '>++++++++++[' ; Faktor 10 vor der Schleife erstellen
    For $i = 0 To UBound($aUnique) -1
    $sBF &= '>' & _StringRepeat('+', $aUnique[$i]/10) ; Faktor für Zehner-Multiplikation
    Next
    $sBF &= _StringRepeat('<', UBound($aUnique)) & '-]' ; zurück auf Schleifenzähler und dekrementieren
    $sBF &= '>' ; Pointer auf erste Wertezelle
    Local $index, $index_last = 0, $step = 0, $diff = 0, $nextStep, $backStep
    For $i = 0 To UBound($aString) -1
    $index = _ArraySearch($aUnique, $aWork[$i][1])
    $diff = $index - $index_last
    $index_last = $index
    Select
    Case $diff < 0
    $nextStep = _StringRepeat('<', Abs($diff))
    Case 0
    $nextStep = ''
    Case Else
    $nextStep = _StringRepeat('>', $diff)
    EndSelect
    $sBF &= $nextStep
    $diff = $aWork[$i][0] - $aWork[$i][1] ; Differenz zw. tatsächlichem Wert und Round-Wert
    ; === Zelle unter Pointer um $diff in/dekrementieren, Zeichen ausgeben, Wert zurücksetzen
    Select
    Case $diff < 0
    $nextStep = _StringRepeat('-', Abs($diff))
    $backStep = _StringRepeat('+', Abs($diff))
    Case 0
    $nextStep = ''
    Case Else
    $nextStep = _StringRepeat('+', $diff)
    $backStep = _StringRepeat('-', $diff)
    EndSelect
    If $i = UBound($aString) -1 Then $backStep = ''
    $sBF &= $nextStep & '.' & $backStep
    Next
    Return $sBF
    EndFunc ;==>_AsciiToBFcode

    [/autoit]
  • Hallo BugFix.
    Du hast da echt was richtig nettes gezaubert.
    Habe mal (ausversehen) den Wikipedia Artikel zu BrainFuck gelesen, und ich finde die Sprache irgendwie, naja ich verstehe nicht wie man aus + und , und . und - ein "Hallo" macht xD
    Aber trotzdem finde ich die umwandlung in AutoIt sehr gelungen.
    MfG. PrideRage

    Meine Projekte:
    ClipBoard Manager (beendet)
    Gutes ClipBoard Verwaltungs Programm mit nützlichen Funktionen.

    HTML Creator (beendet)
    Nützliches Tool um schnell ein eigenes HTML Dokument zu erstellen.

  • Kannste das mal andersrum machen ?

    Normal to Brainfuck ?

    Ich finde es lustig arbeite aber nicht mit einer Sprache die mir das Gehirn "f*ickt", sprich verwirren :D
    Aber sonst :rofl:

    Es gibt sehr viele Leute, die glauben. Aber aus Aberglauben.
    - Blaise Pascal

  • Kann das sein, dass dein Interpreter einen Bug hat? Das funktioniert bei mir nicht:

    [autoit]

    $sBF = ">+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.>>>++++++++[<++++>-]<.>>>++++++++++[<+++++++++>-]<---.<<<<.+++.------.--------.>>+."
    ConsoleWrite(_BFtextInterpreter($sBF) & @CRLF)

    [/autoit]

    Es geht aber bei https://autoit.de/www.brainfuck.tk
    PS: Der Code ist der übersetzte Beispielcode von hier

    Einmal editiert, zuletzt von progandy (15. Juli 2010 um 11:00)

  • Ich kannte BrainFuck schon vorher (oder hab zumindest schonmal was davon gehört ^^)
    Ich hab mal den Delphi Interpreter benutzt und progandy's Script benutzt.
    Da kam eben "Hello World!" und die Meldung "Brainfucker gracefully orgasmed; 492 instructions executed in 1 ms, at 492,00 instructions per milisecond" raus :rofl:

    Spoiler anzeigen

    Grundkenntnisse in: C++, JavaScript
    Sehr gute Kenntnisse: PHP, JAVA, C und näturlich AutoIt


    Klaviatur, Anhang UDF, GDI+ Mühle

    Zitat

    "Wenn einen um 20h der Pizzadienst anruft und fragt, ob man's nur vergessen hat und ob man das gleiche
    möchte wie immer -- dann sollte man sein Bestellverhalten evtl überdenken"

    • Offizieller Beitrag

    Kann das sein, dass dein Interpreter einen Bug hat? Das funktioniert bei mir nicht:


    Ja, war eine Fehlinterpretation von mir. Ich hatte die Beschreibung so verstanden, dass bei erstmaliger Verwendung von ">" der vorher wertlose Pointer auf das erste (Index 0) Element zeigt. Diese Abfrage habe ich jetzt entfernt und dann funktioniert es auch mit deinem Bsp.

  • Hey. Also wenn ich meinen Senf dazu ablassen darf:
    BrainFuck ist besser als Ook!, da man mit BF auch 2d-Spiele programmieren kann.

    Nur keine Hektik - das Leben ist stressig genug

  • Hey. Also wenn ich meinen Senf dazu ablassen darf:
    BrainFuck ist besser als Ook!, da man mit BF auch 2d-Spiele programmieren kann.


    Ook! ist das selbe wie BF.
    BugFix : Und was ist mit verschachtelten Schleifen? :D '+++++[->++[-]<]'
    PS: Soll [] eigentlich eine Do-Until oder eine While-Schleife (sagt jedenfalls Wikipedia) sein?

    • Offizieller Beitrag

    Verschachtelte Schleifen nehme ich mir später vor. ;)
    Ich würde die Schleifen als Do-Until betrachten, da die Abbruchbedingung klar ist (Wert unter Pointer=0) und dieser Pointer erst nach Ausführung von Operationen erreicht wird - also fußgesteuert. Es erfolgt immer ein Eintritt in die Schleife, was ja bei While-End nicht der Fall wäre.
    Ich bastel gerade an Text-2-BF. Aber geschachtelte Schleifen verkneife ich mir da im Moment noch. :rolleyes:

  • Ich hab das hier zu Text zu BF gefunden:

    Spoiler anzeigen

    Ist zwar Javascript, aber das könnte man ja auf AutoIt übertragen

  • Ich habe mich mal an verschachtelten Schleifen versucht mit einem eigenen Interpreter
    Dazu gibt es auch einen Ook-BF Konverter in beide Richtungen ;)

    Spoiler anzeigen
    [autoit]

    #cs
    Befehl C Equivalent Beschreibung
    > ++ptr; Setzt den Pointer um 1 weiter
    < --ptr; Setzt den Pointer um 1 zurück
    + ++*ptr; Den Wert des Elements im Array um 1 erhöhen
    - --*ptr; Den Wert des Elements im Array um 1 verringern
    [ while(*ptr){ Starte einer Schleife - Abbruchbedingung ist, das der Wert des Elements im Array unter dem Pointer 0 beträgt
    ] } Ende einer Schleife
    . putchar(*ptr); ASCII-Code des Wertes unter dem Pointer ausgeben
    , *ptr=getchar(); Zeichen einlesen und im Array unter dem Pointer speichern

    [/autoit] [autoit][/autoit] [autoit]

    Jedes Array und jedes Element eines Arrays wird, mit dem ersten Setzen des Pointers auf dieses Element mit 0 initialisiert. Der Pointer selbst steht zu Beginn ebenfalls immer auf 0.
    #ce

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Global $sBF[5]
    $sBF[0] = '>++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.'
    $sBF[1] = '++++++++[>+>++>+++>++++>+++++>++++++>+++++++>++++++++>+++++++++>++++++++++>+++++++++++>++++++++++++>+++++++++++++>++++++++++++++>+++++++++++++++>++++++++++++++++<<<<<<<<<<<<<<<<-]>>>>>>>>+.-<<<<<<<<>>>>>>>>>>>>>>>---.+++<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>----.++++<<<<<<<<<<<<<<<>>>>>>>>>>>>>>-.+<<<<<<<<<<<<<<>>>>>>>>>+.-<<<<<<<<<>>>>>>>>>>>>>>>----.++++<<<<<<<<<<<<<<<>>>>.<<<<>>>>>>>>>>>>>>---.+++<<<<<<<<<<<<<<>>>>>>>>>>>>>---.+++<<<<<<<<<<<<<>>>>>>>>>>>>>---.+++<<<<<<<<<<<<<>>>>>>>>>>>>>>>----.++++<<<<<<<<<<<<<<<>>>>>>>>>>>>>>+++.---<<<<<<<<<<<<<<>>>>.<<<<>>>>>>>>++.--<<<<<<<<>>>>>>>>>>>>>>++.--<<<<<<<<<<<<<<>>>>>>>>>>>>+.-<<<<<<<<<<<<>>>>>>>>>>>>>+.-<<<<<<<<<<<<<>>>>>>>>>>>>>>--.++<<<<<<<<<<<<<<>>>>>>>>>--.++<<<<<<<<<>>>>>>>>>>>>>>>---.+++<<<<<<<<<<<<<<<>>>>>>>>>>>>+++.---<<<<<<<<<<<<>>>>>>>>>>>>>+++.---<<<<<<<<<<<<<>>>>>>--.++<<<<<<>++.--<.'
    $sBF[2] = '>+++++++++[<++++++++>-]<.>+++++++[<++++>-]<+.+++++++..+++.>>>++++++++[<++++>-]<.>>>++++++++++[<+++++++++>-]<---.<<<<.+++.------.--------.>>+.'
    $sBF[3] = '+++++[->++[-]<]' ; verschachtelte Schleifen
    $sBF[4] = ',[.,]' ; Einfaches Eingabe-Echo

    [/autoit] [autoit][/autoit] [autoit]

    For $i = 0 To UBound($sBF)-1
    MsgBox(0, 'BF Example ' & $i, $sBF[$i])
    ConsoleWrite("> Example " & $i & @CRLF)
    ConsoleWrite(_BF_Execute($sBF[$i]) & @CRLF )
    Next
    ConsoleWrite(" " & @CRLF)

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Local $sOok = "Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook.Ook! Ook. Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook?Ook! Ook! Ook? Ook! Ook? Ook. Ook. Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook.Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook. Ook! Ook. Ook. Ook. Ook. Ook.Ook. Ook. Ook! Ook. Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook.Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook.Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook.Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook! Ook? Ook? Ook. Ook. Ook.Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook. Ook.Ook. Ook? Ook! Ook! Ook? Ook! Ook? Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook.Ook? Ook. Ook? Ook. Ook? Ook. Ook? Ook. Ook! Ook. Ook. Ook. Ook. Ook. Ook. Ook.Ook! Ook. Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook.Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook! Ook!Ook! Ook. Ook. Ook? Ook. Ook? Ook. Ook. Ook! Ook."
    MsgBox(0, 'Ook Example', $sOok)
    ConsoleWrite(">Ook Example (converted):" & @CRLF)
    ConsoleWrite(_BF_FromOok($sOok) & @error & @CRLF)
    ConsoleWrite("+Execute: " & @CRLF)
    ConsoleWrite(_BF_Execute(_BF_FromOok($sOok)) & @CRLF)

    [/autoit] [autoit][/autoit] [autoit]

    Func _BF_FromOok($sOok)
    ; Author: ProgAndy
    Local $array = StringRegExp($sOok, '(?i)Ook([!.?])', 3)
    $sOok = ''
    Local $iSize = UBound($array)
    If Mod($iSize, 2) Then Return SetError(1,0,'')
    $iSize -= 1
    For $i = 0 To $iSize Step 2
    Switch $array[$i] & $array[$i+1]
    Case '..'
    $sOok &= '+'
    Case '!!'
    $sOok &= '-'
    Case '.?'
    $sOok &= '>'
    Case '?.'
    $sOok &= '<'
    Case '!?'
    $sOok &= '['
    Case '?!'
    $sOok &= ']'
    Case '!.'
    $sOok &= '.'
    Case '.!'
    $sOok &= ','
    Case Else
    Return SetError(2,0,'')
    EndSwitch
    Next
    Return $sOok
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _BF_ToOok($sBF)
    ; Author: ProgAndy
    Local $array = StringRegExp($sBF, "([-[\]+.<>,])", 3)
    $sBF = ''
    Local $iSize = UBound($array)-1
    For $i = 0 To $iSize
    Switch $array[$i]
    Case '+'
    $sBF &= 'Ook. Ook. '
    Case '-'
    $sBF &= 'Ook! Ook! '
    Case '>'
    $sBF &= 'Ook. Ook? '
    Case '<'
    $sBF &= 'Ook? Ook. '
    Case '['
    $sBF &= 'Ook! Ook? '
    Case ']'
    $sBF &= 'Ook? Ook! '
    Case '.'
    $sBF &= 'Ook! Ook. '
    Case ','
    $sBF &= 'Ook. Ook! '
    Case Else
    Return SetError(2,0,'')
    EndSwitch
    Next
    Return $sBF
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func _BF_Execute($sBF, $sInput='')
    ; Author: ProgAndy
    StringReplace($sBF, '[', '[', 0, 1)
    Local $iTemp = @extended
    StringReplace($sBF, ']', ']', 0, 1)
    If @extended <> $iTemp Then Return SetError(1,0,'')
    $sBF = StringRegExp($sBF, "([-[\]+.<>,])", 3)
    If @error Then Return SetError(2,0,'')
    Local $iArraySize = 3000, $iLoopCount = 100
    Local $aValues[$iArraySize], $iPtr=0, $sOutput = '', $aLoops[$iLoopCount], $iLoop=0, $iSkipLoop=0
    Local $iCount = UBound($sBF)-1
    For $i = 0 To $iCount
    If $iSkipLoop > 0 Then
    If $sBF[$i] = '[' Then
    $iSkipLoop += 1
    ElseIf $sBF[$i] = ']' Then
    $iSkipLoop -= 1
    EndIf
    ContinueLoop
    EndIf
    Switch $sBF[$i]
    Case '>'
    $iPtr += 1
    If $iPtr >= $iArraySize Then
    ConsoleWrite("- Enlarge BF Valuearray" & @CRLF)
    $iArraySize += 20
    ReDim $aValues[$iArraySize]
    EndIf
    Case '<'
    $iPtr -= 1
    If $iPtr < 0 Then Return SetError(3,0,'')
    Case '+'
    $aValues[$iPtr] += 1
    Case '-'
    $aValues[$iPtr] -= 1
    Case '['
    If $aValues[$iPtr] <= 0 Then ; While-Loop nicht durchlaufen wenn Wert = 0
    $iSkipLoop = 1
    Else
    $iLoop += 1
    If $iLoop >= $iLoopCount Then
    ConsoleWrite("- Enlarge BF Loopstack" & @CRLF)
    $iLoopCount += 20
    ReDim $aLoops[$iLoopCount]
    EndIf
    $aLoops[$iLoop] = $i
    EndIf
    Case ']'
    If $aValues[$iPtr] > 0 Then $i = $aLoops[$iLoop]-1
    $iLoop -= 1
    ContinueLoop
    Case '.'
    $sOutput &= Chr($aValues[$iPtr])
    Case ','
    If $sInput = '' Then $sInput = InputBox("BF Interpreter - Input", "Input char for Interpreter", "") ; Wenn kein Input vorhanden, Eingabebox
    $iTemp = Asc(StringLeft($sInput, 1))
    $sInput = StringTrimLeft($sInput, 1)
    $aValues[$iPtr] = $iTemp
    Case Else
    Return SetError(1,0,'')
    EndSwitch
    Next
    Return $sOutput
    EndFunc

    [/autoit]
  • Weil es so relativ unanschaulich ist, was die Funktionen von BugFix veranstalten,
    gibts jetzt eine gui zum Spaß haben.

    Kann man auch wunderbar zum Codieren von Ascii Zeichenketten nehmen. DAS kann garantiert NIEMAND lesen xD

    mfg
    Mars(i)

  • Geil !!!
    Wenn man nicht wüsste das es BrainFuck ist würde man sicher keine ahnung haben wie man es auslesen soll :D

    Es gibt sehr viele Leute, die glauben. Aber aus Aberglauben.
    - Blaise Pascal

  • Hab die beiden Neuen Funktionen auch direkt mal eingebaut.

    Dabei sind mit in Funktion 2 einige Bugs aufgefallen.

    Wenn am Ende der AscII Zeichenkette ein llo (wie z.B. bei Hallo) stelt wird irgendwas anderes draus. aber kein llo^^. Manchmal kommt jjj manchmal lll dabei raus.

    Spoiler anzeigen

    "asdfkjhasdfkjhlfa llo lllo llo"
    wird zu
    ">++++++++++[>+++>++++++++++>+++++++++++>++++++++++++<<<<-]>>---.+++>>-----.+++++<<.++.-->---.+++----.++++<++++.-------.+++>>-----.+++++<<.++.-->---.+++----.++++<++++.---->--.++<++.-----.+++<++.-->>--..+++.-<<++.-->>--...+.-<<++.-->>--..."
    und dann zu
    "asdfkjhasdfkjhlfa llo lllm jjj"

    "ollo"
    ">++++++++++[>+++++++++++<-]>+.---..."
    "olll"

    usw...

    Der Fehler trat bisher ausschließlich bei sachen mit einem "ll" drin auf. sonst nirgends.

    (Daber da wahrscheinlich irgendwann eine noch mehr optimierte Version des Ascii2BF compilers rauskommt kann man v2 einfach weglassen...)

    mfg
    Mars(i)