Merge pull request #87 from xexyl/1995

1995 entries checked
This commit is contained in:
Landon Curt Noll authored and GitHub committed 2023-03-18 23:06:11 -07:00
commit f4cc326652
13 files changed
+455 -396

No files matched your search

+3
View File
@@ -21,6 +21,9 @@ assistance!
./cdua
NOTE: on modern systems this might be hard to see it solve it in running time as
it goes so quickly but it will still show the result after execution.
## Judges' comments
This could be used as the basis of an a-maze-ing screen exerciser.
+23 -14
View File
@@ -10,31 +10,40 @@
make all
### To run
## To run:
./dodsond1 < some.text
./dodsond1 < text_file
## Judges' comment
## Try:
You might consider givig the following input:
./dodsond1 < README.md
## Judges' comments:
You might consider giving the following input:
... a male (who) gets very, very frustrated sitting in a chair all
the time because males are biologically driven to go out and hunt
giraffes.
-- Adjunct Professor Newt Gingrich, Reinhardt College, 1/7/95
## Author's comments
... which can be done like:
Istha ogrampra akesta Englishwa extta aswa inputwa andwa
anslatestra itwa intowa Igpa Atinla.
./dodsond1 < try.this.txt
The obfuscation is on several levels.
## Author's comments:
Most obviously, the shape of the program.
Istha ogrampra akesta Englishwa extta aswa inputwa andwa
anslatestra itwa intowa Igpa Atinla.
Underneath that, the variable names are in pig latin, as are the
names of the standard C functions, such as putchar. Even main is
written as ainma.
The obfuscation is on several levels.
The program construction is also very obfuscated, with all of the
code being inside the ()'s of one of the 6 "orfa" loops.
Most obviously, the shape of the program.
Underneath that, the variable names are in pig latin, as are the
names of the standard C functions, such as putchar. Even main is
written as ainma.
The program construction is also very obfuscated, with all of the
code being inside the ()'s of one of the 6 "orfa" loops.
+6
View File
@@ -0,0 +1,6 @@
... a male (who) gets very, very frustrated sitting in a chair all
the time because males are biologically driven to go out and hunt
giraffes.
-- Adjunct Professor Newt Gingrich, Reinhardt College, 1/7/95
+15 -14
View File
@@ -10,25 +10,26 @@
make all
### To run
### To run:
./dodsond2
./dodsond2
## Judges' comments
An amazing entry!
## Judges' comments:
The official chef enjoyed solving the maze, which she did on the first
attempt.
An amazing entry!
## Author's comments
The official chef enjoyed solving the maze, which she did on the first
attempt.
Interactive 3D Maze
## Author's comments:
Step into a randomly generated 3D maze and try to get out alive!
Use the vi movement keys (hjkl) to move on a level, and u or d
to move (u)p or (d)own from a position with a U or D on the
map. To simulate the feeling of being in an unknown labyrinth,
areas which you have not visited cannot be seen.
### Interactive 3D Maze
Reach the north-west left corner of level 1 to exit.
Step into a randomly generated 3D maze and try to get out alive!
Use the vi movement keys (hjkl) to move on a level, and u or d
to move (u)p or (d)own from a position with a U or D on the
map. To simulate the feeling of being in an unknown labyrinth,
areas which you have not visited cannot be seen.
Reach the north-west left corner of level 1 to exit.
+37 -35
View File
@@ -9,56 +9,58 @@
make all
### To run
### To run:
./esde data-file word
where data-file contains lines of < 255 chars in length.
where data-file contains lines of < 255 chars in length.
## Judges' comments
Try:
## Try:
./esde esde.data Johanson
./esde esde.data2 read
./esde esde.hint date
./esde README.md date
When reading the source be careful to distinguish between variable
names and library functions.
If you still don't know what it does, try:
http://avian.dars.muohio.edu/~kaelbesa/soundex.html
http://avian.dars.muohio.edu/~kaelbesa/coder.html
## Judges' comments:
When reading the source be careful to distinguish between variable
names and library functions.
If you still don't know what it does, try
[https://en.wikipedia.org/wiki/Soundex](https://en.wikipedia.org/wiki/Soundex).
## Author's comments
0) what this program does.
This program searches in the file words which have the same Soundex code
like the given word, and print out lines with these words.
### what this program does:
The Soundex code is using to find similar sounds words.
This program searches in the file words which have the same Soundex code
like the given word, and print out lines with these words.
Soundex code begins with the first letter of the word followed by a
three-digit code. There is the algorithm:
The Soundex code is using to find similar sounds words.
a) Every letter in the word change by a digit (excluding the first
letter).
b) Replace all pairs of the same code by single code
(ex. R011235 -> R01235).
c) Remove all 0-codes (ex. R01235 -> R1235).
d) If lenght of code is > 4, get only first 4 codes (ex. R1235 -> R123).
e) If lenght of code is < 4, add zeros (ex. T12 -> T120).
Soundex code begins with the first letter of the word followed by a
three-digit code. There is the algorithm:
There is the codes:
0 = A, E, H, I, O, U, W, Y
1 = B, P, F, V
2 = C, S, G, J, K, Q, X, Z
3 = D, T
4 = L
5 = M, N
6 = R
0. Every letter in the word change by a digit (excluding the first letter).
1. Replace all pairs of the same code by single code (ex. R011235 -> R01235).
2. Remove all 0-codes (ex. R01235 -> R1235).
3. If length of code is > 4, get only first 4 codes (ex. R1235 -> R123).
4. If length of code is < 4, add zeros (ex. T12 -> T120).
1) information about an info file.
An info file should be a text file consisting of lines (max. 256 bytes
in each line).
These are the codes:
0 = A, E, H, I, O, U, W, Y
1 = B, P, F, V
2 = C, S, G, J, K, Q, X, Z
3 = D, T
4 = L
5 = M, N
6 = R
### information about an info file:
An info file should be a text file consisting of lines of text (max. 256 bytes
in each line).
+31 -25
View File
@@ -9,51 +9,57 @@
make all
### To run
## To run:
./garry.test.sh
## Judges' comments
In general, try:
./garry <input_file >output_file
While it may not have been the intention of the submitter, the
judges noted that the C pre-processed version (with the #includes
left intact) looked very much like a rat "dropping core". See
garry.cpp and judge for yourself!
## Try:
The author was kind enough to provide a less obfuscated version of
the source called garry.fmt.c.
./garry.test.sh
./garry < README.md
## Judges' comments
In general, try:
While it may not have been the intention of the submitter, the
judges noted that the C pre-processed version (with the `#include`s
left intact) looked very much like a rat "dropping core". See
`garry.cpp` and judge for yourself!
The author was kind enough to provide a less obfuscated version of
the source called `garry.fmt.c`.
## Author's comments
This program is a file filter, designed to do environment-expansion and
incorporating the ability to create binary from escaped data in the
environment variables.
This program is a file filter, designed to do environment-expansion and
incorporating the ability to create binary from escaped data in the
environment variables.
The calling syntax is pretty simple, just use it with stdio-redirection
or inside pipelines, e.g.:
The calling syntax is pretty simple, just use it with stdio-redirection
or inside pipelines, e.g.:
progname <file_to_convert >converted_file
or
or
cat all_my_files/* | progname | lp
The syntax of the conversion of the input file is as follows: To include
the value of an environment variable in the output file, place the name
of the variable between "$"-signs in the input, e.g.:
The syntax of the conversion of the input file is as follows: To include
the value of an environment variable in the output file, place the name
of the variable between "$"-signs in the input, e.g.:
My Home-Directory is: $HOME$
I'm using the path: $PATH$
Unknown Env-variables or misformed expressions are ignored and kept
intact.
Unknown Env-variables or malformed expressions are ignored and kept
intact.
Additionally, the filter replaces escaped octal values in the
environment variables by their binary representation, e.g.:
Additionally, the filter replaces escaped octal values in the
environment variables by their binary representation, e.g.:
$ TEST="\110\145\154\154\157"
$ export TEST
+37 -30
View File
@@ -10,45 +10,52 @@
make all
### To run
## To run:
./heathbar num num
where num is a non-negative number.
## Try:
./heathbar 4253 2281
## Judges' comments
The main reason we liked this entry was mainly because the main
effect of the source was self documenting! :-)
## Judges' comments:
The main reason we liked this entry was mainly because the main
effect of the source was self documenting! :-)
## Author's comments
Run this program with two non-negative integer arguments
(e.g. "prog 1234 999").
Run this program with two non-negative integer arguments
(e.g. "prog 1234 999").
My goal was to create the fastest possible C program. To that
end, I made three critical observations:
My goal was to create the fastest possible C program. To that
end, I made three critical observations:
1. If there's one thing computers are good at, it's math.
2. Simple operations take less time than complicated ones.
3. Every C program seems to contain the word "main".
1. If there's one thing computers are good at, it's math.
2. Simple operations take less time than complicated ones.
3. Every C program seems to contain the word "main".
Based on #1, I knew that the Fastest Program had to be one that
performed addition. From #2, I reasoned that it ought to directly
manipulate the bits, rather than wasting time dealing with bloated,
high-level, fuzzy-logic, artificial-intelligence, neural-net,
client-server, object-oriented abstractions like the C language "+"
operator. And it was obvious from #3 that the program should
resemble, as closely as possible, a long sequence of the familiar
word "main" repeated over and over, so the computer would be
comfortable running the program and wouldn't get distracted dealing
with unfamiliar variable names.
Based on #1, I knew that the Fastest Program had to be one that
performed addition. From #2, I reasoned that it ought to directly
manipulate the bits, rather than wasting time dealing with bloated,
high-level, fuzzy-logic, artificial-intelligence, neural-net,
client-server, object-oriented abstractions like the C language "+"
operator. And it was obvious from #3 that the program should
resemble, as closely as possible, a long sequence of the familiar
word "main" repeated over and over, so the computer would be
comfortable running the program and wouldn't get distracted dealing
with unfamiliar variable names.
Also, I've looked at some past winning entries of your contest, and
if you don't mind a little constructive criticsm, some of them are
kind-of hard to figure out. I didn't want my program to fall into
the same trap, so I went out of my way to write self-documenting
code. Anyone who so much as glances at my program will immediately
see that it adds two 16-bit unsigned integers by streaming their
bits through a simulated cascade of hardware adders. I hope my
diligent effort to write especially clear code gets me extra points!
Also, I've looked at some past winning entries of your contest, and
if you don't mind a little constructive criticism, some of them are
kind-of hard to figure out. I didn't want my program to fall into
the same trap, so I went out of my way to write self-documenting
code. Anyone who so much as glances at my program will immediately
see that it adds two 16-bit unsigned integers by streaming their
bits through a simulated cascade of hardware adders. I hope my
diligent effort to write especially clear code gets me extra points!
P.S. What does "obfuscated" mean?
P.S. What does "obfuscated" mean?
+113 -99
View File
@@ -9,82 +9,95 @@
make all
### To run
## To run:
./leo 1 | cat - /dev/tty | gs -
./leo 37 80 | cat - /dev/tty | gs -
## Judges' comments
Press return after each image is drawn.
The variable names are element-ary. If you find this confusing,
remember that it is nu-clear. :-)
Some Ghostscripts/Postscript programs cleared the screen right after
the image is drawn, so we added element 106 which acts as an input
buffer.
If you don't have gs or an equivalent postscript viewer, try:
echo "" | leo 1 > foo.ps
and send foo.ps to your local postscript printer.
To qualify for a category specially for yourself in the Geek code,
find out the all the secret switches that the author doesn't divulge !
(All switches are single characters on the command line - anything that's
not a number is a candidate)
## Author's comments
The usage is:
./leo [ deep ] [ right ] [ Variable ] [ cycle [ freq ] ]
where the first three are literal words, `cycle' is a positive
integer (0 is ignored), and `freq' is an integer (default = 0)
supposed to be in range 0..100 (bigger values are allowed, however).
Invalid parameters and options usually stop the command line
parsing (but not always, why?). The actual position of the word
options does not matter, so "prog.sh right Variable 1 70"
is equivalent to "prog.sh 0 0 0 1 Variable 70 right", etc.
See the author's information below on these details.
If `Variable' is used, `cycle' is almost ignored (see below) but has
to be present if you want to enter `freq' (and you usually do).
Some options to try (besides the obvious):
## Try:
./leo 1 | cat - /dev/tty | gs -
This draws the basic pattern I invented in high school:
./leo 37 80 | cat - /dev/tty | gs -
You take a big sheet of "arithmetic" paper and draw a line
of length 1 (between 2 crossings) it the center of the sheet:
If you don't have gs or an equivalent postscript viewer, try:
echo "" | ./leo 1 > foo.ps
and send foo.ps to your local postscript printer or open it in an appropriate
application (e.g. GIMP).
## Judges' comments:
Press return after each image is drawn.
The variable names are element-ary. If you find this confusing,
remember that it is nu-clear. :-)
Some Ghostscripts/Postscript programs cleared the screen right after
the image is drawn, so we added element 106 which acts as an input
buffer.
To qualify for a category specially for yourself in the Geek code,
find out all the secret switches that the author doesn't divulge !
(All switches are single characters on the command line - anything that's
not a number is a candidate)
## Author's comments:
The usage is:
./leo [ deep ] [ right ] [ Variable ] [ cycle [ freq ] ]
where the first three are literal words, `cycle' is a positive
integer (0 is ignored), and `freq' is an integer (default = 0)
supposed to be in range 0..100 (bigger values are allowed, however).
Invalid parameters and options usually stop the command line
parsing (but not always, why?). The actual position of the word
options does not matter, so "prog.sh right Variable 1 70"
is equivalent to "prog.sh 0 0 0 1 Variable 70 right", etc.
If `Variable' is used, `cycle' is almost ignored (see below) but has
to be present if you want to enter `freq' (and you usually do).
Some options to try (besides the obvious):
./leo 1 | cat - /dev/tty | gs -
This draws the basic pattern I invented in high school:
You take a big sheet of "arithmetic" paper and draw a line
of length 1 (between 2 crossings) it the center of the sheet:
|
This makes 2 open ends (I think the notion of an "open end" doesn't
require explanations) in step 1. Now, until there are open ends in step N,
repeat: for each open end pretend it points north and draw 2 lines going
northwest and northeast from it to the nearest crossings. This needs to be
done "simultaneously" for all ends that are open at the moment.
This makes 2 open ends (I think the notion of an "open end" doesn't
require explanations) in step 1. Now, until there are open ends in step N,
repeat: for each open end pretend it points north and draw 2 lines going
northwest and northeast from it to the nearest crossings. This needs to be
done "simultaneously" for all ends that are open at the moment.
Step 2:
Step 2:
\./
|
/ \
Step 3:
Step 3:
__| |__
\./
|
__ / \ __
| |
Step 4:
.
Step 4: \./ \./
\./ \./
\__| |__/
/ \./ \
|
@@ -93,7 +106,7 @@
/ \./ \
Step 5:
Step 5:
._| . |_.
__| \./ \./ |__
\__| |__/
@@ -106,16 +119,16 @@
The lines marked by I show the places where "simultaneity" is significant.
Note that so far all the drawings represent valid
structural formulas of some organic substances.
Note that so far all the drawings represent valid
structural formulas of some organic substances.
step 1: ethane
step 2: 2,3-dimethylbutane
step 3: (2,5-dimethyl;3,4-isopropyl)-hexane
step 4 and 5: I don't know. Do you?
etc.
step 1: ethane
step 2: 2,3-dimethylbutane
step 3: (2,5-dimethyl;3,4-isopropyl)-hexane
step 4 and 5: I don't know. Do you?
etc.
Step 6:
Step 6:
\./ \./ \./ \./
._| . |_. ._| . |_.
\__| \./ \./ |__/ \__| \./ \./ |__/
@@ -128,11 +141,11 @@ The lines marked by I show the places where "simultaneity" is significant.
| | | |
/ \ / \ / \ / \
depending on the desired "hairiness". The original (paper-based)
algorithm was "hairy", but it didn't look as good on the screen.
depending on the desired "hairiness". The original (paper-based)
algorithm was "hairy", but it didn't look as good on the screen.
The program cannot handle non-hairy mode 100% correctly - step 6 happens
to be
The program cannot handle non-hairy mode 100% correctly - step 6 happens
to be
|__
...__/ ...__/
@@ -144,71 +157,72 @@ The lines marked by I show the places where "simultaneity" is significant.
\ \.__
|
and so on: the horisontal symmetry has been lost. That's why
the opening for step 1 is not a single line but a cross:
and so on: the horisontal symmetry has been lost. That's why
the opening for step 1 is not a single line but a cross:
\./
/ \
To watch it repeatedly (as a screen saver), use:
To watch it repeatedly (as a screen saver), use:
leo 2 | cat - /dev/tty | gs -
./leo 2 | cat - /dev/tty | gs -
The command line:
The command line:
leo Variable 1 | cat - /dev/tty | gs -
./leo Variable 1 | cat - /dev/tty | gs -
This draws the same as above. Try:
This draws the same as above. Try:
leo Variable 1 1 | cat - /dev/tty | gs -
./leo Variable 1 1 | cat - /dev/tty | gs -
what happened to the picture? Increase `freq' and watch the changes.
what happened to the picture? Increase `freq' and watch the changes.
If `cycle' is more than 1, the program loops, allowing the user to
enjoy randomly changing patterns (the delay is 3 sec),
but there is a secret switch to suppress looping : useful
if you want to pipe the output to a printer.
If `cycle' is more than 1, the program loops, allowing the user to
enjoy randomly changing patterns (the delay is 3 sec),
but there is a secret switch to suppress looping : useful
if you want to pipe the output to a printer.
`uudecode` the spoiler below if you really want to know.
uudecode the spoiler below if you really want to know.
begin 664 spoiler1
M*%1H92!C;VQO;B J:7,J('1H92!S96-R970@<W=I=&-H("T@=&AE('-P86-E
=(&)E9F]R92!I="!I<R!N;W0@82!M:7-T86ME*0II
end
If `Variable' is used, the actual value of `cycle' doesn't matter,
as far as it is > 1. To figure out what difference
`cycle' makes when `Variable' is not used, try
If `Variable' is used, the actual value of `cycle' doesn't matter,
as far as it is > 1. To figure out what difference
`cycle' makes when `Variable' is not used, try
leo Variable 37 80 | cat - /dev/tty | gs -
./leo Variable 37 80 | cat - /dev/tty | gs -
and other values of `cycle'; smaller values usually require
smaller values of `freq' for the patterns to be non-trivial
and other values of `cycle'; smaller values usually require
smaller values of `freq' for the patterns to be non-trivial
The options `deep' and `right' make the patterns to be drawn in different
manners. Try all the examples above with `deep' and with `right'.
What is the difference between them?
The options `deep' and `right' make the patterns to be drawn in different
manners. Try all the examples above with `deep' and with `right'.
What is the difference between them?
...There is a little flaw in the implementation of the algorithm,
and sometimes the patterns are not symmetrical when they ought to be
(the program needs to be slightly changed to expose the flaw,
otherwise it is hardly noticeable, if ever).
...There is a little flaw in the implementation of the algorithm,
and sometimes the patterns are not symmetrical when they ought to be
(the program needs to be slightly changed to expose the flaw,
otherwise it is hardly noticeable, if ever).
A quick and dirty fix (turned on by another secret switch)
makes the patterns symmetrical, but a little too HAIRY.
A quick and dirty fix (turned on by another secret switch)
makes the patterns symmetrical, but a little too HAIRY.
There is one more secret switch (it shall remain nameless), and I don't
even want to explain what it does. You've been warned!
There is one more secret switch (it shall remain nameless), and I don't
even want to explain what it does. You've been warned!
* * *
Special thanks:
Special thanks:
- to PostScript syntax designers for the curly braces;
- to Dmitry Mendeleyev for his periodic table of elements;
- to Hydrogen for having 2 more isotopes.
- to PostScript syntax designers for the curly braces;
- to Dmitry Mendeleyev for his periodic table of elements;
- to Hydrogen for having 2 more isotopes.
+6 -6
View File
@@ -10,18 +10,18 @@
make all
### To run
### To run:
./makarios
## Judges' comments
The judges were impressed that such a small program could do so much!
Can you figure out how it does it?
The judges were impressed that such a small program could do so much!
Can you figure out how it does it?
## Author's comments
This program takes no arguments. It emits the base 8 representation
of prime palindromes (palindromic in base 8, of course).
This program takes no arguments. It emits the base 8 representation
of prime palindromes (palindromic in base 8, of course).
^_^
`^_^`
+28 -25
View File
@@ -10,43 +10,46 @@
make all
### To run
## To run:
./savastio
# enter a number such as 100
NOTE: enter a number (such as 100).
## Try:
## Judges' comments
echo 42 | ./savastio
I know an l when I see a 1.
## Judges' comments:
## Author's comments
I know an l when I see a 1.
This program is an infinite-precision factorial calculator. It will
compute the factorial of any number entered to an infinite degree of
precision (or the limits of your machine's memory, whichever comes
first). I'd suggest you start with small numbers the first few times
you run it and gradually work your way up in order to get a feel for
the computation time your machine will require.
## Author's comments:
Aside from having an artistic code layout and confusing variable names,
the algorithm itself takes advantage of some cute C-isms. Try to
figure out how it prints the prompt "Enter number:".
This program is an infinite-precision factorial calculator. It will
compute the factorial of any number entered to an infinite degree of
precision (or the limits of your machine's memory, whichever comes
first). I'd suggest you start with small numbers the first few times
you run it and gradually work your way up in order to get a feel for
the computation time your machine will require.
Numbers are represented internally by a linked list of blocks each
containing 1000 buckets of 4-digit integers. To further confuse
matters, the buckets are arranged backwards in the block. For example,
the number 8347108947139478934713847134 is represented as:
Aside from having an artistic code layout and confusing variable names,
the algorithm itself takes advantage of some cute C-isms. Try to
figure out how it prints the prompt "Enter number:".
Numbers are represented internally by a linked list of blocks each
containing 1000 buckets of 4-digit integers. To further confuse
matters, the buckets are arranged backwards in the block. For example,
the number 8347108947139478934713847134 is represented as:
7134 1384 9347 3947 9471 7108 834
Platform limitations:
Platform limitations:
Long integers must be at least 4 bytes.
Long integers must be at least 4 bytes.
Features:
### Features
In order to prevent the user from wasting too much time computing
useless factorials, the maximum factorial that can be computed is
429539! This limit was selected through extensive research in
time management studies and the factorial arts.
In order to prevent the user from wasting too much time computing
useless factorials, the maximum factorial that can be computed is
429539! This limit was selected through extensive research in
time management studies and the factorial arts.
+13 -7
View File
@@ -10,20 +10,26 @@
make all
### To run
## To run:
./schnitzi num
## Try:
./schnitzi 24
./schnitzi 18
./schnitzi 30
## Judges' comments
NOTE: as the author warns do not use too high a number! If you wish to ignore
the warning it is an exercise to determine how high is too high. :-)
Sometimes a core dump is a feature, not a bug!
## Judges' comments:
This is one of the better one-liners we have seen in a while.
Take some time to figure out what it does before you run it!
Sometimes a core dump is a feature, not a bug!
This is one of the better one-liners we have seen in a while.
Take some time to figure out what it does before you run it!
## Author's comments
Beware, running this program with too high of a number
amounts to doing a fork bomb on your machine!
Beware, running this program with too high of a number
amounts to doing a fork bomb on your machine!
+11 -11
View File
@@ -10,24 +10,24 @@
make all
### To run
### To run:
./spinellis < spinellis.c
## Judges' comments
While code does not abuse the rules, its output surely does!
While the code does not abuse the rules, its output surely does!
P.S. Does the source have any spelling errors?
P.S. Does the source have any spelling errors?
## Author's comments
96% of the program lines (631 out of the 658) are comment text rendering
the program readable and understandable. With the exception of the
two include file names (needed for a warning-free compile) the program
passes the standard Unix spell checker without any errors. Checking
for spelling errors is considered very important for programs that are
so heavily commented. This program is exactly 3217 characters long
through judicious use of white space. Rule abuse? Would I _ever_ abuse
the rules?
96% of the program lines (631 out of the 658) are comment text rendering
the program readable and understandable. With the exception of the
two include file names (needed for a warning-free compile) the program
passes the standard Unix spell checker without any errors. Checking
for spelling errors is considered very important for programs that are
so heavily commented. This program is exactly 3217 characters long
through judicious use of white space. Rule abuse? Would I _ever_ abuse
the rules?
+132 -130
View File
@@ -11,155 +11,157 @@
make all
### To run
## To run:
./vanschnitz
## Judges' comments
## Try:
To use:
make clobber all LEVEL=6
./vanschnitz
make clobber all LEVEL=8
## Judges' comments:
Warning: Values of LEVEL>8 have been known to cause compilers
(and in one case a system) to crash during compilation.
Warning: in the past, values of LEVEL>8 have been known to cause compilers (and
in one case a system) to crash during compilation. We tested it in 2023 on a
MacBook Pro with the M1 chip and found that LEVEL > 6 caused problems.
For a bad/slow time try LEVEL=15.
For a bad/slow time try LEVEL=15.
## Author's comments
## Authors' comments:
A classic problem in computer science is known as the Towers
of Hanoi. It involves a set of different-sized disks mounted
on one of three pegs. The object is to move the pile of disks
to one of the other pegs. You may only move one disk at a
time, and there is an additional constraint that a disk may
never be placed on top of a smaller disk.
A classic problem in computer science is known as the Towers
of Hanoi. It involves a set of different-sized disks mounted
on one of three pegs. The object is to move the pile of disks
to one of the other pegs. You may only move one disk at a
time, and there is an additional constraint that a disk may
never be placed on top of a smaller disk.
Our program solves the Towers of Hanoi problem. Well, that's
not exactly true; actually, it's the compiler that solves the
problem. The resulting program just prints out the correct
solution.
Our program solves the Towers of Hanoi problem. Well, that's
not exactly true; actually, it's the compiler that solves the
problem. The resulting program just prints out the correct
solution.
How do you trick a compiler into actually solving the problem?
First, you must tell it how many disks you wish to solve it
for. This is done by defining the symbol 'n' on the compile
line. For instance, to cause the compiler to solve the Towers
of Hanoi problem with four disks, you would compile the program
like this:
How do you trick a compiler into actually solving the problem?
First, you must tell it how many disks you wish to solve it
for. This is done by defining the symbol 'n' on the compile
line. For instance, to cause the compiler to solve the Towers
of Hanoi problem with four disks, you would compile the program
like this:
gcc hanoi.c -o hanoi -Dn=4
A default value of 5 will be used for n if you do not define
it on the command line. The value of n cannot be greater than
fifteen (the compiler we used to test has a limit on the #include
depth). The compiler then solves the problem using binary
arithmetic based on whether particular symbols are defined or not.
To loop, the program #include's itself. This is, of course,
expensive; one compile we did with n=14 took about fifty
minutes to compile on our system (compiling with n=15
caused our system to crash).
A default value of 5 will be used for n if you do not define
it on the command line. The value of n cannot be greater than
fifteen (the compiler we used to test has a limit on the #include
depth). The compiler then solves the problem using binary
arithmetic based on whether particular symbols are defined or not.
The resulting program that the compiler generates simply
prints out the answer. Did I say "simply"? Actually, the
whole resulting program consists of a single printf statement,
consisting of a massive string constant of length 35*(2^n-1),
followed by 3*(2^n-1) integers which get formatted into the
string. For our n=14 run, this adds up to a string constant
of length 573405, followed by 49149 integers delimeted by
commas. (Generating the string constant depends on the
ANSI C feature in which adjacent character strings are
catenated; a version that does not use this feature has been
included for people who can only run K&R). A good way to see
the resulting program (on a Unix system) is to do the command
To loop, the program #include's itself. This is, of course,
expensive; one compile we did with n=14 took about fifty
minutes to compile on our system (compiling with n=15
caused our system to crash).
The resulting program that the compiler generates simply
prints out the answer. Did I say "simply"? Actually, the
whole resulting program consists of a single printf statement,
consisting of a massive string constant of length `35*(2^n-1)`,
followed by `3*(2^n-1)` integers which get formatted into the
string. For our n=14 run, this adds up to a string constant
of length 573405, followed by 49149 integers delimited by
commas. (Generating the string constant depends on the
ANSI C feature in which adjacent character strings are
catenated; a version that does not use this feature has been
included for people who can only run K&R). A good way to see
the resulting program (on a Unix system) is to do the command
gcc hanoi.c -E -Dn=5 | grep -v \# | grep -v ^\$
For an odd number of disks, the program will provide a
solution wherein the disks end up on peg 2; for an even
number of disks, they will end on peg 3. This should
provide some hint as to what sort of algorithm is used.
For an odd number of disks, the program will provide a
solution wherein the disks end up on peg 2; for an even
number of disks, they will end on peg 3. This should
provide some hint as to what sort of algorithm is used.
We have included a "spoiler" version of the program, with
meaningful symbol names and comments, but we encourage you
to try to decipher the program without it...
We have included a "spoiler" version of the program, with
meaningful symbol names and comments, but we encourage you
to try to decipher the program without it...
begin 444 spoiler.c
M(VEF;F1E9B`@24Y)5$E!3$E:140*"B\J"B`J("!)9B!N(&ES;B=T(&1E9FEN
M960L(&UA:V4@:70@-0H@*B\*(VEF;F1E9B`@;@HC9&5F:6YE("!N(#`U"B-E
M;F1I9@H*+RH*("H@4V]M92!U<V5F=6P@=F%R:6%B;&5S"B`J+PHC9&5F:6YE
M("!42$E37T9)3$4@7U]&24Q%7U\@"B-D969I;F4@($9/4DU!5%]35%))3D<@
M(DUO=F4@9&ES:R`E9"!F<F]M('!E9R`E9"!T;R!P96<@)61<;B(*(V1E9FEN
M92`@24Y)5$E!3$E:140*"B\J"B`J(%1R86YS;&%T92!N(&EN=&\@8FET<PH@
M*B\*(VEF("`@("`@;B8P,0HC9&5F:6YE("!B:70P"B-E;F1I9@HC:68@("`@
M("!N)C`R"B-D969I;F4@(&)I=#$*(V5N9&EF"B-I9B`@("`@(&XF,#0*(V1E
M9FEN92`@8FET,@HC96YD:68*(VEF("`@("`@;CX^,PHC9&5F:6YE("!B:70S
M"B-E;F1I9@H*+RH*("H@2&5R92=S('1H92!P<F]G<F%M(0H@*B\*;6%I;B@I
M>PIP<FEN=&8H"B-I;F-L=61E(%1(25-?1DE,10HC9&5F:6YE("!.3U=?1$]?
M5$A%7TY534)%4E,*(VEN8VQU9&4@5$A)4U]&24Q%"BD[?0H*(V5L<V4*"B\J
M"B`J($-H96-K('1O('-E92!I9B!T:&4@;G5M8F5R(&ES('IE<F\@*&)O='1O
M;2!O9B!R96-U<G-I;VXI"B`J+PHC:69D968@("!B:70P"B-D969I;F4@($Y?
M25-?3D]47UI%4D\*(V5N9&EF"B-I9F1E9B`@(&)I=#$*(V1E9FEN92`@3E])
M4U].3U1?6D523PHC96YD:68*(VEF9&5F("`@8FET,@HC9&5F:6YE("!.7TE3
M7TY/5%]:15)/"B-E;F1I9@HC:69D968@("!B:70S"B-D969I;F4@($Y?25-?
M3D]47UI%4D\*(V5N9&EF"@HC:69D968@("!.7TE37TY/5%]:15)/"B-U;F1E
M9B`@($Y?25-?3D]47UI%4D\*"B\J"B`J($1E8W)E;65N="!N"B`J+PHC:69N
M9&5F("!B:70P"B-D969I;F4@(&)I=#`*(VEF;F1E9B`@8FET,0HC9&5F:6YE
M("!B:70Q"B-I9FYD968@(&)I=#(*(V1E9FEN92`@8FET,@HC:69N9&5F("!B
M:70S"B-D969I;F4@(&)I=#,*(V5L<V4*(W5N9&5F("`@8FET,PHC96YD:68*
M(V5L<V4*(W5N9&5F("`@8FET,@HC96YD:68*(V5L<V4*(W5N9&5F("`@8FET
M,0HC96YD:68*(V5L<V4*(W5N9&5F("`@8FET,`HC96YD:68*"B\J"B`J("!(
M97)E)W,@<F5C=7)S:6]N"B`J+PHC:6YC;'5D92!42$E37T9)3$4*"B\J"B`J
M("!.;W1E.B!/9&0@;G5M8F5R960@9&ES:W,@86QW87ES(&-Y8VQE(&9R;VT@
M,2`]/B`R(#T^(#,@/3X@,2`]/B`R(#T^(#,*("H@($5V96X@;G5M8F5R960@
M9&ES:W,@86QW87ES(&-Y8VQE(&9R;VT@,2`]/B`S(#T^(#(@/3X@,2`]/B`S
M(#T^(#(*("HO"@HO*@H@*B!#:&5C:R!T;R!S964@:68@;B!I<R!Z97)O+B!)
M9B!S;RP@=V4G<F4@;6]V:6YG(&1I<VL@,2X*("H@26X@9V5N97)A;"P@9F]R
M(&%N>2!N('=E)W)E(&UO=FEN9R!D:7-K(&XK,2X@5&AA="!M96%N<R!T:&%T
M"B`J('=H96X@;B!I<R!O9&0L('=E)W)E(&UO=FEN9R!A;B!E=F5N(&1I<VLL
M(&%N9"!V:6-E('9E<G-A+@H@*B\*(VEF;F1E9B`@8FET,`HC:69N9&5F("!B
M:70Q"B-I9FYD968@(&)I=#(*(VEF;F1E9B`@8FET,PHC9&5F:6YE("!.7TE3
M7UI%4D\*(V5N9&EF"B-E;F1I9@HC96YD:68*(V5N9&EF"@HC:69D968@("!.
M7TE37UI%4D\*(W5N9&5F("`@3E])4U]:15)/"@HC:69N9&5F("!.3U=?1$]?
M5$A%7TY534)%4E,*1D]234%47U-44DE.1PHC96QS90H*+RH*("H@($EF(&1I
M<VL@,2!I<R!O;B!P96<@,BP@;6]V92!I="`R(#T^(#,*("HO"B-I9F1E9B`@
M($1)4TM?3TY%7TE37T].7U!%1U]45T\*+#$L,BPS"B-U;F1E9B`@($1)4TM?
M3TY%7TE37T].7U!%1U]45T\*(V1E9FEN92`@1$E32U]/3D5?25-?3TY?4$5'
M7U1(4D5%"B-E;'-E"@HO*@H@*B`@268@9&ES:R`Q(&ES(&]N('!E9R`S+"!M
M;W9E(&ET(#,@/3X@,0H@*B\*(VEF9&5F("`@1$E32U]/3D5?25-?3TY?4$5'
M7U1(4D5%"BPQ+#,L,0HC=6YD968@("!$25-+7T].15])4U]/3E]014=?5$A2
M144*(V5L<V4*"B\J"B`J("!$:7-K(#$@;75S="!B92!O;B!P96<@,2X@36]V
M92!I="`Q(#T^(#(*("HO"BPQ+#$L,@HC9&5F:6YE("!$25-+7T].15])4U]/
M3E]014=?5%=/"B-E;F1I9@HC96YD:68*(V5N9&EF"B-E;'-E"@HO*@H@*B`@
M2&5R92P@=V4@:&%N9&QE(&1I<VMS(#XQ+B!296UE;6)E<B!T:&%T(&]D9',@
M8WEC;&4@,2`]/B`R(#T^(#,@/3X@,2P*("H@(&%N9"!E=F5N<R!C>6-L92`Q
M(#T^(#(@/3X@,R`]/B`Q+B!#;VUB:6YE('1H:7,@=VET:"!T:&4@:VYO=VQE
M9&=E"B`J("!O9B!W:&5R92!D:7-K(#$@:7,L(&%N9"!W92!C86X@9&5T97)M
M:6YE(&AO=R!T;R!M;W9E(&%N>2!D:7-K+@H@*B\*(VEF;F1E9B`@3D]77T1/
M7U1(15].54U"15)3"D9/4DU!5%]35%))3D<*(V5L<V4*"B\J"B`J("!0<FEN
M="!T:&4@9&ES:R!N=6UB97(N(%)E;65M8F5R+"!D:7-K(&YU;6)E<B`](&XK
M,0H@*B\*+#$*(VEF9&5F("`@8FET,`HK,0HC96YD:68*(VEF9&5F("`@8FET
M,0HK,@HC96YD:68*(VEF9&5F("`@8FET,@HK-`HC96YD:68*(VEF9&5F("`@
M8FET,PHK.`HC96YD:68*"B\J"B`J("!$:7-K(#$@;VX@<&5G(#(@"B`J+PHC
M:69D968@("!$25-+7T].15])4U]/3E]014=?5%=/"B-I9F1E9B`@(&)I=#`*
M+#$L,R`@("`O*B!%=F5N.B`Q(#T^(#,@("AN(&ES(&]D9"P@<V\@=&AE(&1I
M<VL@:7,@979E;BD@*B\*(V5L<V4*+#,L,2`@("`O*B`@3V1D.B`S(#T^(#$@
M("HO"B-E;F1I9@HC96QS90H*+RH*("H@($1I<VL@,2!O;B!P96<@,R`*("HO
M"B-I9F1E9B`@($1)4TM?3TY%7TE37T].7U!%1U]42%)%10HC:69D968@("!B
M:70P"BPR+#$@("`@+RH@179E;CH@,B`]/B`Q("HO"B-E;'-E"BPQ+#(@("`@
M+RH@($]D9#H@,2`]/B`R("HO"B-E;F1I9@HC96QS90H*+RH*("H@($1I<VL@
M,2!O;B!P96<@,2`*("HO"B-I9F1E9B`@(&)I=#`*+#,L,B`@("`O*B!%=F5N
M.B`S(#T^(#(@*B\*(V5L<V4*+#(L,R`@("`O*B`@3V1D.B`R(#T^(#,@*B\*
M(V5N9&EF"B-E;F1I9@HC96YD:68*(V5N9&EF"B-E;F1I9@H*+RH*("H@($UO
M<F4@<F5C=7)S:6]N"B`J+PHC:6YC;'5D92!42$E37T9)3$4*"B\J"B`J("!)
M;F-R96UE;G0@;@H@*B\*(VEF9&5F("`@8FET,`HC=6YD968@("!B:70P"B-I
M9F1E9B`@(&)I=#$*(W5N9&5F("`@8FET,0HC:69D968@("!B:70R"B-U;F1E
M9B`@(&)I=#(*(VEF9&5F("`@8FET,PHC=6YD968@("!B:70S"B-E;'-E"B-D
M969I;F4@(&)I=#,*(V5N9&EF"B-E;'-E"B-D969I;F4@(&)I=#(*(V5N9&EF
M"B-E;'-E"B-D969I;F4@(&)I=#$*(V5N9&EF"B-E;'-E"B-D969I;F4@(&)I
M=#`*(V5N9&EF"@HC96YD:68@("\J("-I9F1E9B!.7TE37TY/5%]:15)/("HO
M"@HC96YD:68@("\J("-E;'-E(&]F("-I9FYD968@24Y)5$E!3$E:140@*B\*
`
end
begin 444 spoiler.c
M(VEF;F1E9B`@24Y)5$E!3$E:140*"B\J"B`J("!)9B!N(&ES;B=T(&1E9FEN
M960L(&UA:V4@:70@-0H@*B\*(VEF;F1E9B`@;@HC9&5F:6YE("!N(#`U"B-E
M;F1I9@H*+RH*("H@4V]M92!U<V5F=6P@=F%R:6%B;&5S"B`J+PHC9&5F:6YE
M("!42$E37T9)3$4@7U]&24Q%7U\@"B-D969I;F4@($9/4DU!5%]35%))3D<@
M(DUO=F4@9&ES:R`E9"!F<F]M('!E9R`E9"!T;R!P96<@)61<;B(*(V1E9FEN
M92`@24Y)5$E!3$E:140*"B\J"B`J(%1R86YS;&%T92!N(&EN=&\@8FET<PH@
M*B\*(VEF("`@("`@;B8P,0HC9&5F:6YE("!B:70P"B-E;F1I9@HC:68@("`@
M("!N)C`R"B-D969I;F4@(&)I=#$*(V5N9&EF"B-I9B`@("`@(&XF,#0*(V1E
M9FEN92`@8FET,@HC96YD:68*(VEF("`@("`@;CX^,PHC9&5F:6YE("!B:70S
M"B-E;F1I9@H*+RH*("H@2&5R92=S('1H92!P<F]G<F%M(0H@*B\*;6%I;B@I
M>PIP<FEN=&8H"B-I;F-L=61E(%1(25-?1DE,10HC9&5F:6YE("!.3U=?1$]?
M5$A%7TY534)%4E,*(VEN8VQU9&4@5$A)4U]&24Q%"BD[?0H*(V5L<V4*"B\J
M"B`J($-H96-K('1O('-E92!I9B!T:&4@;G5M8F5R(&ES('IE<F\@*&)O='1O
M;2!O9B!R96-U<G-I;VXI"B`J+PHC:69D968@("!B:70P"B-D969I;F4@($Y?
M25-?3D]47UI%4D\*(V5N9&EF"B-I9F1E9B`@(&)I=#$*(V1E9FEN92`@3E])
M4U].3U1?6D523PHC96YD:68*(VEF9&5F("`@8FET,@HC9&5F:6YE("!.7TE3
M7TY/5%]:15)/"B-E;F1I9@HC:69D968@("!B:70S"B-D969I;F4@($Y?25-?
M3D]47UI%4D\*(V5N9&EF"@HC:69D968@("!.7TE37TY/5%]:15)/"B-U;F1E
M9B`@($Y?25-?3D]47UI%4D\*"B\J"B`J($1E8W)E;65N="!N"B`J+PHC:69N
M9&5F("!B:70P"B-D969I;F4@(&)I=#`*(VEF;F1E9B`@8FET,0HC9&5F:6YE
M("!B:70Q"B-I9FYD968@(&)I=#(*(V1E9FEN92`@8FET,@HC:69N9&5F("!B
M:70S"B-D969I;F4@(&)I=#,*(V5L<V4*(W5N9&5F("`@8FET,PHC96YD:68*
M(V5L<V4*(W5N9&5F("`@8FET,@HC96YD:68*(V5L<V4*(W5N9&5F("`@8FET
M,0HC96YD:68*(V5L<V4*(W5N9&5F("`@8FET,`HC96YD:68*"B\J"B`J("!(
M97)E)W,@<F5C=7)S:6]N"B`J+PHC:6YC;'5D92!42$E37T9)3$4*"B\J"B`J
M("!.;W1E.B!/9&0@;G5M8F5R960@9&ES:W,@86QW87ES(&-Y8VQE(&9R;VT@
M,2`]/B`R(#T^(#,@/3X@,2`]/B`R(#T^(#,*("H@($5V96X@;G5M8F5R960@
M9&ES:W,@86QW87ES(&-Y8VQE(&9R;VT@,2`]/B`S(#T^(#(@/3X@,2`]/B`S
M(#T^(#(*("HO"@HO*@H@*B!#:&5C:R!T;R!S964@:68@;B!I<R!Z97)O+B!)
M9B!S;RP@=V4G<F4@;6]V:6YG(&1I<VL@,2X*("H@26X@9V5N97)A;"P@9F]R
M(&%N>2!N('=E)W)E(&UO=FEN9R!D:7-K(&XK,2X@5&AA="!M96%N<R!T:&%T
M"B`J('=H96X@;B!I<R!O9&0L('=E)W)E(&UO=FEN9R!A;B!E=F5N(&1I<VLL
M(&%N9"!V:6-E('9E<G-A+@H@*B\*(VEF;F1E9B`@8FET,`HC:69N9&5F("!B
M:70Q"B-I9FYD968@(&)I=#(*(VEF;F1E9B`@8FET,PHC9&5F:6YE("!.7TE3
M7UI%4D\*(V5N9&EF"B-E;F1I9@HC96YD:68*(V5N9&EF"@HC:69D968@("!.
M7TE37UI%4D\*(W5N9&5F("`@3E])4U]:15)/"@HC:69N9&5F("!.3U=?1$]?
M5$A%7TY534)%4E,*1D]234%47U-44DE.1PHC96QS90H*+RH*("H@($EF(&1I
M<VL@,2!I<R!O;B!P96<@,BP@;6]V92!I="`R(#T^(#,*("HO"B-I9F1E9B`@
M($1)4TM?3TY%7TE37T].7U!%1U]45T\*+#$L,BPS"B-U;F1E9B`@($1)4TM?
M3TY%7TE37T].7U!%1U]45T\*(V1E9FEN92`@1$E32U]/3D5?25-?3TY?4$5'
M7U1(4D5%"B-E;'-E"@HO*@H@*B`@268@9&ES:R`Q(&ES(&]N('!E9R`S+"!M
M;W9E(&ET(#,@/3X@,0H@*B\*(VEF9&5F("`@1$E32U]/3D5?25-?3TY?4$5'
M7U1(4D5%"BPQ+#,L,0HC=6YD968@("!$25-+7T].15])4U]/3E]014=?5$A2
M144*(V5L<V4*"B\J"B`J("!$:7-K(#$@;75S="!B92!O;B!P96<@,2X@36]V
M92!I="`Q(#T^(#(*("HO"BPQ+#$L,@HC9&5F:6YE("!$25-+7T].15])4U]/
M3E]014=?5%=/"B-E;F1I9@HC96YD:68*(V5N9&EF"B-E;'-E"@HO*@H@*B`@
M2&5R92P@=V4@:&%N9&QE(&1I<VMS(#XQ+B!296UE;6)E<B!T:&%T(&]D9',@
M8WEC;&4@,2`]/B`R(#T^(#,@/3X@,2P*("H@(&%N9"!E=F5N<R!C>6-L92`Q
M(#T^(#(@/3X@,R`]/B`Q+B!#;VUB:6YE('1H:7,@=VET:"!T:&4@:VYO=VQE
M9&=E"B`J("!O9B!W:&5R92!D:7-K(#$@:7,L(&%N9"!W92!C86X@9&5T97)M
M:6YE(&AO=R!T;R!M;W9E(&%N>2!D:7-K+@H@*B\*(VEF;F1E9B`@3D]77T1/
M7U1(15].54U"15)3"D9/4DU!5%]35%))3D<*(V5L<V4*"B\J"B`J("!0<FEN
M="!T:&4@9&ES:R!N=6UB97(N(%)E;65M8F5R+"!D:7-K(&YU;6)E<B`](&XK
M,0H@*B\*+#$*(VEF9&5F("`@8FET,`HK,0HC96YD:68*(VEF9&5F("`@8FET
M,0HK,@HC96YD:68*(VEF9&5F("`@8FET,@HK-`HC96YD:68*(VEF9&5F("`@
M8FET,PHK.`HC96YD:68*"B\J"B`J("!$:7-K(#$@;VX@<&5G(#(@"B`J+PHC
M:69D968@("!$25-+7T].15])4U]/3E]014=?5%=/"B-I9F1E9B`@(&)I=#`*
M+#$L,R`@("`O*B!%=F5N.B`Q(#T^(#,@("AN(&ES(&]D9"P@<V\@=&AE(&1I
M<VL@:7,@979E;BD@*B\*(V5L<V4*+#,L,2`@("`O*B`@3V1D.B`S(#T^(#$@
M("HO"B-E;F1I9@HC96QS90H*+RH*("H@($1I<VL@,2!O;B!P96<@,R`*("HO
M"B-I9F1E9B`@($1)4TM?3TY%7TE37T].7U!%1U]42%)%10HC:69D968@("!B
M:70P"BPR+#$@("`@+RH@179E;CH@,B`]/B`Q("HO"B-E;'-E"BPQ+#(@("`@
M+RH@($]D9#H@,2`]/B`R("HO"B-E;F1I9@HC96QS90H*+RH*("H@($1I<VL@
M,2!O;B!P96<@,2`*("HO"B-I9F1E9B`@(&)I=#`*+#,L,B`@("`O*B!%=F5N
M.B`S(#T^(#(@*B\*(V5L<V4*+#(L,R`@("`O*B`@3V1D.B`R(#T^(#,@*B\*
M(V5N9&EF"B-E;F1I9@HC96YD:68*(V5N9&EF"B-E;F1I9@H*+RH*("H@($UO
M<F4@<F5C=7)S:6]N"B`J+PHC:6YC;'5D92!42$E37T9)3$4*"B\J"B`J("!)
M;F-R96UE;G0@;@H@*B\*(VEF9&5F("`@8FET,`HC=6YD968@("!B:70P"B-I
M9F1E9B`@(&)I=#$*(W5N9&5F("`@8FET,0HC:69D968@("!B:70R"B-U;F1E
M9B`@(&)I=#(*(VEF9&5F("`@8FET,PHC=6YD968@("!B:70S"B-E;'-E"B-D
M969I;F4@(&)I=#,*(V5N9&EF"B-E;'-E"B-D969I;F4@(&)I=#(*(V5N9&EF
M"B-E;'-E"B-D969I;F4@(&)I=#$*(V5N9&EF"B-E;'-E"B-D969I;F4@(&)I
M=#`*(V5N9&EF"@HC96YD:68@("\J("-I9F1E9B!.7TE37TY/5%]:15)/("HO
M"@HC96YD:68@("\J("-E;'-E(&]F("-I9FYD968@24Y)5$E!3$E:140@*B\*
`
end