How to run Kragen's fifth C .signature puzzle

Last updated 1999-07-12.

Here's the program:

char b[2000], m[] = {1,-80,-1,80};
main() {
    int i,
    x=1000,
    s=2000,
    d=0;
    while(1 + (i=getchar()))
        switch(i) {
        case'f':
	    b[x]=1;
	case'g':
	    x = (x + m[d/2] + s) % s;
	    d--;
	case'+':
	    d+=2;
	case'-':
	    d+=7;
	    d%=8;
	}
    for (i = 0; i != s; i++)
	putchar(" #"[b[i]]);
}

Here's a line-by-line explanation. You should read how to run it first.

char b[2000], m[] = {1,-80,-1,80},

b is a bunch of zeroes; we'll write ones in there when we draw lines. It's conceptually an 80x25 array, 25 rows of 80 columns.

m[] tells what to add to your coordinates to move in a particular direction. To move in direction 0, you add 1; to move in direction 1, you add -80; etc.

main() {
    int i,
    x=1000,

x is the current position.

    s=2000,

s is the size of the board. We use it to avoid going off the top or bottom and crashing the program.

    d=0;

d is the direction we're going, sort of.

    while(1 + (i=getchar()))

EOF is traditionally -1. So this expression will be 0 when we hit end-of-file.

        switch(i) {

This is a very curious switch expression. There are no break;s, because break; is six characters. Instead I just fix everything up so it's OK to fall through.

        case'f':
	    b[x]=1;

For 'f', we mark our current position, then do 'g'.

	case'g':
	    x = (x + m[d/2] + s) % s;

'g' moves us forward. Originally, this expression read x += m[d], but it was not to be so simple. First, I wanted forty-five-degree turns so I could write the dragon curve as an L-system. So I divide d by 2; this gives perfect results for the dragon curve, since in the dragon curve, you never have any turns that add up to other than 90 degrees. It's probably confusing otherwise. Then I got sick of the program crashing when x ran off the top or bottom of the array, so I took its remainder when dividing by the size of the array. That takes care of the bottom, but on most computers, dividing a negative number by a positive number gives a negative remainder. So I add the size of the array first, to guarantee that what I'm dividing is positive.

	    d--;

I could have said "break;" here. But what we fall into is just '+', which we can cope with by turning '-' before we go in to cancel out the '+' effect. And 'd--;' is two characters shorter than 'break;' :)

	case'+':
	    d+=2;

This requires some explanation. '+'s final effect is to increase d by one. But we fall through into '-' from here, so we have to cancel out the '-' by adding two instead of one. And it was only one more character, while break; would have been six.

	case'-':
	    d+=7;
	    d%=8;

Again, the remainder thing bites; adding 7 instead of subtracting 1 guarantees that the result will be positive.

	}

End of switch and end of loop. Characters that are not mentioned are ignored, which is handy when generating input with .signature puzzle 4.

    for (i = 0; i != s; i++)
	putchar(" #"[b[i]]);

Fairly straightforward; for each of the characters in the array, we output either a ' ' or a '#', depending on whether that character is a 0 or a 1. Turning this long string of characters into an image is done by terminal wrap.

}

End of program.


Kragen's fifth C .signature puzzle | Kragen's home page