Add alt code to 1989/paul + format README.md
The alt code is based on the author's remarks: a trace routine had been provided but it was commented out. It offers for some rather fun output. The Makefile was updated accordingly. The README.md file has been typo and format fixed. The .gitignore file has been updated - added paul.alt.
This commit is contained in:
1 parent
d1cf700126
commit
887417c6ab
5 files changed
+113
-49
No files matched your search
@@ -1,3 +1,4 @@
|
|||||||
paul
|
paul
|
||||||
|
paul.alt
|
||||||
paul.orig
|
paul.orig
|
||||||
prog.orig
|
prog.orig
|
||||||
+2
-2
@@ -114,8 +114,8 @@ OBJ= ${PROG}.o
|
|||||||
DATA=
|
DATA=
|
||||||
TARGET= ${PROG}
|
TARGET= ${PROG}
|
||||||
#
|
#
|
||||||
ALT_OBJ=
|
ALT_OBJ= ${PROG}.alt.o
|
||||||
ALT_TARGET=
|
ALT_TARGET= ${PROG}.alt
|
||||||
|
|
||||||
|
|
||||||
#################
|
#################
|
||||||
|
|||||||
+71
-46
@@ -1,10 +1,6 @@
|
|||||||
# Most complex algorithm
|
# Most complex algorithm
|
||||||
|
|
||||||
Paul E. Black\
|
Paul E. Black\
|
||||||
CIRRUS LOGIC, Inc.\
|
|
||||||
1463 Centre Pointe Dr.\
|
|
||||||
Milpitas, CA\
|
|
||||||
95035\
|
|
||||||
US
|
US
|
||||||
|
|
||||||
## To build:
|
## To build:
|
||||||
@@ -13,6 +9,8 @@ US
|
|||||||
make all
|
make all
|
||||||
```
|
```
|
||||||
|
|
||||||
|
There is an alternate version with a trace routine that the author had commented
|
||||||
|
out. See [alternate code](#alternate-code) below for more details.
|
||||||
|
|
||||||
## Try:
|
## Try:
|
||||||
|
|
||||||
@@ -20,17 +18,43 @@ make all
|
|||||||
./paul
|
./paul
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Alternate code:
|
||||||
|
|
||||||
|
This version was described by the author like:
|
||||||
|
|
||||||
|
> I could have squeezed the program under 1024 bytes without the
|
||||||
|
trace subroutine, but I felt it was important for understanding
|
||||||
|
the program. Besides it is fun to watch the tape zooming back
|
||||||
|
and forth as the program runs. A much better debugger or trace
|
||||||
|
could easily be added.
|
||||||
|
|
||||||
|
#### To build:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make alt
|
||||||
|
```
|
||||||
|
|
||||||
|
#### To use:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./paul.alt
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## Judges' remarks:
|
## Judges' remarks:
|
||||||
|
|
||||||
The original source contained a long line which caused many
|
The author's comments is a detailed program explanation and spoiler. If you
|
||||||
mailers to barf. The original file may be re-constructed by
|
want a real challenge, don't read any further and try to understand the program
|
||||||
removing the trailing "\" on line 12 and joining lines 12 and
|
via the source.
|
||||||
13 together without a space.
|
|
||||||
|
|
||||||
WHAT FOLLOWS IS A DETAILED PROGRAM EXPLANATION AND SPOILER.
|
### Historical note:
|
||||||
IF YOU WANT A REAL CHALLENGE, DON'T READ ANY FURTHER AND TRY
|
|
||||||
TO UNDERSTAND THE PROGRAM VIA THE SOURCE.
|
|
||||||
|
|
||||||
|
The original source contained a long line which caused many mailers to barf.
|
||||||
|
The original file may be re-constructed by removing the trailing `\` on line 12
|
||||||
|
and joining lines 12 and 13 together without a space.
|
||||||
|
|
||||||
|
However as this is no longer a problem the trailing `\` has been restored in all
|
||||||
|
versions, both the original and the fixed for modern systems version.
|
||||||
|
|
||||||
## Author's remarks:
|
## Author's remarks:
|
||||||
|
|
||||||
@@ -43,69 +67,70 @@ natural to write incredibly obscure Turing programs.)
|
|||||||
|
|
||||||
If the program is invoked with an operand, the operand is used
|
If the program is invoked with an operand, the operand is used
|
||||||
as the Turing program. It includes a "trace" facility,
|
as the Turing program. It includes a "trace" facility,
|
||||||
subroutine r (commented out for obscurity), to help write and
|
subroutine `r` (commented out for obscurity), to help write and
|
||||||
debug Turing programs. Just the thing for some fun in a Theory
|
debug Turing programs. Just the thing for some fun in a Theory
|
||||||
of Computation class.
|
of Computation class.
|
||||||
|
|
||||||
The Turing machine tape is represented as a doubly linked list
|
The Turing machine tape is represented as a doubly linked list
|
||||||
of pointers. The forward and backward links are XOR'd together
|
of pointers. The forward and backward links are `XOR`ed together
|
||||||
and stored in one pointer. If we always keep one of the links
|
and stored in one pointer. If we always keep one of the links
|
||||||
on hand, we can recover the other link at any time. The
|
on hand, we can recover the other link at any time. The
|
||||||
variable q is the scan head (and a pointer at some tape cell),
|
variable `q` is the scan head (and a pointer at some tape cell),
|
||||||
and p is a "previous" link. The state of the tape is stored in
|
and `p` is a "previous" link. The state of the tape is stored in
|
||||||
the low order bit of the pointer. Since we always allocate an
|
the low order bit of the pointer. Since we always allocate an
|
||||||
even number of bytes, the low order bit carries no information
|
even number of bytes, the low order bit carries no information
|
||||||
(see portability below.) Memory representing a tape cell is
|
(see [portability](#portability) below.) Memory representing a tape cell is
|
||||||
allocated when the cell is first scanned. Thus the simulation
|
allocated when the cell is first scanned. Thus the simulation
|
||||||
begins with a tape effectively the size of virtual memory set
|
begins with a tape effectively the size of virtual memory set
|
||||||
to all zeros. Since a header can be added to any Turing
|
to all zeros. Since a header can be added to any Turing
|
||||||
program to write initial data and position the scan head, this
|
program to write initial data and position the scan head, this
|
||||||
is little loss of generality.
|
is little loss of generality.
|
||||||
|
|
||||||
The simulated Turing machine has a single tape with either an 1
|
The simulated Turing machine has a single tape with either a `1`
|
||||||
or a 0 in each cell. The Turing machine language format is a
|
or a `0` in each cell. The Turing machine language format is a
|
||||||
string of three bytes. The first byte is the current state.
|
string of three bytes. The first byte is the current state.
|
||||||
The second byte is the next state. (The last bit of states is
|
The second byte is the next state. (The last bit of states is
|
||||||
ignored, e.g., B and C are the same state, in an attempt to be
|
ignored, i.e., `B` and `C` are the same state, in an attempt to be
|
||||||
able to have interesting words in the program.) The third byte
|
able to have interesting words in the program.) The third byte
|
||||||
is composed of bits. Bit 1 (2&byte) is the symbol scanned,
|
is composed of bits. Bit `1` (`2&byte`) is the symbol scanned,
|
||||||
i.e. an instruction is selected for state and for a match with
|
i.e. an instruction is selected for state and for a match with
|
||||||
the symbol under the scan head. Bit 2 (4&byte) is the new
|
the symbol under the scan head. Bit `2` (`4&byte`) is the new
|
||||||
symbol to be written to the cell. Bit 3 (8&byte) is the
|
symbol to be written to the cell. Bit `3` (`8&byte`) is the
|
||||||
direction to move the scan head: 0 for left and 1 for right.
|
direction to move the scan head: `0` for left and `1` for right.
|
||||||
If bit 4 (16&byte) is true, the next character is sent to
|
If bit `4` (`16&byte`) is true, the next character is sent to
|
||||||
stdout. (I added this feature so programs could print
|
`stdout`. (I added this feature so programs could print
|
||||||
results.)
|
results.)
|
||||||
|
|
||||||
The Turing machine has next state `j` when it begins. The
|
The Turing machine has next state `j` when it begins. The
|
||||||
cycle is 1) exit if the state is `x`, 2) find the next
|
cycle is (1) exit if the state is `x`, (2) find the next
|
||||||
instruction (given the state and the character under the scan
|
instruction (given the state and the character under the scan
|
||||||
head). [The program string is searched forward for the next
|
head). (The program string is searched forward for the next
|
||||||
matching instruction. If the end of the string is reached, the
|
matching instruction. If the end of the string is reached, the
|
||||||
search begins again at the first of the string. Thus states
|
search begins again at the first of the string. Thus states
|
||||||
can be used as local labels in different places.] 3) change to
|
can be used as local labels in different places.) (3) change to
|
||||||
the next state, 4) print a character if indicated, 5) write the
|
the next state, (4) print a character if indicated, (5) write the
|
||||||
tape symbol, and 6) move the scan head. The cycle then repeats
|
tape symbol, and (6) move the scan head. The cycle then repeats
|
||||||
with step 1. A call to the trace routine is just before step
|
with step 1. A call to the trace routine is just before step
|
||||||
2, but is commented out.
|
2, but is commented out.
|
||||||
|
|
||||||
The following ROT13'ed text is a quick outline of the actual
|
### Quick outline of the Turing program:
|
||||||
Turing program:
|
|
||||||
|
|
||||||
Urer vf n dhvpx bhgyvar bs gur Ghevat cebtenz: gur
|
The previous and current Fibonacci numbers are kept in base
|
||||||
cerivbhf naq pheerag Svobanppv ahzoref ner xrcg va onfr
|
1 form with the current on the right. The first three
|
||||||
1 sbez jvgu gur pheerag ba gur evtug. Gur svefg guerr
|
steps set up the first two numbers, `1` and `1`. Then
|
||||||
fgrcf frg hc gur svefg gjb ahzoref, 1 naq 1. Gura
|
[beginning with `@ (`] a marker of `III` is created and
|
||||||
[ortvaavat jvgu "@ ("] n znexre bs VVV vf perngrq naq
|
the current number is copied to the right of the
|
||||||
gur pheerag ahzore vf pbcvrq gb gur evtug bs gur
|
marker. Then (beginning with `OV `) the number is
|
||||||
znexre. Gura [ortvaavat jvgu "BI "] gur ahzore vf
|
converted to binary by repeatedly dividing by 2 leaving I
|
||||||
pbairegrq gb ovanel ol ercrngrq qvivqvat ol 2 yrnivat V
|
for remainder `1`, and II for remainder `0`. Next
|
||||||
sbe erznvaqre 1, naq VV sbe erznvaqre 0. Arkg
|
(beginning with `WV `) the binary representation is
|
||||||
[ortvaavat jvgu "JI "] gur ovanel ercerfragngvba vf
|
printed and its symbols and the marker are erased.
|
||||||
cevagrq naq vgf flzobyf naq gur znexre ner renfrq.
|
Finally (beginning with `EEn`) the two numbers are
|
||||||
Svanyyl [ortvaavat jvgu "RRa"] gur gjb ahzoref ner
|
added and the current number copied to the left to
|
||||||
nqqrq naq gur pheerag ahzore pbcvrq gb gur yrsg gb
|
become the previous. Then the cycle repeats.
|
||||||
orpbzr gur cerivbhf. Gura gur plpyr ercrngf.
|
|
||||||
|
|
||||||
|
### Portability
|
||||||
|
|
||||||
The program requires that the lowest bit of a pointer to be 0.
|
The program requires that the lowest bit of a pointer to be 0.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#define f long
|
||||||
|
#define v (void)printf(
|
||||||
|
#define x ),exit(1);
|
||||||
|
#define y ){if(n)c=z(n,u),u=n,n=c;o[i]=n?'0'+(1&*n):'0';}
|
||||||
|
#define z(a,b) (f*)(~1&*a^(f)b)
|
||||||
|
#define k(l) if(!(l=(f*)malloc(sizeof(l))))v 23+m x if(1&(f)l)v 39+m x*l=
|
||||||
|
r(p,q,d)f*p,*q;{char o[81];f*n=p,i=39,*c,*u=d?q:z(p,q);o[40]='0'+(1&*p);
|
||||||
|
for(;i>=0;i--y u=d?z(p,q):q;n=p;for(i=41;i<79;i++y o[i++]='\r';o[i++]=0;
|
||||||
|
v o);(void)fflush(stdout);sleep(1);}
|
||||||
|
main(a,c)char**c;{char*u,*malloc(),*m=
|
||||||
|
"Usage: black [string]\n\0No more memory\n\0Unusable memory alignment\n\0jt,s@m@ (beleY%XX&Yz {z&z}i|R(|)*((.)i)hiniFiGJ%FG.JJgJ: ;;&;z {z&z}-RS/ROiOV OP+PsaPh+ijainnjmamfmfAlnnnnphppopv%vvgv.aABiB1/BVP11/1.%..&.OhrR-WV V1#1VP1CcC0R\
|
||||||
|
\n\n'CVP0\n!\n\n'\nEaEEnEamat!akckk'kwaww'wz,zzozEit +",
|
||||||
|
*n=m;f*q,*p=0,*g,b=3,d;
|
||||||
|
if(a>2)v m x n=a>1?c[1]:n;
|
||||||
|
/*v"\t\t\t\t\tV\n");*/
|
||||||
|
k(q)0;u=n;a=~1&'j';
|
||||||
|
while(a!='x'){
|
||||||
|
r(q,p,b);
|
||||||
|
for(;;u+=3){
|
||||||
|
u= *u?u:n;
|
||||||
|
if((~1&*u)==a&&(1&*q)<<1==(2&u[2]))break;
|
||||||
|
}
|
||||||
|
a=~1&u[1];
|
||||||
|
d=(8&u[2])>>3;
|
||||||
|
if(16&u[2])putchar(u[3]);
|
||||||
|
if(4&u[2])*q|=1;else*q&=~1;
|
||||||
|
if(b==d)g=p;else{
|
||||||
|
g=z(q,p);
|
||||||
|
if(!g){k(g)(f)q;*q^=(f)g;}
|
||||||
|
}
|
||||||
|
p=q;q=g;b=1-d;
|
||||||
|
}
|
||||||
|
r(q,p,b);v"\n");exit(0);
|
||||||
|
}
|
||||||
+4
-1
@@ -565,9 +565,12 @@ Cody fixed a segfault under macOS that prevented it from working. The problem
|
|||||||
was that the int (from `#define f`) should be a long. This became apparent when
|
was that the int (from `#define f`) should be a long. This became apparent when
|
||||||
he was using lldb and saw that the type of a pointer was too `long` :-)
|
he was using lldb and saw that the type of a pointer was too `long` :-)
|
||||||
|
|
||||||
|
Cody also provided the [alternate version](1989/paul/paul.alt.c)
|
||||||
|
which has the trace function that the author included but commented out. See the
|
||||||
|
README.md for details.
|
||||||
|
|
||||||
|
|
||||||
## [1989/robison](1989/robison/robison.c) ([README.md](1989/robison/README.md]))
|
## [1989/robison](1989/robison/robison.c) ([README.md](1989/robison/README.md]))
|
||||||
cd 1989/robison ; make orig_prog_diff
|
|
||||||
|
|
||||||
Yusuke Endoh fixed this to compile under modern systems. To see the changes
|
Yusuke Endoh fixed this to compile under modern systems. To see the changes
|
||||||
made, try:
|
made, try:
|
||||||
|
|||||||
Reference in new issue
Block a user