[comp.lang.pascal] Self-replicating programs

levison@qucis.UUCP (Mike Levison) (12/22/87)

This is probably more than you ever wanted to know on self-
replicating programs:

         Self-Reproducing Program (Pascal version)

The  basic idea is  to create within the program an array of
characters  which consists  of the whole  program EXCEPT for
the  assignments which  initialize  the array. The  array is
then used once  for printing the basic program, and a second
for printing the assignments.

Ignore for  a moment  two minor annoyances: line layout, and
the fact  that one cannot  assign or output quotemarks using
c[i]:= ''' or write(''').  Both can be overcome trivially at
the  expense of clarity. Then the program is as follows (the
comments are not part of it):

  program hermaph (input, output);

    const len = ???;        {len is the number of chars in this program
                            without the assignments;  mid is the number
                            up to the assignments. len may be 357, say}
          mid = ???;

    var chrom : array [1..len] of char;
            i : integer;

  begin

    chrom[1]:= 'p';
    chrom[2]:= 'r';
    chrom[3]:= 'o';
    chrom[4]:= 'g';
    ...                     {and another 349 or so}
    chrom[354]:= 'e';
    chrom[355]:= 'n';
    chrom[356]:= 'd';
    chrom[357]:= '.';

    for i:= 1 to mid do write(chrom[i]);

    for i:= 1 to len do
      begin
        writeln("chrom[");
        write(i);
        write("]:= '");
        write(chrom[i]);
        write("';")
      end;

    for i:= mid + 1 to len do write(chrom[i]);
    writeln;

  end.


Note the  three  for-loops. The first and third simply print
the contents  of chrom, and  so  produce the  first and last
parts  of the program.  The second uses chrom in a different
way to generate  the 357 assignment statements. (There is an
interesting analogy with a cell; the chromosome is used once
to construct the body of the cell, and in a different way to
replicate itself.)

In a  language which allows  the  assignment and printing of
whole  strings,  the  body  of  the  above program  is  more
concise, something like:

  {A}
  chrom1:= "program herm   ...  {A}";
  chrom2:= "{B}  ...  end.";

  {B}
  write(chrom1);
  write("chrom1:= &"); write (chrom1) ; write ("&;");
  write("chrom2:= &"); write (chrom2) ; write ("&;");
  write(chrom2)

where  &  is really  supposed to be " (the quotemark problem
again).

As to  the annoyances, the quotemark problem can be bypassed
by storing integers (the ASCII values) instead of chars, and
using chr(chrom[i]) for output. Or one can use & to denote "
in strings, and replace 'write' by a procedure which behaves
like the usual one but prints " when it sees &.

If we want  the  offspring to  be identical to the parent in
layout,  we  could   use   a  special  character  to  denote
'newline',  and  again declare a  new  'write' to  interpret
this.  But  this is  not  really necessary.  Call  the above
program h,  and its output son-of-h. Then certainly son-of-h
may   differ  in  layout  from  h,  but  son-of-son-of-h  is
identical to son-of-h.  So the true self-reproducing program
is son-of-h, rather than h itself.

Finally, typing  the  357 (??)  assignments  in  the  Pascal
version of  h would  be very tedious.  But  this too  can be
avoided. We create  a  datafile shell-of-h,  which is h with
the  assignments omitted. And we create a program mother-of-
h,  similar to  h  but  with  chrom  initialized  by reading
characters from a datafile. Now mother-of-h reads shell-of-h
to create h  as output (and this h will already be identical
to its child in layout.)

As a matter of interest, a discussion on this topic, without
a program or programming language being involved occurred in
the work of John von Neumann on self-reproducing automata in
the early fifties.

djones@megatest.UUCP (Dave Jones) (12/26/87)

in article <52@qucis.UUCP>, levison@qucis.UUCP (Mike Levison) says:
> 
> 
> 
> This is probably more than you ever wanted to know on self-
> replicating programs:
> 
>          Self-Reproducing Program (Pascal version)
> 
> The  basic idea is  to create within the program an array of
> characters  which consists  of the whole  program EXCEPT for
> the  assignments which  initialize  the array. The  array is
> then used once  for printing the basic program, and a second
> for printing the assignments.
> 
> Ignore for  a moment  two minor annoyances: line layout, and
> the fact  that one cannot  assign or output quotemarks using
> c[i]:= ''' or write(''').  Both can be overcome trivially at
> the  expense of clarity. Then the program is as follows (the
> comments are not part of it):

[...]



The "quotemark" problem is the only hard problem. How do you make
this program character-set independant?  (The one I posted will
work just as well on an EBCDIC machine as on an ASCII machine.
This posting does not contain everything I want ot know on
self-replicating programs.

		Dave Jones
		Megatest Corp.
		880 Fox Lane
		San Jose, CA.
		95131

		(408) 437-9700 Ext 3227
		UUCP: ucbvax!sun!megatest!djones
		ARPA: megatest!djones@riacs.ARPA

luc@kulcs.UUCP (Luc Van Braekel) (12/29/87)

In article <188@goofy.megatest.UUCP>, djones@megatest.UUCP (Dave Jones) writes:
> The "quotemark" problem is the only hard problem. How do you make
> this program character-set independant?  (The one I posted will
> work just as well on an EBCDIC machine as on an ASCII machine.
> This posting does not contain everything I want ot know on
> self-replicating programs.
The quotemark problem is not so difficult to solve.  Here is a
slightly modified version of the program I posted some time ago.  This
version is character-set independant.  Again, this is an ugly but very
short Pascal program that doesn't use external files etc.  At least
one thing that's shorter in Pascal than in C ! :-)

program self (output);  const q = '''';                    
var i,j: integer;                                          
    a: array[1..8] of packed array[1..59] of char; begin   
  a[1] := 'program self (output);  const q = '''''''';                    ';
  a[2] := 'var i,j: integer;                                          ';
  a[3] := '    a: array[1..8] of packed array[1..59] of char; begin   ';
  a[4] := 'for i := 1 to 3 do writeln(a[i]);                          ';
  a[5] := 'for i := 1 to 8 do begin write(''  a['',i:0,''] := '',q);      ';
  a[6] := 'for j := 1 to 59 do begin write(a[i][j]);if a[i][j]=q      ';
  a[7] := 'then write(a[i][j]) end; writeln(q,'';'') end;               ';
  a[8] := 'for i := 4 to 8 do writeln(a[i]) end.                      ';
for i := 1 to 3 do writeln(a[i]);                          
for i := 1 to 8 do begin write('  a[',i:0,'] := ',q);      
for j := 1 to 59 do begin write(a[i][j]);if a[i][j]=q      
then write(a[i][j]) end; writeln(q,';') end;               
for i := 4 to 8 do writeln(a[i]) end.                      

+-----------------------------------+------------------------------------+
| Name   : Luc Van Braekel          |  Katholieke Universiteit Leuven    |
| UUCP   : luc@kulcs.UUCP           |  Department of Computer Science    |
| BITNET : luc@blekul60.bitnet      |  Celestijnenlaan 200 A             |
| Phone  : +(32) 16 20 0656 x3563   |  B-3030 Leuven (Heverlee)          |
| Telex  : 23674 kuleuv b           |  Belgium                           |
+-----------------------------------+------------------------------------+