karl@haddock.ima.isc.com (Karl Heuer) (03/24/89)
In article <2976@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes: >To me, the really interesting problem is, Write a _portable_ >program which writes its source code exactly. Well, it happens that I was going to post this anyway... *** Portable Self-Replicating C Contest *** Rules: 0. The output of the program must be its own source code. 1. It may not be safely assumed that the source code resides in an openable file at runtime. 2. The program must be written in Strictly Conforming ANSI C. 3. The program must return a proper exit status, indicating whether or not its output-calls succeeded. 4. The source must use only the ISO 646 character set, using trigraphs as needed. 5. No source line may exceed 72 characters. 6. There will be two winners: the first correct program to arrive at my site, and the shortest (measured in source characters, including newlines). The contest ends on 23-Apr-1989. No prizes will be awarded. The rationale for rules 4 and 5 is that I want to distribute the result on punch-cards. :-) I will be the sole judge, and my interpretation of the rules is final. (You might not like trigraphs, but it makes the puzzle more challenging.) Appeals will be allowed on the question of whether a construct is legal Strictly Conforming ANSI C; the pANS should be the final authority here. Be warned that rule 2 will be observed to the letter. For example, if you invoke the variadic function printf(), there must be a prototype in scope (either explicitly declared in the code, or via including <stdio.h>). Followups to comp.std.c only. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint (Why 72? The last eight columns are reserved for possible addition of a card sequence number at some future date.)
uucibg@sw1e.UUCP (3929]) (03/24/89)
In article <12144@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes: >Well, it happens that I was going to post this anyway... > >*** Portable Self-Replicating C Contest *** > >Rules: >0. The output of the program must be its own source code. [ More of the rules of the contest ] >Followups to comp.std.c only. > >Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint >(Why 72? The last eight columns are reserved for possible addition of a card >sequence number at some future date.) This is a good opportunity for me to ask a question that's been bugging me for quite a while: It seems that it would be impossible to create a program which generates it's source as output because you have a self-referential system and will end up with an infinite recursion. I guess this presumes that you can't go out to the operating system to do things, since then it's not a strictly self-refer- ential system. I note that this contest doesn't prevent you from going to the operating system, it simply prevents you from opening the source file and printing it out (that rule was in part of the text I deleted...sorry). But: Isn't it impossible for a C program to replicate itself if it doesn't access the operating system (other than printing to stdout)? The question of whether it can be done while *using* the OS should come out of this contest so I'll wait patiently... By the way, please forgive me if this all seems trivially true/false...but please enlighten me. Brian R. Gilstrap Southwestern Bell Telephone One Bell Center Rm 17-G-4 ...!ames!killer!texbell!sw1e!uucibg St. Louis, MO 63101 ...!bellcore!texbell!sw1e!uucibg (314) 235-3929 #include <std_disclaimers.h>
geoff@tom.harvard.edu (Geoff Clemm) (03/26/89)
Here is an old self-replicating program I did a while back ... no attempt was made to make the program short. It may not be ansi but it should be trivial to make it so. ------------ cut here ----------------- char *text = "\n\ #include <stdio.h>\n\ main()\n\ {\n\ (void)printf(\"char *text =\\n\\\"\");\n\ out(text);\n\ (void)printf(\"\\\";\\n%s\\n\", text); exit(0);};\n\ \n\ out(s)\n\ char *s;\n\ {\n\ while (*s != 0) {\n\ if (*s == '\\n') (void)printf(\"\\\\n\\\\\");\n\ if (*s == '\\\\' || *s == '\"') (void)putchar('\\\\');\n\ (void)putchar(*s); s += 1; };};\n\ "; #include <stdio.h> main() { (void)printf("char *text =\n\""); out(text); (void)printf("\";\n%s\n", text); exit(0);}; out(s) char *s; { while (*s != 0) { if (*s == '\n') (void)printf("\\n\\"); if (*s == '\\' || *s == '"') (void)putchar('\\'); (void)putchar(*s); s += 1; };}; ------------ cut here ----------------- Geoff Clemm geoff@harvard.harvard.edu
jdchrist@watcgl.waterloo.edu (Dan Christensen) (03/27/89)
In article <12144@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes: >*** Portable Self-Replicating C Contest *** > >Rules: >4. The source must use only the ISO 646 character set, using trigraphs as > needed. > >(You might not like trigraphs, but it makes the puzzle more challenging.) > >Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint Sorry if this is trivial, but what is the ISO 646 character set and what are trigraphs? ---- Dan Christensen, Computer Graphics Lab, jdchrist@watcgl.uwaterloo.ca University of Waterloo, Waterloo, Ont. jdchrist@watcgl.waterloo.edu
gwyn@smoke.BRL.MIL (Doug Gwyn ) (03/27/89)
In article <1417@sw1e.UUCP> uucibg@sw1e.UUCP (Brian Gilstrap [5-3929]) writes: >It seems that it would be impossible to create a program which generates it's >source as output because you have a self-referential system and will end up >with an infinite recursion. Nope. If you try to make that line of reasoning precise you'll find gaps in the logic. In fact self-replicating systems can be quite small. Self-reference need not imply infinite recursion, and self-replication need not imply self-reference.
utoddl@ecsvax.UUCP (Todd M. Lewis) (03/27/89)
In article <9929@smoke.BRL.MIL>, gwyn@smoke.BRL.MIL (Doug Gwyn ) writes: > In article <1417@sw1e.UUCP> uucibg@sw1e.UUCP (Brian Gilstrap [5-3929]) writes: > >It seems that it would be impossible to create a program which generates it's > >source as output because you have a self-referential system and will end up > >with an infinite recursion. > > Nope. If you try to make that line of reasoning precise you'll find > gaps in the logic. In fact self-replicating systems can be quite small. > Self-reference need not imply infinite recursion, and self-replication > need not imply self-reference. That's a bit theoretical. If it doesn't convince you, try thinking about it this way. Most programs that will be submitted will use some form of put or printf call, yet the source to printf will not be printed. The point is that it could be. Think of the token "printf" as expanding to the entire source to printf. The program would still work, but the string produced by the program would have to be longer. That may make it more tricky, but not any harder, er, theoretically. Note also that this printf need not use the OS, but could go right to the hardware so that it could work without any OS at all. (How it would have gotten into the machine is another question.) Now that the magic is done, consider this: this program will only work on specific hardware. You have to consider this because each op-code is in fact "expanded" to the hardware design that supports it, just as printf is expanded on a higher level. Programs can only reproduce themselves in a suitable environment. (That goes for lizards, fish, people, and other self-replicating systems.) So work back from this perspective to our self-replicating program and you will see that the OS and library routines and the hardware all work together to create an environment in which our programs can "live" (dont take this too far..) and in which some programs can reproduce. You are right in thinking that programs can't really reproduce without some greater reference capabilities. Self-replicating systems rely heavily on building on the structure of their environments, whether that means computer op-codes and address spaces or atoms and the Universe. The "meaning" of our programms' op-codes derives from the hardware. Now, about that entropy thingy ... :) _____ | Todd M. Lewis Disclaimer: If you want my employer's ||\/| utoddl@ecsvax.uncecs.edu ideas, you'll have to || || _buy_ them. | || |___ (Never write a program bigger than your screen.)
hearn@claris.com (Bob Hearn) (03/28/89)
From article <1417@sw1e.UUCP>, by uucibg@sw1e.UUCP (3929]): > In article <12144@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes: >>Well, it happens that I was going to post this anyway... >> >>*** Portable Self-Replicating C Contest *** >> >>Rules: >>0. The output of the program must be its own source code. > > [ More of the rules of the contest ] > >>Followups to comp.std.c only. >> >>Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint >>(Why 72? The last eight columns are reserved for possible addition of a card >>sequence number at some future date.) > > This is a good opportunity for me to ask a question that's been bugging me for > quite a while: > > It seems that it would be impossible to create a program which generates it's > source as output because you have a self-referential system and will end up > with an infinite recursion. I guess this presumes that you can't go out to > the operating system to do things, since then it's not a strictly self-refer- > ential system. I note that this contest doesn't prevent you from going to the > operating system, it simply prevents you from opening the source file and > printing it out (that rule was in part of the text I deleted...sorry). But: > > Isn't it impossible for a C program to replicate itself if it doesn't access > the operating system (other than printing to stdout)? The question of whether > it can be done while *using* the OS should come out of this contest so I'll > wait patiently... > > By the way, please forgive me if this all seems trivially true/false...but > please enlighten me. > > > Brian R. Gilstrap Southwestern Bell Telephone > One Bell Center Rm 17-G-4 ...!ames!killer!texbell!sw1e!uucibg > St. Louis, MO 63101 ...!bellcore!texbell!sw1e!uucibg > (314) 235-3929 > #include <std_disclaimers.h>
hearn@claris.com (Bob Hearn) (03/28/89)
Oops... sorry. Stupid mailer sent the wrong file. One more time... > Isn't it impossible for a C program to replicate itself if it doesn't access > the operating system (other than printing to stdout)? The question of whether > it can be done while *using* the OS should come out of this contest so I'll > wait patiently... > > By the way, please forgive me if this all seems trivially true/false...but > please enlighten me. No, it's not impossible... the basic idea is to write a program that means the equivalent of: Write the following quotation, then write it again, quoted: "Write the following quotation, then write it again, quoted:" Bob Hearn hearn@claris.com
dhesi@bsu-cs.UUCP (Rahul Dhesi) (03/28/89)
In article <9201@claris.com> hearn@claris.com (Bob Hearn) writes:
Write the following quotation, then write it again, quoted: "Write
the following quotation, then write it again, quoted:"
Tell me to tell you to do what I just did.
--
Rahul Dhesi UUCP: <backbones>!{iuvax,pur-ee}!bsu-cs!dhesi
ARPA: dhesi@bsu-cs.bsu.edu
huxtable@kuhub.cc.ukans.edu (Kathryn Huxtable) (04/01/89)
char a[] = "char a[] = %c%s%c; main() { printf( a, 34, a, 34 ); }"; main() { printf( a, 34, a, 34 ); } Of course, all this has to be on one long line. Kathryn Huxtable huxtable@kuhub.cc.ukans.edu
karl@haddock.ima.isc.com (Karl Heuer) (04/08/89)
I've received several contest entries by mail. Our gateway has been flakey, so if you haven't gotten a response, try again. I reply to each entry. My reply has almost become a form letter, since I keep seeing the same mistakes. So I guess it's time for a followup. Here are the rules from my original article: >0. The output of the program must be its own source code. >1. It may not be safely assumed that the source code resides in an openable > file at runtime. >2. The program must be written in Strictly Conforming ANSI C. >3. The program must return a proper exit status, indicating whether or not > its output-calls succeeded. >4. The source must use only the ISO 646 character set, using trigraphs as > needed. >5. No source line may exceed 72 characters. >6. There will be two winners: the first correct program to arrive at my site, > and the shortest (measured in source characters, including newlines). The > contest ends on 23-Apr-1989. No prizes will be awarded. Note rule 3. Output calls can fail (e.g. disk full); the program must detect this condition and return the value EXIT_FAILURE to the execution environment. This constant is defined in <stdlib.h>, which must therefore be included. Note rule 4 especially. The nine characters # ^ ~ { | } [ \ ] are not allowed to appear in the source; you must use the trigraph equivalents ??= ??' ??- ??< ??! ??> ??( ??/ ??) instead. Only one entrant has observed this rule so far! I should also point out that assumptions such as '"'==34 are an artifact of the ASCII character set, which a strictly conforming program may not rely on. I use the enclosed shell script as a preliminary test. If you don't have <stdlib.h>, or if your compiler doesn't understand trigraphs, you might find it useful. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint ________ #!/bin/sh # Accepts a program by file name, or on standard input. PATH=/bin:/usr/bin:/usr/ucb; export PATH E=2; T=/tmp/$$self.d; trap 'rm -rf $T; trap 0; exit $E' 0 1 2 3 15 mkdir $T; cat $1 >$T/self.src; cd $T if [ `tr -cd '#^~[\\]{|}' <self.src | wc -c` != 0 ]; then echo 'bad character set'; E=1 fi awk '{if (length>72) {print "too wide"; exit 1}}' <self.src || E=1 if grep printf <self.src >/dev/null; then if egrep '\.\.\.|stdio' <self.src >/dev/null; then :; else echo 'printf not declared'; E=1 fi fi sed -e "s/??=/#/g" -e "s/??'/^/g" -e "s/??!/|/g" -e "s/??-/~/g" \ -e "s/??</{/g" -e "s/??>/}/g" -e "s/??(/[/g" -e "s/??)/]/g" \ -e 's;??/;\\;g' <self.src >self.c cat <<\! >stdlib.h #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 ! ${CC-/bin/cc} -I. self.c -o self && ./self | cmp - self.src || E=1 if [ "$E" = "2" ]; then echo 'looks good'; E=0; fi
huxtable@kuhub.cc.ukans.edu (Kathryn Huxtable) (04/08/89)
Jerry Schwarz <jss@ulysses.att.com> writes (through E-Mail): > In article <4244@kuhub.cc.ukans.edu> you write: > >char a[] = "char a[] = %c%s%c; main() { printf( a, 34, a, 34 ); }"; main() { > >printf( a, 34, a, 34 ); } > Not portable. The code for " does not have to be 34. I answered with a variant of the following: Aw....You're right, of course. No one has pointed out that it doesn't print a trailing newline, either. Actually, Stan Switzer at sjs@bellcore.whatever_it_is has made a study of what he calls "Quine" programs. He calls them Quine programs after Willard van Orman Quine, who said: "Yields falsehood when preceded by itself in quotations," yields falsehood when preceded by itself in quotations. Stan had a program when he was a student here at KU (1981) which was extremely clean. It wasn't particularly terse, though. I say clean, because the method generalized to a program of arbitrary complexity. -Kathryn Huxtable huxtable@kuhub.cc.ukans.edu Reconstructing from memory: ------------------------- Cut here ------------------------- /* * Quine -- Self replicating program. * * Just compile, link and go. * * Written by Kathryn Huxtable, after a memory of a similar * program written by Stan Switzer. */ #include <stdio.h> char *first[] = { "/*", " * Quine -- Self replicating program.", " *", " * Just compile, link and go.", " *", " * Written by Kathryn Huxtable, after a memory of a similar", " * program written by Stan Switzer.", " */", "", "#include <stdio.h>", NULL }; char *last[] = { "/*", " * Print a vector of lines one line at a time.", " */", "", "print_norm( char *lines[] )", "{", " int i;", "", " for( i = 0; lines[i] != NULL; i++ )", " printf( \"%s\\n\", lines[i] );", "", "} /* print_norm */", "", "", "/*", " * Print a quoted string, enclosing it in quotes", " * and escaping quote and backslash.", " */", "", "puts_quoted( char *str )", "{", " int i;", "", " putchar( '\"' );", "", " for( i = 0; str[i] != '\\0'; ++i ) {", " if( str[i] == '\"' || str[i] == '\\\\' )", " putchar( '\\\\' );", " putchar( str[i] );", " }", "", " putchar( '\"' );", "", "} /* puts_quoted */", "", "", "/*", " * Print a vector of lines, in the format", " * in which it was declared.", " */", "", "print_quoted( char *name, char *lines[] )", "{", " int i;", "", " printf( \"char *%s[] = {\\n\", name );", "", " for( i = 0; lines[i] != NULL; i++ ) {", " printf( \" \" );", " puts_quoted( lines[i] );", " printf( \",\\n\" );", " }", "", " printf( \" NULL\\n\" );", " printf( \"};\\n\" );", " printf( \"\\n\" );", "", "} /* print_quoted */", "", "", "/*", " * Print a copy of my source, reconstructed", " * from the vectors first and last.", " */", "", "main()", "{", " print_norm( first );", " printf( \"\\n\" );", " print_quoted( \"first\", first );", " print_quoted( \"last\", last );", " printf( \"\\n\" );", " print_norm( last );", "", "} /* main */", NULL }; /* * Print a vector of lines one line at a time. */ print_norm( char *lines[] ) { int i; for( i = 0; lines[i] != NULL; i++ ) printf( "%s\n", lines[i] ); } /* print_norm */ /* * Print a quoted string, enclosing it in quotes * and escaping quote and backslash. */ puts_quoted( char *str ) { int i; putchar( '"' ); for( i = 0; str[i] != '\0'; ++i ) { if( str[i] == '"' || str[i] == '\\' ) putchar( '\\' ); putchar( str[i] ); } putchar( '"' ); } /* puts_quoted */ /* * Print a vector of lines, in the format * in which it was declared. */ print_quoted( char *name, char *lines[] ) { int i; printf( "char *%s[] = {\n", name ); for( i = 0; lines[i] != NULL; i++ ) { printf( " " ); puts_quoted( lines[i] ); printf( ",\n" ); } printf( " NULL\n" ); printf( "};\n" ); printf( "\n" ); } /* print_quoted */ /* * Print a copy of my source, reconstructed * from the vectors first and last. */ main() { print_norm( first ); printf( "\n" ); print_quoted( "first", first ); print_quoted( "last", last ); printf( "\n" ); print_norm( last ); } /* main */
dhesi@bsu-cs.bsu.edu (Rahul Dhesi) (04/09/89)
In article <12593@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes: >The nine characters # ^ ~ { | } [ \ ] are not >allowed to appear in the source; you must use the trigraph equivalents ??= >??' ??- ??< ??! ??> ??( ??/ ??) instead. (I'm ??xorry, my ??x key i??x broken, ??xo I'm ??xub??xtituting the trigraph ??x in it??x place.) I'm curiou??x to know: What i??x the purpo??xe of the rule above? All it will do i??x make ??xubmitted program??x harder to read, and nearly impo??x??xible to make ??xen??xe of in a ca??xual ??xcan. -- Rahul Dhesi <dhesi@bsu-cs.bsu.edu> UUCP: ...!{iuvax,pur-ee}!bsu-cs!dhesi
friedl@vsi.COM (Stephen J. Friedl) (04/10/89)
In article <6647@bsu-cs.bsu.edu>, dhesi@bsu-cs.bsu.edu (Rahul Dhesi) writes: > > (I'm ??xorry, my ??x key i??x broken, ??xo I'm ??xub??xtituting the > trigraph ??x in it??x place.) > > I'm curiou??x to know: What i??x the purpo??xe of the rule above? All > it will do i??x make ??xubmitted program??x harder to read, and nearly > impo??x??xible to make ??xen??xe of in a ca??xual ??xcan. I really like Rahul's point here and wish to talk to him about it, but mail to "dhe??xi@b??xu-c??x.b??xu.edu" keeps bouncing. Any ideas? Steve :-) -- Stephen J. Friedl / V-Systems, Inc. / Santa Ana, CA / +1 714 545 6442 3B2-kind-of-guy / friedl@vsi.com / {attmail, uunet, etc}!vsi!friedl "I do everything in software, even DMA" - Gary W. Keefe (garyk@telxon)
karl@haddock.ima.isc.com (Karl Heuer) (04/11/89)
In article <6647@bsu-cs.bsu.edu> dhesi@bsu-cs.UUCP (Rahul Dhesi) writes: >In article <12593@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) >writes [that contest entries must use trigraphs] > >I'm curious to know: What is the purpose of the rule above? All >it will do is make submitted programs harder to read, and nearly >impossible to make sense of in a casual scan. It makes the problem more challenging. Note that a program which satisfies all of the rules except this one is not self-reproducing after a naive conversion to trigraphs, because `printf("??=")' will output `#', not `??='. (One correct fix is to use `printf("?\?=")', but since `\' is itself a trigraphable character, this must be written `printf("???/?=")'!) Yes, it's hard to read, but one pass through a detrigraphing sed script will fix that, as I did with your text before quoting it above. Karl W. Z. Heuer (ima!haddock!karl or karl@haddock.isc.com), The Walking Lint
diamond@diamond.csl.sony.junet (Norman Diamond) (04/13/89)
In article <12629@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes: [about the rule that contest entries must use trigraphs] > It makes the problem more challenging. Note that a program which satisfies > all of the rules except this one is not self-reproducing after a naive > conversion to trigraphs, because `printf("??=")' will output `#', not `??='. Yes indeed, such conversions take place even in strings. I wonder how such programs execute in environments that don't have a '#' character. Norman Diamond, Sony Computer Science Lab (diamond%csl.sony.jp@relay.cs.net) The above opinions are my own. | Why are programmers criticized for If they're also your opinions, | re-inventing the wheel, when car you're infringing my copyright. | manufacturers are praised for it?
dhe??xi@b??xu-c??x.b??xu.edu (Rahul Dhe??xi) (04/14/89)
In article <12629@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes: >(One correct fix is to use `printf("?\?=")', but since `\' is itself a >trigraphable character, this must be written `printf("???/?=")'!) ^^^^^^ This seems awfully difficult for a lexical analyzer to handle, and perhaps illustrates my point again. (Isn't ? itself a trigraph character, at least when ambiguity requires it?) As a sporting gesture, would you be willing to repost the contest rules, this time using trigraphs only in place of the offending symbols? If that doesn't make my point, nothing will. Rahul Dhe??xi <dhe??xi@b??xu-c??x.b??xu.edu> UUCP: ...!{iuvax,pur-ee}!b??xu-c??x!dhe??xi
david@dhw68k.cts.com (David H. Wolfskill) (04/16/89)
In article <6756@bsu-cs.bsu.edu> dhesi@bsu-cs.bsu.edu (Rahul Dhesi) writes: >In article <12629@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) >writes: >>(One correct fix is to use `printf("?\?=")', but since `\' is itself a >>trigraphable character, this must be written `printf("???/?=")'!) > ^^^^^^ >This seems awfully difficult for a lexical analyzer to handle, and >perhaps illustrates my point again. (Isn't ? itself a trigraph >character, at least when ambiguity requires it?) No, '?' is *not* representable by a trigraph sequence. Section 2.2.1.1 ("Trigraph Sequences") reads (in the May 13, 1988 draft): -=-=-=-=-=-=-=-=-=-=-= All occurrences in a source file of the following sequences of three characters (called *trigraph sequences*[5]) are replaced with the corresponding single character. ??= # ??( [ ??/ \ ??) ] ??' ^ ??< { ??! | ??> } ??- ~ No other trigraph sequences exist. Each ? that does not begin one of the trigraphs listed above is not changed. Example The following source line printf("Eh???/n"); becomes (after replacement of the trigraph sequence ??/) printf("Eh?\n"); ----- 5. The trigraph sequences enable the input of characters that are not defined in the ISO 646-1983 Invariant Code Set, which is a subset of the seven-bit ASCII code set. -=-=-=-=-=-=-=-=-=-=-= >As a sporting gesture, would you be willing to repost the contest >rules, this time using trigraphs only in place of the offending >symbols? If that doesn't make my point, nothing will. I think Karl's rules were clear enough. As to the trigraphs, I don't know of anyone who claims that they are aesthetically pleasing; some mechanism, however, needs to exist for representing characters that do not exist in an environment's character set (unless, of course, X3J11 had been willing to banish folks in such circumstances to a C-less existence). To quote Douglas Adams (note "Adams," not "Gwyn") "You were quite entitled to make any suggestions or protests at the appropriate time, you know." david -- David H. Wolfskill uucp: ...{spsd,zardoz,felix}!dhw68k!david InterNet: david@dhw68k.cts.com
karl@haddock.ima.isc.com (Karl Heuer) (04/28/89)
# Compilation Copyright (c) 1989 by Karl Heuer. I don't care what you do with # this article, but the right to resubmit these programs to the IOCCC remains # with the original authors. #!/bin/sh : run this file through sh to unbundle : README scjones diomidis cat <<\--------cut-------- >README Well, the contest is over, and here are the results. For those of you who missed the beginning of this, the challenge was to write a self-reproducing program which is strictly pANS-conforming (to the letter!), had a proper exit status, was no more than 72 characters wide, and used only the characters in ISO 646 (using trigraphs as needed). (I should also have had a rule against using any obsolescent feature, but I didn't think of that in time.) To the best of my knowledge, the two enclosed programs were the only entries that satisfied all of the rules. If someone still manages to spot a flaw in either of these, I'll be impressed. The Early Bird Winner was Larry Jones <scjones@sdrc.UU.NET>. His entry demonstrated that I should have said "columns" instead of "characters" in the width requirement (he used tabs), but that's not important. (If I'd insisted on rephrasing the rule, a simple `tr \\11 \\40' would have fixed his entry.) Note that he didn't resort to printf trickery to construct trigraphs for output; he just used the straightforward notation like `???/?/'. I like that. The winner for shortest program was Diomidis Spinellis <ecrcvax!diomidis>, at 499 characters. Interestingly enough, there was still some slack here; it would still be strictly conforming to drop the `int' declaration from main() and to use 0 rather than EXIT_SUCCESS, for example. This entry deserves a special award for the clever use of the `#' operator to do most of the work; that possibility hadn't occurred to me. (It should also be pointed out that this program cannot be directly tested with gcc 1.32, because of a bug in the gnu preprocessor that was discovered when he submitted an earlier attempt.) A few other entries were only slightly flawed, and probably could have been fixed if the deadline hadn't expired first. I apologize for the sometimes long turnaround time on reporting such flaws; besides my having other business to take care of, we had severe problems with our mail gateway. (I considered extending the duration of the contest as a sporting gesture, but I'm getting rather tired of this. If you want to improve on these, you can do it without my help.) When I first thought about this puzzle, I was thinking in terms of the simple program (shown here folded) char*f="char*f=%c%s%c;main(){printf(f,34,f,34,10);}%c";\ main(){printf(f,34,f,34,10);} and wondered how much effort it would be to make it portable. After fixing the hardcoded ASCII values, entrigraphing, adding required headers, and checking the exit status, the program had grown to: ??=include<stdlib.h> ??=include<stdio.h> char*f="?%c=include<stdlib.h>%c?%c=include<stdio.h>%cchar*f=%c%s%c,\ t='?',n='?%c/n',q='%c';main()?%c<exit(printf(f,t,n,t,n,q,f,q,t,q,t,\ t,n)<0?EXIT_FAILURE:0);?%c>%c",t='?',n='??/n',q='"';main()??<exit(p\ rintf(f,t,n,t,n,q,f,q,t,q,t,t,n)<0?EXIT_FAILURE:0);??> and I still needed a way to break up that 255-character third line. At this point I gave up on the single-printf approach, though I'd be interested to hear if anybody can salvage it. --------cut-------- cat <<\--------cut-------- >scjones static const char *foo??(??) = ??< "??=include <stdio.h>??/n", "??=include <stdlib.h>??/n", "??/n", "void out(q, f)??/n", " const char *q;??/n", " int f;??/n", " ??<??/n", " for (;; q++) ??<??/n", " switch (*q) ??<??/n", " case 0:??/n", " if (f) fputs(??/"??/??/??/",??/??/n??/??/??/"??/", stdout);??/n", " return;??/n", " case '??=':??/n", " fputs(??/"???/??/?=??/", stdout);??/n", " break;??/n", " case '??<':??/n", " fputs(??/"???/??/?<??/", stdout);??/n", " break;??/n", " case '??>':??/n", " fputs(??/"???/??/?>??/", stdout);??/n", " break;??/n", " case '??(':??/n", " fputs(??/"???/??/?(??/", stdout);??/n", " break;??/n", " case '??)':??/n", " fputs(??/"???/??/?)??/", stdout);??/n", " break;??/n", " case '??/??/??/??/':??/n", " if (f) fputs(??/"???/??/?/??/", stdout);??/n", " fputs(??/"???/??/?/??/", stdout);??/n", " break;??/n", " case '??/??/n':??/n", " if (f) fputs(??/"???/??/?/n??/", stdout);??/n", " else putchar(*q);??/n", " break;??/n", " case '??/"':??/n", " if (f) fputs(??/"???/??/?/??/??/??/"??/", stdout);??/n", " else putchar(*q);??/n", " break;??/n", " default:??/n", " putchar(*q);??/n", " ??>??/n", " ??>??/n", " ??>??/n", "??/n", "main()??/n", " ??<??/n", " const char **p;??/n", "??/n", " out(??/"static const char *foo??(??) = ??<??/??/n??/", 0);??/n", " out(??/"??/??/??/"??/", 0);??/n", " for (p = foo; **p; p++) out(*p, 1);??/n", " out(??/"??/??/??/"??>;??/??/n??/", 0);??/n", " for (p = foo; **p; p++) out(*p, 0);??/n", " exit(ferror(stdout) ? EXIT_FAILURE : EXIT_SUCCESS);??/n", " ??>??/n", ""??>; ??=include <stdio.h> ??=include <stdlib.h> void out(q, f) const char *q; int f; ??< for (;; q++) ??< switch (*q) ??< case 0: if (f) fputs("??/",??/n??/"", stdout); return; case '??=': fputs("???/?=", stdout); break; case '??<': fputs("???/?<", stdout); break; case '??>': fputs("???/?>", stdout); break; case '??(': fputs("???/?(", stdout); break; case '??)': fputs("???/?)", stdout); break; case '??/??/': if (f) fputs("???/?/", stdout); fputs("???/?/", stdout); break; case '??/n': if (f) fputs("???/?/n", stdout); else putchar(*q); break; case '"': if (f) fputs("???/?/??/"", stdout); else putchar(*q); break; default: putchar(*q); ??> ??> ??> main() ??< const char **p; out("static const char *foo??(??) = ??<??/n", 0); out("??/"", 0); for (p = foo; **p; p++) out(*p, 1); out("??/"??>;??/n", 0); for (p = foo; **p; p++) out(*p, 0); exit(ferror(stdout) ? EXIT_FAILURE : EXIT_SUCCESS); ??> --------cut-------- cat <<\--------cut-------- >diomidis ??=include<stdlib.h> ??=include<stdio.h> ??=include<string.h> ??=define P(x)char*w=??=x;x P(p(char q) ??<if(putchar(q)==EOF)exit(EXIT_FAILURE);??> o(char*s) ??<char*q;char*t="??<??>??=??/??/??(??)";for(;*s;s++)if(q=strchr(t,*s)) ??<o("??");p("<>=/()"??(q-t??));??>else if(!strchr("'Pc<",s??(1??))&&*s==' ')p('??/n');else p(*s);??> int main() ??<o("??=include<stdlib.h>??/n??=include<stdio.h>??/n??=include<str" "ing.h>??/n??=define P(x)char*w=??=x;x??/nP("); o(w);o(")??/n");exit(EXIT_SUCCESS);??>) --------cut-------- exit 0
jv@mh.nl (Johan Vromans) (05/01/89)
... And in a few years from now we'll all talk about C as "that language with all those funny ?? in it" ... Remember (((((lisp)))))? Johan -- Johan Vromans jv@mh.nl via european backbone (mcvax) Multihouse Automatisering bv uucp: ..!{mcvax,hp4nl}!mh.nl!jv Doesburgweg 7 phone: +31 1820 62944 2803 PL Gouda - The Netherlands fax: +31 1820 62500