C++Guns – RoboBlog blogging the bot

08.09.2010

Nochmal Brainfuck

Filed under: Allgemein — Tags: — Thomas @ 21:09

Einfache Aufgabe: Eingabe 0 -> Ausgabe 1; Eingabe 1 -> Ausgabe 0.
Und zwar die Zahlen 0 und 1, nicht die Zeichen.

$ echo -e "\000" | beef if2.bf | xxd
0000000: 01 .
$ echo -e "\001" | beef if2.bf | xxd
0000000: 00

Hier ein paar Lösungen.
Von Siberion 10 Zeichen
,[>-<-]>+.
12 Zeichen
,>+<[>-<-]>.
Und wenn man die Rahmenbedingungen etwas lockert und zusätzliche Zeichen in der
Ausgabe in kauf nimmt, kommt man sogar auf 7 Zeichen
,[-.]+.

Von Seba 11 Zeichen
,[[-]->]<+.
13 Zeichen
,[>.->]<+[.-]

Und von mir. 20 Zeichen
,>+<[[-].>-<]>[.[-]]
Und modifizierte Version von seba. 9 Zeichen
,[-->]<+.

15.08.2010

Game Of Life in BF to C

Filed under: Allgemein — Tags: , — Thomas @ 23:08

The Game of Life in Brainfuck geschrieben und mit einem BF2C Converter übersetzt und compiliert und dann noch statisch gelinkt.

Das klingt irgendwie absurd oder?

Im Anhang der Quelltext... (God gab ihn mir ;) )

gameoflifesource.tar

fucking C

Filed under: Allgemein — Tags: , — Thomas @ 20:08

Bei Lft Craft habe ich den wohl schrecklichsten C Code aller Zeiten gefunden.

char m[9999],*n[99],*r=m,*p=m+5000,**s=n,d,c;main(){for(read(0,r,4000);c=*r;
r++)c-']'||(d>1||(r=*p?*s:(--s,r)),!d||d--),c-'['||d++||(*++s=r),d||(*p+=c==
'+',*p-=c=='-',p+=c=='>',p-=c=='<',c-'.'||write(2,p,1),c-','||read(2,p,1));}

Leute die meinen Style schlecht reden habe einfach keine Ahnung ;)

Und ja, das Ding compiliert wirklich. In den letzten zwei Tage habe ich das mal in lesbares C übersetzt


// m enthaelt den kompletten bf code und den programm pointer
// also programm und daten, so ist es moeglich eine quine zu programmieren
// 0 bis 4999 ist der bf code in plain text
// n und s sind mir noch nicht so ganz klar
// r zeigt auf das aktuelle zeichen im bf code
// p der programm pointer
// d hat irgendwas mit schleifen zu tun
// c das aktuelle zeichen im bf code

char m[9999],*n[99],*r=m,*p=m+5000,**s=n,d,c;

main(){
// Lese maximal 4000 zeichen von stdin
// (was mag passieren wenn der bf code groesser als 4000 zeicen ist
// naja, wird wohl einfach ueberschrieben)
for(read(0,r,4000);c=*r;r++)
{
//c- ']' || (d>1 || (r=*p?*s:(--s,r)) , !d||d--);
if(c == ']')
{
if(d <= 1) { if(*p) { r = *s; } else { --s; } } if(d) d--; } //c- '[' || d++ || (*++s=r), if(c == '[') { if(d == 0) { d++; *(++s) = r; } } //d|| ( if(d == 0) { //*p+=c=='+', if(c == '+') *p += 1; //*p-=c=='-', if(c == '-') *p -= 1; //p+=c=='>',
if(c == '>')
p += 1;

//p-=c=='<'; if(c == '<') p -= 1; //c-'.'||write(2,p,1); if(c == '.') write(2,p,1); //c-','||read(2,p,1); if(c == ',') read(2,p,1); // ) } } }
(Leider geht die Formatierung in WordPress verloren).

Aber jetzt erstmal ein paar Erklärungen. Wenn man sich den Code genauer anschaut, wird man feststellen, dass wohl alle ";" durch "," ersetzt wurden. So kann man mehrere Anweisungen in eine Zeile schreiben.

a = 0, b = a+1, c = a+b;

Weiterhin fällt auf, dass es kein einziges if() gibt. Man kann ein if() durch ein logisches ODER ersetzen:

a || b++;

Der Ausdruckt stimmt so. Normalerweise erwartet man sowas in einer if(), aber es geht auch ohne. Das Programm wird von links nach rechts abgearbeitet.
Ein ODER ist dann wahr, wenn einer von beiden Argumenten wahr ist.

Also wenn a ungleich 0 ist, zählt das als wahr. Aber sagen wir lieber true, spricht sich schöner.
Wenn also a true ist, muss b++ nicht mehr ausgeführt werden.
Ist a hingegen 0, wird b++ ausgeführt.
So einfach kann es sein :)

Dann fallen Sachen wie p+=c=='>' auf. Auch das ist ganz einfach. Der Operator == wird vor += ausgewertet. Wenn also c=='>' ist, ergibt das true, also 1. Dann steht als zweites p+=1 da. Sollte c irgendein anderes Zeichen sein, wird p+=0 ausgeführt.

Folgender Code ist auch noch erwähnenswert

c- '[' || d++ || blubb

Das ist wieder eine geschachtelte if(). In c steht ein Zeichen vom Bf Code. Sollte in C nun das Zeichen '[' stehen, und subtrahiert man nun ein '[', ist das ergebis 0. Unsere if() wird also wahr und der nächste Ausdruck wird in Angriff genommen.

d++ || blubb

Das Problem mit dem ++ sollte ja bekannt sein, bei d++ wird erst d bentuzt, dann um eins erhöht. Bei ++d wird erst d um ein erhöht und dann benutzt. Ist also d gleich 0. Wird d um eins erhöht und dann blubb ausgewetet.

Mit diesem Wissen kann man schon fast den kompletten Code verstehen. Nur diese eine Zeile hat mich eine Weile beschäftigt

c- ']' || (d>1 || (r=*p?*s:(--s,r)) , !d||d--)

Schaut erstmal eine Weile drauf. Am Anfang eine if(), noch eine if(), noch eine if() und dann noh eine if() ;)

Interesannt ist nur der innerste Teil

r=*p?*s:(--s,r)

Da steht ?:
Und ?: geht vor dem = Operator. Wenn also *p nicht 0 ist, dann wird r = *s ausgeführt. Sollte *p 0 ergeben. Wird erst s um eins erniedrigt und dann r=r ausgeführt.
r=r ist natürlich doof, aber ohne das würde da stehen r=--s; und das ist ja nicht gewollt.

So und was ist das nun für ein Programm? Na ein Brainfuck Interpreter. Sieht man doch ;)

Powered by WordPress