170 likes | 183 Views
A guide on how to create a self-reproducing program in C++ using different attempts and exercises. Includes C/C++ source code examples and solutions.
E N D
CS 163Data StructuresChapter 11Self-Reproducing C++ Programs Herbert G. Mayer, PSU Status 6/11/2015
Syllabus • Goal • First Try • Second Try • Exercise 1 • Third Try • Success • Exercise 2 • More Complex Self-Reproducer • Haskel Solution • References
General Goal • Write a program p in C or C++ that requires no input, but produces an output string o, with o being textually identical to the source program p! • Ideal Goal at CCUT: to write this program in C++
First Try • C Source Attempt 1, assuming C-flavor that does not require: #include <stdio.h> • Program source: • char*s="char*s=main(){printf(s);}";main(){printf(s);} • Program Output: char*s=main(){printf(s);} • Verdict: Goal obviously not accomplished!
Second Try C/C++ Source Attempt 2: main(){char*s="main(){char*s=%c%s%c";printf(s,34,s,34);} Program Output: main(){char*s="main(){char*s=%c%s%c" Verdict: Goal also not accomplished!
Exercise 1 Without reading ahead, students should try to design a self-reproducing program on their own The rules are: • Write a C, C++, . . . or Java program that reads no input and produces 1 output, which is identical to its own source • With zero compiler issues, i.e. also no warnings • Compiled best on 2 different compilers, for example: • For the first compiler use C++ • For the second use gcc • Best NOT to use 2 Microsoft or 2 GNU compilers! Coming from the same background, they may have identical, inherited flaws • The Unix diff command must find zero differences, no blanks, no \n, nothing to be flagged!! Total diff silence! Shorter is better, but there is no requirement to stay below a certain number of lines
Third Try C/C++ Source Attempt 3: main(){char*s="main(){char*s=%c%s%c;printf(s,34,s,34);";printf(s,34,s,34);} Program Output: main(){char*s="main(){char*s=%c%s%c;printf(s,34,s,34);";printf(s,34,s,34); Note: Warp-around is a pure PowerPoint issue; the line is one long single C source line Verdict: Goal almost accomplished! Except missing ‘}’
Success at Try 4 Final Attempt: main(){char*s="main(){char*s=%c%s%c;printf(s,34,s,34);}";printf(s,34,s,34);} Program Output: main(){char*s="main(){char*s=%c%s%c;printf(s,34,s,34);}";printf(s,34,s,34);} Verdict: Finally accomplished! All 1 single line of C++ source
Exercise 2 Students should replace the parameterized double quotes 34 “ with ‘\”’ main(){char*s="main(){char*s=%c%s%c;printf(s,34,s,34);}";printf(s,34,s,34);}
More Complex Self-Reproducer • Build the following programs • part1.c is the core of a C program to become self-reproducing • chop.c chops an incoming source string to char constants of the kind ’x’, with the comma , • part2.c is a copy of part1.c but minus the first line, holding the C code char s[]={ • Next come initial source programs to create the self-replicator • Then I explain in detail, how to make part2.c
part1.c to be deleted for part2.c char s[]={ 0}; int main() { // main inti; printf("char s[]={\n"); for(i=0;s[i];i++){ if(i%20==0)printf("\n"); switch(s[i]){ case'\'':printf("'\\\'',");break; case'\n':printf("'\\n',");break; case'\\':printf("'\\\\',");break; default:printf("'%c',",s[i]); } } printf("%s",s); }
chop.c #include <stdio.h> int main() { // main char c; int count = 0; while( ( c = getchar() ) != EOF ) { if( 0 == ( count % 20 ) ) { printf( "\n" ); } //end if switch ( c ){ case '\'': printf( "'\\\''," ); break; case '\n': printf( "'\\n'," ); break; case '\\': printf( "'\\\\'," ); break; default: printf( "'%c',", c ); } //end switch count++; } //end while } //end main
part1.c Chopped, not line 1 '0','}',';','\n','i','n','t',' ','m','a','i','n','(',')','\n','{',' ','/','/',' ', 'm','a','i','n','\n',' ',' ','i','n','t',' ','i',';','\n',' ',' ','p','r','i','n', 't','f','(','"','c','h','a','r',' ','s','[',']','=','{','\\','n','"',')',';','\n', ' ',' ','f','o','r','(','i','=','0',';','s','[','i',']',';','i','+','+',')','{', '\n',' ',' ',' ',' ','i','f','(','i','%','2','0','=','=','0',')','p','r','i','n', 't','f','(','"','\\','n','"',')',';','\n',' ',' ',' ',' ','s','w','i','t','c','h', '(','s','[','i',']',')','{','\n',' ',' ',' ',' ',' ',' ','c','a','s','e','\'','\\', '\'','\'',':','p','r','i','n','t','f','(','"','\'','\\','\\',’\'\'','\'',',','"',')', ';','b','r','e','a','k',';','\n',' ',' ',' ',' ',' ',' ','c','a','s','e','\'','\\', 'n','\'',':','p','r','i','n','t','f','(','"','\'','\\','\\','n','\'',',','"',')',';', 'b','r','e','a','k',';','\n',' ',' ',' ',' ',' ',' ','c','a','s','e','\'','\\','\\', '\'',':','p','r','i','n','t','f','(','"','\'','\\','\\','\\',’\,'\'',',','"',')',';', 'b','r','e','a','k',';','\n',' ',' ',' ',' ',' ',' ','d','e','f','a','u','l','t', ':','p','r','i','n','t','f','(','"','\'','%','c','\'',',','"',',','s','[','i',']', ')',';','\n',' ',' ',' ',' ','}','\n',' ',' ','}','\n',' ',' ','p','r','i','n','t', 'f','(','"','%','s','"',',','s',')',';','\n','}','\n', add 0}; here
Detailed Instructions Create part1.c Compile and run for kicks. Output: char s[]={ cp part1.ctemp1, delete first line, which is char s[]={ Run chop.o < temp1 > temp2 cp part1.c part2.c Insert temp2 into the part2.c char array s[] At end of char array in part2.c: move 0}; to end of previous line, i.e. exchange the place of the \n In part2.c to avoid duplication, delete the original line 0}; Now compile part2.c and run part2.o > output diff output part2.c is null
part2.c char s[]={ '0','}',';','\n','i','n','t',' ','m','a','i','n','(',')','\n','{',' ','/','/',' ', 'm','a','i','n','\n',' ',' ','i','n','t',' ','i',';','\n',' ',' ','p','r','i','n', 't','f','(','"','c','h','a','r',' ','s','[',']','=','{','\\','n','"',')',';','\n', ' ',' ','f','o','r','(','i','=','0',';','s','[','i',']',';','i','+','+',')','{', '\n',' ',' ',' ',' ','i','f','(','i','%','2','0','=','=','0',')','p','r','i','n', 't','f','(','"','\\','n','"',')',';','\n',' ',' ',' ',' ','s','w','i','t','c','h', '(','s','[','i',']',')','{','\n',' ',' ',' ',' ',' ',' ','c','a','s','e','\'','\\', '\'','\'',':','p','r','i','n','t','f','(','"','\'','\\','\\','\\','\'','\'',',','"',')', ';','b','r','e','a','k',';','\n',' ',' ',' ',' ',' ',' ','c','a','s','e','\'','\\', 'n','\'',':','p','r','i','n','t','f','(','"','\'','\\','\\','n','\'',',','"',')',';', 'b','r','e','a','k',';','\n',' ',' ',' ',' ',' ',' ','c','a','s','e','\'','\\','\\', '\'',':','p','r','i','n','t','f','(','"','\'','\\','\\','\\','\\','\'',',','"',')',';', 'b','r','e','a','k',';','\n',' ',' ',' ',' ',' ',' ','d','e','f','a','u','l','t', ':','p','r','i','n','t','f','(','"','\'','%','c','\'',',','"',',','s','[','i',']', ')',';','\n',' ',' ',' ',' ','}','\n',' ',' ','}','\n',' ',' ','p','r','i','n','t', 'f','(','"','%','s','"',',','s',')',';','\n','}','\n',0}; int main() { // main inti; printf("char s[]={\n"); for(i=0;s[i];i++){ if(i%20==0)printf("\n"); switch(s[i]){ case'\'':printf("'\\\'',");break; case'\n':printf("'\\n',");break; case'\\':printf("'\\\\',");break; default:printf("'%c',",s[i]); } } printf("%s",s); }
Haskell Solution During the summer 2012 course of CS 510 a student provided the following complete solution in Haskell: main = putStr s >> print s s = "main = putStr s >> print s\ns = "
References • Quine Page for Self-Producing Programs: http://www.nyx.net/~gthompso/quine.htm • Wiki Page for quine program: http://en.wikipedia.org/wiki/Quine_(computing) • Quine’s Paradox: http://en.wikipedia.org/wiki/Quine%27s_paradox • Ken Thompson’s “Reflections on Trust”: http://cm.bell-labs.com/who/ken/trust.html