#!/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; }
	
