#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.

Befehle

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.

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

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>

Local $sBF_1 = '>++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.'
Local $sBF_2 = '>++++++++++[>+>+++>+++++>+++++++>++++++++++>+++++++++++>++++++++++++<<<<<<<-]>>>>-----.>>>---.-.<+.<<++++++++.>>>.<<<<<++.>>>>--.<+..>>.-.<<<<<.>>-------.>>+++++.<----.>---------.+++++.<<++++.>>>++.<<++.>---.<<<----.<<+++.---.'
ConsoleWrite('$sBF_1 & $sBF_2:' & @CRLF)
ConsoleWrite(_BFtextInterpreter($sBF_1) & _BFtextInterpreter($sBF_2) & @CRLF)

$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

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

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


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




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

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
