When I'm bored, I often think of ways to write new inefficient "Hello, world!" programs. These are some methods I've come up with:

Making the program go through the characters of the string "Hello, world!" one by one, generating random characters until it comes up with the correct one, then displaying it.

strcat()'ing many short strings containing parts of the string "Hello, world!"

Using many #define's, I've made a hello world program where the only code that wasn't preprocessor directives was "q foo lal lol rod b n s 19 y x n g r w r x a lal n lol x bar l x rofl".

Writing "Hello, world!" to a file, then using system() to display the text in the file using cat.

Transferring "Hello, world!" character by character through a local TCP/IP socket connection, displaying each character as it is received.

Using a separate thread to display each character in the string "Hello, world!"

And possibly some others that I've forgotten.

(For sake of sanity, please don't turn this into a huuuuuge GTKYN!)

Here's my try - this uses Octave. I tried to write this (apart of the polynomial-fitting stuff) in C, but I "ran out steam" so to speak (maybe I should try this in Fortran or something...)

What it does? Well, it takes the ASCII values of the string, interprets that as a series of number (Y coordinate for X each coordinate 1, 2, 3...), finds a polynomial of 13th degree that fits the data, evaluates the polynomial for each X, converts results back to ASCII, and displays the string.

(Evaluation is done automatically by polyfit, stored to evald... Handy, that.)

To run, store this to a text file "helloworld.oct", and run it:

octave> source "helloworld.oct"
Hello world

Also, if you run it with "want_plotted=1;" before the source command, it plots a kewl graph for you with GNUPlot!

Final disclaimer: I'm not a mathematician (math is hard), but I know a doomed-to-fail programming approach when I see one. =)

Without further ado, here's the stuff...


# -*- octave -*-
# This is just about the most hideous and complicated way of printing
# "Hello World" I can think of for the moment...
# Feel free to abuse the idea.
# By Weyfour WWWWolf (Urpo Lankinen), 2001-02-04
1;

letters = toascii("Hello world");
[p, evald] = polyfit([1:11],letters,13);

if (exist("want_plotted"))
  plotx = (0:0.1:25)';
  polydata = [plotx, polyval(p,plotx)];

  chardata = [(1:11)',letters'];

  gset grid xtics ytics;
  gplot [0:13] [0:255] \
      chardata with points title "desired values", \
      polydata with lines title "fitted curve"
endif

disp(setstr(evald))

Note that this simple "encryption" is highly unstable if you need characters other than upper-case-only or lower-case-only... In this example, if you look at the graph that it produces, the space "yanks" the graph to a wild wave. I was unable to add the exclamation point because the curve was so curved... this sort of problems could be avoided with simple change of encoding to some other that is less varied.

Then again, the whole graph thing here is pretty... absurd. AND probably someone has patented this stuff in USA because it's so obvious and sounds cool... =)

(I really should turn the polynomial evaluation and the polyfit result coefficient floats into a nice, 300-line C program that no one really can make any sense of...)

Many months ago, one listless Sunday afternoon, I crafted a stupidly inefficient program using the already long-winded assembly language. This is quite possibly the dumbest way to print "Hello world!" to the DOS standard output using NASM...

segment code

..start         mov ax,0B800h
                mov es,ax
                xor di,di
                mov cx,2000
                mov ah,7
                mov al,0
                rep stosw      ;Clear the screen (just to be safe!)

                mov dh,0
                mov dl,0
                xor bh,bh
                mov ah,2
                int 10h        ;Reset cursor to 0,0

                mov ax,data
                mov ds,ax

                mov ax,0B800h
                mov es,ax
                xor di,di
                mov bx,0

findchar        mov cl,0       ;Search every ASCII character from 0...
                cmp byte cl,[ds:_message+bx]
                je print
                inc cl
                jmp findchar   ;Until required letter is found

print           mov ah,7
                mov byte al,cl
                stosw          ;Get char and store character in stdout...

                cmp bx,12      ;Check for end of string...
                je end
                inc bx
                jmp findchar   ;Then do it all over again!

end             mov ax,4C00h
                int 21h

segment data

_message db "Hello world!"

A similar effect could probably be achieved in less than ten lines, although saying that, the above program would probably still be more efficient than cout << "Hello world!" (at least with my POS compiler)

It seems to me that any supposedly inefficient "Hello World" program which actually contains the string "Hello world\n" in its source code (excluding comments) is bogus since such a program could just print out the string directly.

Here's a program which doesn't contain the string "Hello world" anywhere except in the comments. It generates a string of twelve characters randomly selected from the set of lower and upper case letters, the space character and the newline character. It then checks if the string's MD5 checksum is equal to the hard-coded MD5 checksum of "Hello world\n". If the checksums match then it prints the string and terminates. Otherwise, it begins again with another randomly generated twelve character string.

There are 5412 or 614,787,626,176,508,399,616 twelve character strings containing the characters used by the program. If the program generates and MD5 checksums 100,000 random strings per second (roughly what a 2GHz Athlon should be capable of) then the correct string should appear in about one hundred million years.


In fairness, it should be noted that this program could produce the wrong output as the MD5 checksum algorithm is known to not necessarily produce different hash values for different input values (even if the input values are as short as 16 bytes). See ariels' md5 hash function writeup for details.

The input value to the MD5 algorithm in this program is the 12 character string "Hello world\n". Since this string is four bytes shorter than the sixteen byte value computed by the MD5 function, it isn't clear if there is another different 12 character string (using the same character set as used by this program) that results in the same MD5 hash value as "Hello world\n" generates. This may not seem very important but a program which is going to run for one hundred million years really should use an algorithm which is known to be correct!

P.S. Don't try this at home . . .


Here's a few questions for the cryptology folks or those with a few hundred million years of CPU cycles to burn:

  • An MD5 checksum is 16 bytes long. Each of the 256 different byte sequences of length one generate different MD5 checksums. On the other hand, there must be many pairs of byte sequences of length seventeen which both generate the same MD5 checksum.

    Question: are there any pairs of byte sequences shorter than 16 bytes which both generate the same MD5 checksum?

    if the answer is no then the program below will, eventually, produce the correct answer. If the answer is yes then more work is required before we can tell if the program necessarily eventually produces the correct answer.

  • Is there a second twelve character string containing characters from the set a-z, A-Z, space and newline which generates an MD5 checksum equal to the one generated for the twelve character string "Hello world\n"?

    If the answer is yes then the program below might produce the wrong answer. If the answer is no then the program below will, eventually, produce the correct answer.

One last question:

Assume:
  • that computers will continue to get faster and faster over time and that humanity survives long enough for the algorithm illustrated by this program to run to completion.
  • that whatever computer the program is started on will continue to operate without interruption until the program terminates successfully.
  • that computers continue to increase in speed at a long term average rate of a doubling in performance every two years.
  • that if you start the program on a current vintage (i.e. 2003) computer then it will take exactly 100 million years to get a result.
In which year's January should the program be started (on a then current computer) in order to get the correct result as quickly as possible using a single computer?

Hint: if all of the assumptions are true then many of the folks who read this writeup in 2003 will almost certainly still be alive when it comes time to start this program. See my homenode for the answer.


/*
 * Print's "Hello world\n" to stdout.
 *
 * How it works:  it generates strings of randomly selected letters,
 * spaces and newline characters and computes the MD5 checksum of
 * each string.  Once it get's a string whose MD5 checksum matches
 * the MD5 checksum of "Hello world\n", it prints the string and
 * terminates.
 *
 * N.B. This program uses the standard srandom and random functions to
 * generate the random strings.  Make sure that your implementation of
 * these functions has sufficient entropy to give you a decent chance
 * of generating the "Hello world\n" string!
 */

/*
 * md5data is a routine which computes the MD5 checksum of
 * the specified data bytes and returns the 16-byte checksum
 * into the 4 element array csum.
 * Many MD5 implementations are available on the 'net.  Pick your
 * favourite one (or use the one in the md5 hash function node) and
 * write an interface routine for it called md5data which takes
 * the parameters described below.
 */

extern void md5data( void *data, int length, int csum[] );

/*
 * pre-computed MD5 checksum of "Hello world\n"
 */

int md5[4] = { 0xf0ef7081, 0xe1539ac0, 0x0ef5b761, 0xb4fb01b3 };

main()
{
    srandom(0);
    while (1) {
        char msg[13];
        int tmp[4];
        int i;
        for ( i = 0; i < 12; i += 1 ) {
            msg[i] =
            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ \n"[
            random() % (2 * 26 + 2)
            ];
        }
        msg[12] = '\0';
        md5data(msg,strlen(msg),tmp);
        if ( md5[0] == tmp[0]
        &&   md5[1] == tmp[1]
        &&   md5[2] == tmp[2]
        &&   md5[3] == tmp[3] ) {
            write(1,msg,strlen(msg));
            exit(0);
        }
    }
}

Log in or registerto write something here or to contact authors.