#!/usr/bin/perl -w # dissociated press my $contextwords = shift @ARGV; my $outputwords = shift @ARGV; my %map = (); sub incrinmap { my ($key, $value) = @_; if (exists $map{$key}) { push @{$map{$key}}, $value; } else { $map{$key} = [ $value ]; } } sub addtomap { my ($outword, @otherwords) = @_; my $key = join " ", @otherwords; incrinmap ($key, $outword); } # contains the last several words in reverse order my @context = (); sub addword { my $word = $_; unshift @context, $word; if (@context == $contextwords + 1) { addtomap @context; pop @context; } } my @thisline; while (<>) { @thisline = split; local $_; for (@thisline) { addword; } } ######################################################################## # input done; output time. srand(time() ^ $$); sub paniccontext { # return a context that'll work in case of panics warn "resetting context from " . join (" ", @context) . "\n"; my ($key, $value) = each %map; if (defined ($key)) { @context = split /\s+/, $key; return $key; } else { return paniccontext(); } } sub randomelement { my ($list) = @_; return $$list[rand() * @$list]; } sub outputword { # look for a possible place to go from here; if there isn't one, # get a context from paniccontext. my $key = join " ", @context; if (not exists $map{$key}) { $key = paniccontext; } my $word = randomelement $map{$key}; unshift @context, $word; pop @context; print "$word "; } my $counter; for $counter (1..$outputwords) { outputword; }