From: spl@szechuan.ucsd.edu (Steve Lamont)
Newsgroups: alt.discordia
Subject: discord generator
Summary: wombat
Date: 8 Oct 92 16:41:53 GMT
Organization: University of Calif., San Diego/Microscopy and Imaging Resource
NNTP-Posting-Host: szechuan.ucsd.edu

Here's a free association generator that might be amusing.  I wrote it
in a few minutes while waiting for a friend to show up.  Unshar it,
make it, and then feed your favorite text, such as the Principia
Discordia, into it via standard input.  Feed the output to nroff with
the -ms macros.  For example,

discord < principia | nroff -ms | mail -s "threat" bush@white.house.gov

The algorithm is stupid, the code is pretty gross, and the data
structures are completely brain damaged, but it comes up with some
amusing juxtapositions every once and a while.  Oh, yeah, it's slow
and a memory hog, too.  It even uses a bubble sort just to be
perverse.  Just the thing for burning those excess CPU cycles.

							spl

 - - - - gnaw on dotted line - - - -
#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#
#	Run the following text with /bin/sh to create:
#	  Makefile
#	  discord.c
#
sed 's/^X//' << 'SHAR_EOF' > Makefile &&
X# Released upon the public domain.
X
XCC	= gcc
XOPT	= -O2
XDEBUG	= -g
XFNORD	=
XCFLAGS	= $(OPT) $(DEBUG) $(FNORD)
XLFLAGS	=
X
Xdiscord:	discord.c
X	$(CC) $(CFLAGS) -o discord discord.c $(LFLAGS)
SHAR_EOF
chmod 0644 Makefile || echo "restore of Makefile fails"
sed 's/^X//' << 'SHAR_EOF' > discord.c &&
X#include <stdio.h>
X#include <string.h>
X#include <ctype.h>
X#include <sys/types.h>
X#include <sys/time.h>
X
X/*
X * Copyright?  Hell, if asked, I'll deny I even wrote this bit of trash.
X */
X
Xtypedef struct Words {
X    char *word;
X    int visited;
X    int nfollows;
X    int *counts;
X    int class;
X    struct Words **follows;
X    struct Words *before;
X    struct Words *after;
X} Words;
X
Xenum { FullStop, Punct, Word };
X
Xchar *fetchWord();
XWords *addWord( Words **, char * );
XWords *newWord( char * );
Xvoid erisify( Words *, long, long );
Xvoid setup();
Xvoid tally( Words *, Words * );
Xvoid search( long, Words * );
XWords *chase( Words *, long * );
Xvoid fsort( Words * );
XWords *findNewWord( Words * );
X
Xint wordcount = 0;
X
Xint tgrid[128] = { 0 };
X
Xint main( int argc, char **argv )
X
X{
X
X    char *word;
X    Words *w = ( Words *) NULL;
X    Words *last;
X
X    setup();
X
X    last = addWord( &w, fetchWord() );
X    while ( word = fetchWord() ) {
X
X	Words *wd;
X
X	wd = addWord( &w, word );
X	tally( last, wd );
X	last = wd;
X
X    }	
X
X    srandom( ( int ) time( ( time_t *) NULL ) );
X
X    erisify( w, ( random() % 10 ) + 1, random() % wordcount );
X
X    exit( 0 );
X
X}
X
Xvoid setup()
X
X{
X
X    tgrid['@'] = 1;
X    tgrid['#'] = 1;
X    tgrid['$'] = 1;
X    tgrid['%'] = 1;
X    tgrid['^'] = 1;
X    tgrid['&'] = 1;
X    tgrid['*'] = 1;
X    tgrid['('] = 1;
X    tgrid[')'] = 1;
X    tgrid['_'] = 1;
X    tgrid['-'] = 1;
X    tgrid['='] = 1;
X    tgrid['+'] = 1;
X    tgrid['|'] = 1;
X    tgrid['\\'] = 1;
X    tgrid['`'] = 1;
X    tgrid['~'] = 1;
X    tgrid['['] = 1;
X    tgrid[']'] = 1;
X    tgrid['{'] = 1;
X    tgrid['}'] = 1;
X    tgrid[':'] = 1;
X    tgrid[';'] = 1;
X    tgrid['\"'] = 1;
X    tgrid['<'] = 1;
X    tgrid['>'] = 1;
X    tgrid['/'] = 1;
X
X}
X
Xchar *fetchWord()
X
X{
X
X    static char text[30];
X    int ch;
X    int tp = 1;
X    char *txt;
X
X    while ( ( ( ch = getchar() ) != EOF ) && 
X	    ( ( isspace( ch ) || 
X	        isdigit( ch ) ||
X	        tgrid[ch] ) ) )
X	;
X
X    if ( ch != EOF ) {
X
X	text[0] = ch;
X	if ( !ispunct( ch ) ) {
X
X	    while ( ( ( isalnum( text[tp] = getchar() ) ) ||
X		     ( text[tp] == '\'' ) ) && ( tp < 30 ) )
X		tp++;
X		
X	    if ( ( text[0] != 'M' ) || 
X		 ( text[1] != 'r' ) ||
X		 ( text[2] != '.' ) )
X		ungetc( text[tp], stdin );
X	    else
X		tp++;
X
X	}
X	
X	text[tp] = '\0';
X	
X	txt = text;
X
X    } else
X	txt = ( char *) NULL;
X
X    return txt;
X
X}
X
XWords *addWord( Words **w, char *word )
X
X{
X
X    Words *nw;
X
X    if ( !*w )
X	*w = nw = newWord( word );
X    else {
X
X	int s = strcmp( ( *w )->word, word );
X
X	if ( s < 0 )
X	    nw = addWord( &( *w )->after, word );
X	else if ( s > 0 )
X	    nw = addWord( &( *w )->before, word );
X	else
X	    nw = *w;
X
X    }
X
X    return nw;
X
X}
X
XWords *newWord( char *word )
X
X{
X
X    static int left = 0;
X    static Words *w;
X    
X    wordcount++;
X    if ( !left )
X	w = ( Words *) calloc( sizeof( Words ), left = 23768 );
X
X    left--;
X    ( w + left )->word = strdup( word );
X    switch ( *word ) {
X
X      case '!':
X      case '?':
X      case '.': {
X
X	  ( w + left )->class = FullStop;
X	  break;
X
X      }
X      default: {
X
X	  ( w + left )->class = ispunct( *word ) ? Punct : Word;
X	  break;
X
X      }
X
X    }
X
X    return ( w + left );
X
X}
X
Xvoid tally( Words *last, Words *wd )
X
X{
X
X    int i;
X
X    for ( i = 0; i < last->nfollows; i++ )
X	if ( strcmp( last->follows[i]->word, wd->word ) == 0 ) {
X
X	    last->counts[i]++;
X	    return;
X
X	}
X
X    if ( last->nfollows ) {
X
X	last->follows = ( Words **) realloc( last->follows, sizeof( Words *) *
X					    ( last->nfollows + 1 ) );
X	
X	last->counts = ( int *) realloc( last->counts, sizeof( int ) *
X					( last->nfollows + 1 ) );
X	
X    } else {
X
X	last->follows = ( Words **) malloc( sizeof( Words *) *
X					    ( last->nfollows + 1 ) );
X	
X	last->counts = ( int *) malloc( sizeof( int ) *
X					( last->nfollows + 1 ) );
X
X    }
X    *( last->follows + last->nfollows ) = wd;
X    ( *( last->counts + last->nfollows ) )++;
X    last->nfollows++;
X
X}
X
Xvoid erisify( Words *w, long paragraphs, long start )
X
X{
X
X    Words *lastword = chase( w, &start );
X    int count = 0;
X    int paralen = ( random() % 5 ) + 1;
X    int capitalize = 1;
X
X    fsort( lastword );
X
X    printf( ".PP\n" );
X    do {
X
X	Words *theword;
X
X	if ( lastword->nfollows && ( lastword->class != FullStop ) )
X	    theword = findNewWord( lastword );
X	else {
X
X	    long where = random() % wordcount;
X
X	    theword = chase( w, &where );
X
X	}
X	
X	if ( capitalize )
X	    printf( "%c%s", toupper( *( lastword->word ) ), 
X		                      ( lastword->word + 1 ) );
X	else
X	    printf( "%s", lastword->word );
X
X	if ( random() % 200 == 0 )
X	    printf( " fnord" );
X	if ( ( theword->class != Punct ) &&
X	     ( theword->class != FullStop ) &&
X	     ( lastword->class != FullStop ) )
X	    printf( " " );
X	if ( !( ++count % 5 ) && 
X	      ( theword->class != Punct ) &&
X	      ( theword->class != FullStop ) &&
X	      ( lastword->class != FullStop ) )
X	    printf( "\n" );
X
X	if ( lastword->class == FullStop ) {
X
X	    printf( "\n" );
X	    if ( !( --paralen ) ) {
X
X		printf( ".PP\n" );
X		count = 0;
X		paralen = ( random() % 5 ) + 1;
X		--paragraphs;
X
X	    }
X
X	}
X	capitalize = lastword->class == FullStop;
X	fsort( lastword = theword );
X
X    } while ( paragraphs );
X
X}
X
XWords *chase( Words *w, long *count )
X
X{
X
X    Words *wd;
X
X    if ( w->before )
X	wd = chase( w->before, count );
X    if ( *count ) {
X
X	if ( --( *count ) == 0 )
X	    wd = w;
X	else if ( w->after )
X	    wd = chase( w->after, count );
X
X    }
X
X    return wd;
X
X}
X
Xvoid fsort( Words *w )
X
X{
X
X    if ( !w->visited ) {
X
X	int i;
X	int wsum;
X
X	for ( i = 0; i < w->nfollows - 1; i++ ) {
X
X	    int j;
X
X	    for ( j = i + 1; j < w->nfollows; j++ ) {
X
X		if ( w->counts[i] < w->counts[j] ) {
X
X		    int temp = w->counts[i];
X		    Words *wtemp = w->follows[i];
X
X		    w->counts[i] = w->counts[j];
X		    w->follows[i] = w->follows[j];
X		    
X		    w->counts[j] = temp;
X		    w->follows[j] = wtemp;
X
X		}
X
X	    }
X
X	}
X
X	wsum = w->counts[0];
X	for ( i = 1; i < w->nfollows; i++ ) {
X
X	    wsum += w->counts[i];
X	    w->counts[i] = wsum;
X
X	}
X	w->visited = wsum;
X
X    }
X
X}
X
XWords *findNewWord( Words *w )
X
X{
X
X    int rnum = random() % w->visited;
X    int i;
X
X    for ( i = 0; i < w->nfollows - 1; i++ )
X	if ( w->counts[i] < rnum )
X	    break;
X
X    return w->follows[i];
X
X}
SHAR_EOF
chmod 0644 discord.c || echo "restore of discord.c fails"
exit 0

exit 0 # In case we skid

 - - - - - -

-- 
Steve Lamont, SciViGuy -- (619) 534-7968 -- spl@szechuan.ucsd.edu
UCSD Microscopy and Imaging Resource/UCSD Med School/La Jolla, CA 92093-0608
"Twit twit twit/Jug jug jug jug jug jug/So rudey forc'd./Tereu"
                - T. S. Eliot, "The Waste Land," III. The Fire Sermon