leo@s514.ipmce.su (Leonid A. Broukhis) (03/11/91)
This is an introspective program in C. char*a="char*a=%c%s%c;main(){printf(a,34,a,34);}";main(){printf(a,34,a,34);} Do you know a shorter program? -- Leonid A. Broukhis | 89-1-95 Liberty St. | "BROUKHIS" is Hebrew for 7+095 494.6241 (h) | Moscow 123481 USSR | "BENEDICTAE" 7+095 132.9475 (o) | (leo@s514.ipmce.su) | {Licet omnia qualibet dicas}
olsen@casbah.acns.nwu.edu (Jeff Olsen) (03/11/91)
In article <AB2MbsdCB6@s514.ipmce.su> leo@s514.ipmce.su writes: > This is an introspective program in C. >char*a="char*a=%c%s%c;main(){printf(a,34,a,34);}";main(){printf(a,34,a,34);} > Do you know a shorter program? sure... *a="*a=%c%s%c;main(){printf(a,34,a,34);}";main(){printf(a,34,a,34);} I tried it with MSC 6.0 and whatever the default cc is on a encore multimax. GCC doesn't appear to like it, though. Jeff Olsen olsen@eecs.nwu.edu
andy@research.canon.oz.au (Andy Newman) (03/12/91)
The smaller the better! In many interpreted BASIC's of years ago you could do: 1 LIST Which when RUN would produce: 1 LIST (Using a single digit line number to make it as small as possible). -- Andrew Newman, Software Engineer. | Net: andy@research.canon.oz.au Canon Information Systems Research Australia | Phone: +61 2 805 2914 P.O. Box 313 North Ryde, NSW, Australia 2113 | Fax: +61 2 805 2929
scotth@corp.sgi.com (Scott Henry) (03/12/91)
andy> The smaller the better! In many interpreted BASIC's of years ago you andy> could do: andy> 1 LIST andy> Which when RUN would produce: andy> 1 LIST andy> (Using a single digit line number to make it as small as possible). And in any sh|csh|tcsh on unix, this one is about as short as you can get: cat $0 -- Scott Henry <scotth@sgi.com> / Traveller on Dragon Wings Information Services, / Help! My disclaimer is missing! Silicon Graphics, Inc / Politicians no baka!
dm@think.com (Dave Mankins) (03/13/91)
This is not quite the same thing, but it is a hack I have found very useful
when spinning small test programs.
You start the program (e.g., ``foo.c'') with:
#ifdef notdef
cc $0 -g -o `basename $0 .c` -Ineeded-includes -lneeded-libraries
exit;
#endif notdef
#include <stdio.h>
...
(all bound to an emacs function, insert-self-compile, of course)
Then invoke it with:
sh foo.c
This is much less labor-intensive than editing a Makefile (and re-editing it,
if the source file should move to another directory).
Even in semi-formally maintained code, I have found this most useful in files
that make up components of libraries, in this form:
#ifdef notdef
cc $0 -DTEST -g -o `basename $0 .c` -Ineeded-includes -lneeded-libraries
exit;
#endif notdef
/* library module source ... */
#ifdef TEST
main() {
.... code to test the call library functions with test inputs and
check the results ....
}
#endif /* TEST */
This allows your library modules to be self-testing, a great time-saver in the
later phases of development.
--
david mankins (dm@think.com)
clear@cavebbs.gen.nz (Charlie Lear) (03/13/91)
In article <1991Mar12.050929.2870@research.canon.oz.au> andy@research.canon.oz.au (Andy Newman) writes: >The smaller the better! In many interpreted BASIC's of years ago you could do: > 1 LIST >Which when RUN would produce: > 1 LIST >(Using a single digit line number to make it as small as possible). Sorry, your entry is disqualified through being too large. REAL BASICs used to be able to tokenise, and the winner is: 1 L. which when run would produce 1 L. Lets see you do THAT in C! -- -------------------------------------------------------------------------- Charlie "The Bear" Lear | clear@cavebbs.gen.nz | Kawasaki Z750GT DoD#0221 The Cave MegaBBS +64 4 642260 V32 | PO Box 2009, Wellington, New Zealand --------------------------------------------------------------------------
steele@en.ecn.purdue.edu@en.ecn.purdue.edu (Richard A. Steele) (03/13/91)
In article <1991Mar13.032422.9438@cavebbs.gen.nz> clear@cavebbs.gen.nz (Charlie Lear) writes: >In article <1991Mar12.050929.2870@research.canon.oz.au> andy@research.canon.oz.au (Andy Newman) writes: >>The smaller the better! In many interpreted BASIC's of years ago you could do: >> 1 LIST >>Which when RUN would produce: >> 1 LIST >>(Using a single digit line number to make it as small as possible). > >Sorry, your entry is disqualified through being too large. REAL BASICs used >to be able to tokenise, and the winner is: > 1 L. >which when run would produce > 1 L. > >Lets see you do THAT in C! > You sure? If the BASIC is tokenized, then L. will be expanded to LIST in the source code listing, so that you'd get 1 LIST when run. I have to admit, my only experience with tokenized basics is the old 8-bit Ataris; do other basics leave the abbreviation? Rich -- ------------------------------------------------------------------------------- Richard Steele | INTERNET : steele@ecn.purdue.edu Electrical Engineering | BITNET : steele%ecn.purdue.edu@purccvm Purdue University | UUCP : {purdue, pur-ee}!ecn.purdue.edu!steele
henry@zoo.toronto.edu (Henry Spencer) (03/14/91)
In article <1991Mar13.001423.5194@Think.COM> dm@think.com (Dave Mankins) writes: >You start the program (e.g., ``foo.c'') with: > >#ifdef notdef > cc $0 -g -o `basename $0 .c` -Ineeded-includes -lneeded-libraries > exit; >#endif notdef It is no longer legal to put arbitrary trash after "#endif", so that identifier has to go. "#endif /* notdef */" is better. Note also that you need to be careful about what you put inside #ifdef, because it is *not* completely ignored. The above example should be okay, but in general the contents have to be either legal C tokens or things that could not be mistaken for C tokens. Notably, an unmatched ' or " is not kosher. -- "But this *is* the simplified version | Henry Spencer @ U of Toronto Zoology for the general public." -S. Harris | henry@zoo.toronto.edu utzoo!henry
gwyn@smoke.brl.mil (Doug Gwyn) (03/14/91)
In article <SCOTTH.91Mar12125443@harlie.corp.sgi.com> scotth@sgi.com (Scott Henry) writes: >And in any sh|csh|tcsh on unix, this one is about as short as you can get: > cat $0 No, the program contained between the following quotation marks is shorter: ""
peter@ficc.ferranti.com (Peter da Silva) (03/14/91)
Better make the indicated changes or watch it barf on a strict ANSI compiler. In article <1991Mar13.001423.5194@Think.COM> dm@think.com (Dave Mankins) writes: ! #ifdef notdef /* > > cc $0 -g -o `basename $0 .c` -Ineeded-includes -lneeded-libraries > ! exit + + */ > > #endif notdef -- Peter da Silva. `-_-' peter@ferranti.com +1 713 274 5180. 'U` "Have you hugged your wolf today?"
zap@savage.UUCP (Zap Savage) (03/14/91)
In <1991Mar13.151756.2885@en.ecn.purdue.edu>, steele@en.ecn.purdue.edu@en.ecn.purdue.edu (Richard A. Steele) writes: > In article <1991Mar13.032422.9438@cavebbs.gen.nz> clear@cavebbs.gen.nz (Charlie Lear) writes: > > REAL BASICs used > >to be able to tokenise, and the winner is: > > 1 L. > >which when run would produce > > 1 L. > You sure? If the BASIC is tokenized, then L. will be expanded to LIST > in the source code listing, so that you'd get > 1 LIST > when run. I have to admit, my only experience with tokenized basics is > the old 8-bit Ataris; do other basics leave the abbreviation? Nah, old TRS-80s with Level-1 Basic stored exactly what you typed and L. was indeed the short form of LIST as P. was short for PRINT. 1 L. would indeed work. Zap --- Zap Savage, Savage Research, Inc. "We are the energy of Shakespeare's verse/we are what mathematics wants to be/ The Life Force in the Universe/That longs to See!/That would Become/and give a voice to matter that was dumb." "To Sail Beyond The Sun" R. Bradbury&J.V.Post
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (03/14/91)
The subject line is seriously misleading. None of the examples that has been posted has anything to do with INTROSPECTION (one might call 3-Lisp introspective, perhaps even Scheme, with its built in function call-with-current-continuation). They are SELF-REPRODUCING programs, which is something rather different. A program would be introspective if it could take a step back from itself and watch its own workings. (One might even call a UNIX program that has called monitor() or profil() an introspective program.) Self-reproducing programs are old hat. -- The purpose of advertising is to destroy the freedom of the market.
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) (03/14/91)
[About the hack for including a command to compile itself in a C program.] Many years ago Tom Duff wrote a nifty little program called "com"; David Tilbrook added some options, and I later added another. com [-c$Escape] [-n] [-o | -x] file... The program searches each file in turn for a comment /*% <command> \n where % is the Escape chacter (which defaults to "%"). Any Escape character occurring in the file is replaced by the file name from the command line. Then - if the -o flag appeared, the command is written to stdout, or - if the -x flag appeared, the command is written to stderr - if the -n flag did NOT appear, the command is given to system(). So the "com" program itself starts with a comment /*% cc -o com -O % */ In an AWK script, one could have #/*% awk -f % When 'make' come around I gradually stopped using 'com'. > ! #ifdef notdef /* > > cc $0 -g -o `basename $0 .c` -Ineeded-includes -lneeded-libraries > ! exit > + */ > > #endif notdef If you want to use the "shell-in-C" trick, though, it can be simplified: #if 0 /* exec cc -g -o `basename $0 .c` -Ineeded-includes $0 -lneeded-libraries */ #endif -- The purpose of advertising is to destroy the freedom of the market.
magnus%thep.lu.se@Urd.lth.se (Magnus Olsson) (03/14/91)
In article <1991Mar13.151756.2885@en.ecn.purdue.edu> steele@en.ecn.purdue.edu@en.ecn.purdue.edu (Richard A. Steele) writes: >In article <1991Mar13.032422.9438@cavebbs.gen.nz> clear@cavebbs.gen.nz (Charlie Lear) writes: >>Sorry, your entry is disqualified through being too large. REAL BASICs used >>to be able to tokenise, and the winner is: >> 1 L. >>which when run would produce >> 1 L. >You sure? If the BASIC is tokenized, then L. will be expanded to LIST >in the source code listing, so that you'd get > 1 LIST >when run. I have to admit, my only experience with tokenized basics is >the old 8-bit Ataris; do other basics leave the abbreviation? I'm afraid Charlie used the word `tokenize' in a non-canonical way... Tokenization means that tokens (identifiers, keywords etc) are saved just as numbers, not as text. The interpreter would recognize `L.' as a valid abbreviation of LIST, and store the corresponding number. The LIST command would then look up this number and write out the corresponding word, i.e. `LIST'. Applesoft Basic did this, I believe - `?' was accepted as an abbreviation for `PRINT', but the LIST command printed it as `PRINT'. Anyway, there *are* Basics that don't tokenize, but accept abbreviated statements - like the one on the Acorn Atom (a 6502-based British machine). A typical line from an Atom program would look something like 100F.I=1TOA.X;P.ZZX';GOS.200;N. which would correspond to 100 FOR I=1 TO ABS(X) : PRINT ZZ(X) : GOSUB 200 : NEXT I in Micrososft Basic. Unfortunately, Atom Basic didn't allow LIST inside a program, so Charlie's program wouldn't run on an Atom... Magnus Olsson | \e+ /_ Dept. of Theoretical Physics | \ Z / q University of Lund, Sweden | >----< Internet: magnus@thep.lu.se | / \===== g Bitnet: THEPMO@SELDC52 | /e- \q
henry@zoo.toronto.edu (Henry Spencer) (03/15/91)
In article <DQ.90AA@xds13.ferranti.com> peter@ficc.ferranti.com (Peter da Silva) writes: >Better make the indicated changes or watch it barf on a strict ANSI >compiler. > >! #ifdef notdef /* Why? That is legal, strict ANSI C he had inside the #ifdef. In general you can't get away with arbitrary trash in there, but nothing he did was improper. (If you're upset about the $ and `, they are unlawful only when transformed from preprocessor tokens to real tokens, and that never happens in this case.) -- "But this *is* the simplified version | Henry Spencer @ U of Toronto Zoology for the general public." -S. Harris | henry@zoo.toronto.edu utzoo!henry
net@opal.cs.tu-berlin.de (Oliver Laumann) (03/15/91)
In article <15462@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: > >And in any sh|csh|tcsh on unix, this one is about as short as you can get: > > cat $0 > > No, the program contained between the following quotation marks is shorter: "" Hmmm... % /bin/sh $ > foo $ chmod +x foo $ ./foo Cannot exec binary file. sh: ./foo: cannot execute $ ^D This is what happens under SunOS 4.1. Yes, I know, the original poster said "on UNIX", but I found the fact that the SunOS shell refuses to execute an empty file so funny that I wanted to share it with you. Don't tell me that this has something to do with the fact that Sun switched to POSIX with SunOS 4.1...
jay@hermix.UUCP (Jay Skeer) (03/16/91)
This one is self-recognizing. I am sure someone can do it shorter. (Btw, what about lisp's shortest self-repro programs "T", "0", "1", "2", ...) j' ------------------- #include <stdio.h> #define N 18 #define F 8 #define L 80 #define Y Z[k++] #define P sprintf char*I="\"%s\",",*B="%s", M[N*3][L],Z[L],D[N][L]={ "#include <stdio.h>", "#define N 18", "#define F 8", "#define L 80", "#define Y Z[k++]", "#define P sprintf", "char*I=\"\\\"%s\\\",\",*B=\"%s\",", "M[N*3][L],Z[L],D[N][L]={", "\"\"},v='\\\\',q='\\\"';", "main(){int c,i=0,j=0,k,l;", "for(;i<F;P(M[j++],B,D[i++]));", "for(i=0;i<N-1;i++,P(M[j++],I,Z))", "for(k=0,l=0;Z[k]=0,c=D[i][l++];Y=c)", "((c^v)*(c^q))||(Y=v);", "for(i=F;i<N;P(M[j++],B,D[i++]));", "for(i=0;gets(Z);)strcmp(M[i++],Z)&&exit(puts(\"no\"),1);", "exit(puts(\"yes\"),0);}", ""},v='\\',q='\"'; main(){int c,i=0,j=0,k,l; for(;i<F;P(M[j++],B,D[i++])); for(i=0;i<N-1;i++,P(M[j++],I,Z)) for(k=0,l=0;Z[k]=0,c=D[i][l++];Y=c) ((c^v)*(c^q))||(Y=v); for(i=F;i<N;P(M[j++],B,D[i++])); for(i=0;gets(Z);)strcmp(M[i++],Z)&&exit(puts("no"),1); exit(puts("yes"),0);}
kym@bingvaxu.cc.binghamton.edu (R. Kym Horsell) (03/17/91)
In article <217@hermix.UUCP> jay@hermix.UUCP (Jay Skeer) writes: [about a program that recognises itself] Ok, that's nice. Why not progress to the stage of writing programs that write self-recognising programs? The following is a (probabalistic) example. It relies on fixpoint theory to guarantee finding the appropriate parameters (in fact the search for any self-replicating automaton can use this theory) and terminates in several iterations. Of course the output program is not guaranteed to recognise only itself -- it also can be fooled by `family members'. Question -- what is another legal C program that the `recogniser' thinks is similar to itself? Have fun y'all. -kym --- Program to find self-recognising program --- #include <stdio.h> char buf[1000]; char *prog= "main(){int MAGIC=0x%x,c,i=0,s=0;while((c=getchar())>=0)s+=s^(c<<(i++&15));puts(s==MAGIC?\"maybe\":\"no\");}\n"; int sum(MAGIC) { int c,i=0,sum=0; char *cp=buf; sprintf(buf,prog,MAGIC); while(c= *cp++) sum+=sum^(c<<(i++&15)); return sum; } main(){ int MAGIC=0,NEWMAGIC; for(;;) { NEWMAGIC=sum(MAGIC); printf("NEWMAGIC=0x%x\n",NEWMAGIC); if(NEWMAGIC==MAGIC) break; MAGIC=NEWMAGIC; } fputs(buf,stdout); exit(0); } --- self-recognising program found by above --- main(){int MAGIC=0x40116000,c,i=0,s=0;while((c=getchar())>=0)s+=s^(c<<(i++&15));puts(s==MAGIC?"maybe":"no");} --- sample run --- cc t.c a.out < t.c maybe a.out < a.out no --- end ---
gwyn@smoke.brl.mil (Doug Gwyn) (03/17/91)
In article <1991Mar16.163213.9794@bingvaxu.cc.binghamton.edu> kym@bingvaxu.cc.binghamton.edu (R. Kym Horsell) writes: >Ok, that's nice. Why not progress to the stage of writing programs >that write self-recognising programs? My program "" does that too. The reason I posted the empty-content example program was to emphasize the point that without carefully-specified rules this "contest" is a waste of time. I think my example has won the loosely-specified contest.
gwyn@smoke.brl.mil (Doug Gwyn) (03/17/91)
In article <1991Mar16.163213.9794@bingvaxu.cc.binghamton.edu> kym@bingvaxu.cc.binghamton.edu (R. Kym Horsell) writes: >The following is a (probabalistic) example. It relies on fixpoint >theory to guarantee finding the appropriate parameters (in fact the >search for any self-replicating automaton can use this theory) and >terminates in several iterations. I think it was Ken Thompson who tried the experiment of taking the diagnostic output from a UNIX C compiler and feeding it back to another invokation of the compiler as source code: echo foo bar > X # initial invalid "program" while : do cp X x.c cc x.c > X 2>&1 || : if cmp -s X x.c then cat X exit fi done
rdc@nebulus.ampr.org (Dalton Clark) (03/17/91)
magnus%thep.lu.se@Urd.lth.se (Magnus Olsson) writes: >In article <1991Mar13.151756.2885@en.ecn.purdue.edu> steele@en.ecn.purdue.edu@en.ecn.purdue.edu (Richard A. Steele) writes: >>In article <1991Mar13.032422.9438@cavebbs.gen.nz> clear@cavebbs.gen.nz (Charlie Lear) writes: >>>Sorry, your entry is disqualified through being too large. REAL BASICs used >>>to be able to tokenise, and the winner is: >>> 1 L. >>>which when run would produce >>> 1 L. >>You sure? If the BASIC is tokenized, then L. will be expanded to LIST >>in the source code listing, so that you'd get >> 1 LIST >>when run. I have to admit, my only experience with tokenized basics is Isn't there a BASIC that uses "!" as a REM. Thus the "shortest" basic program would be "1!"; this is 1/3 to 1/2 as short as your suggested "1 L." (I would have ommited the space before submitting). I believe it is an old Tandy basic that does this and it did not expand the "!" to rem but left it as is; it did add a space though .....
goer@quads.uchicago.edu (Richard L. Goerwitz) (03/18/91)
>Isn't there a BASIC that uses "!" as a REM. >Thus the "shortest" basic program would be "1!"; this is 1/3 to 1/2 as short >as your suggested "1 L." (I would have ommited the space before submitting). >I believe it is an old Tandy basic that does this and it did not expand the "!" >to rem but left it as is; it did add a space though ..... I don't see any source code here. Please note the followup-to line above. Please, please, please - ! -Richard
ark@alice.att.com (Andrew Koenig) (03/18/91)
In article <15489@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: > In article <1991Mar16.163213.9794@bingvaxu.cc.binghamton.edu> kym@bingvaxu.cc.binghamton.edu (R. Kym Horsell) writes: > >Ok, that's nice. Why not progress to the stage of writing programs > >that write self-recognising programs? > My program "" does that too. No -- if you try to run your program, your implementation should complain that you don't have a function named `main.' -- --Andrew Koenig ark@europa.att.com
gwyn@smoke.brl.mil (Doug Gwyn) (03/19/91)
In article <20063@alice.att.com> ark@alice.UUCP () writes: >In article <15489@smoke.brl.mil> gwyn@smoke.brl.mil (Doug Gwyn) writes: >> My program "" does that too. >No -- if you try to run your program, your >implementation should complain that you don't >have a function named `main.' You apparently lost sight of the fact that the discussion had been enlarged to include shell scripts etc. "" wasn't meant to be a C program.
lee@sq.sq.com (Liam R. E. Quin) (03/21/91)
ok@goanna.cs.rmit.oz.au (Richard A. O'Keefe) writes: >[About the hack for including a command to compile itself in a C program.] > Many years ago Tom Duff wrote a nifty little program called "com"; [...] I still use a shell-script called "use" for troff files, and sometimes for complex shell scripts. It understands a number of comment conventions, and looks for <any-sort-of-comment> use <command> A % sign is turned into the filename. For example, .\" Use pic % | troff - Options other than -n are passed along....and appear immediately before the first option in the Use line, so use -Timpr file in the above file would be turned into pic file | troff -Timpr - The Use comment must be in the 1st 5 lines. Personally I prefer make, but that's another story... Here it is. Edit the "sed" line to change "^G" into a control G before extracting. Lee sed 's/ControlG/^Gg' << 'boy' > use : if [ x"$1" = x"-n" ] then NOACTION=yes; shift fi while [ $# -gt 0 ] do case "$1" in -*) TSOPTS="$TSOPTS '$1'" shift ;; *) break ;; esac done FILE=${1-:"You must give a filename"} CMD=`sed -n '/^[ ]*[#%*;][#%!*;]*\([ ]*[uU]se \)/s//.\\\\" \1/ /^\.[ ]*\\\\"[ ]*[uU]se /p 5q' "${FILE}"` if [ x"$CMD" = x"" ] then echo "No Use comment in the file... do it yourself" exit 1 fi pipeline=`echo "$CMD" | sed -e ' s/^\.[ ]*\\\\"[ ]*[uU]se[ ]*// sControlG%'"ControlG${FILE}"'ControlGg sControlG -ControlG'"${TSOPTS}"'&ControlG ' ` echo $pipeline if [ x"$NOACTION" = x"yes" ] then echo "[no action taken]" else eval $pipeline fi use echo extracted use. exit 0 -- Liam R. E. Quin, lee@sq.com, SoftQuad Inc., Toronto, +1 (416) 963-8337 `A wrong that cannot be repaired must be transcended' Ursula K. Le Guin, in _Tehanu_
ishpanta@bluemoon.uucp (John Huenefeld) (03/22/91)
> Isn't there a BASIC that uses "!" as a REM. > > Thus the "shortest" basic program would be "1!"; this is 1/3 to 1/2 as short > your suggested "1 L." (I would have ommited the space before submitting). > > I believe it is an old Tandy basic that does this and it did not expand the " > to rem but left it as is; it did add a space though ..... I also believe that the Basic on the IBM system 3x machines (34,36,38) also uses the ! as REM. Also when listed it would be listed as 1 ! (even when you just typed 1!). John Huenefeld
al@unhd.unh.edu (Anthony Lapadula) (03/23/91)
In article <17816@crdgw1.crd.ge.com> volpe@camelback.crd.ge.com (Christopher R Volpe) writes: > >But what does this have to do with self-replicating programs? What does *any* of this have to do with C? -- Anthony (uunet!unhd!al, al@cs.unh.edu) Lapadula