Well, here is the program I wrote to judge the feasibility of the problem. The principal feature is the search trie which categorises each word successively by length, first letter and last letter. E.g., "vagabond" would be an element of the array $words[8]['v']['d'], along with "vineyard" and "vanguard". So if I needed an eight-letter word that started with 'v' and ended with 'd', I knew exactly where to look.
The wordlist used contains 24867 entries, where the longest is "electroencephalography".
function letters_only($a)
{
return preg_replace('![^a-z]!','',$a);
}
$program_start = microtime(true);
$wordlist = preg_grep('!^$!', //killing blank lines
array_map('letters_only',
array_map('strtolower',
file('wordlist.txt'))), PREG_GREP_INVERT);
// Build the table ($words_flat) and search trie ($words)
// Each element of $words_flat is an array of words that are all the same length:
// it is indexed by that length, and used to find candidate left and right words.
// $words breaks that array down further into arrays that are indexed by the
// first letter of the words they contain, then further still into arrays that are
// indexed by the last letter.
$words = array();
$words_flat = array();
foreach($wordlist as $word)
{
$length = strlen($word);
$words_flat[$length][] =
$words[$length][$word{0}][$word{$length-1}][] = $word;
}
// Should probably check these exist, eh?
$length = $argv[1];
$width = $argv[2];
// Obvious impossibilities
if(!isset($words_flat[$length]))
{
echo "No acrostics of the given length.";
exit;
}
if(!isset($words_flat[$width]))
{
echo "No acrostics of the given width.";
exit;
}
$found = false;
$acrostic = array();
shuffle($words_flat[$length]); // For variety in left and right words
$search_start = microtime(true);
foreach($words_flat[$length] as $left_word)
{
foreach($words_flat[$length] as $right_word)
{
if($right_word==$left_word) continue; //???Do we care about this?
for($i=0; $i<$length; ++$i)
{
if(!isset( $words[$width][$left_word{$i}][$right_word{$i}] )) break;
$suitable_words = $words[$width][$left_word{$i}][$right_word{$i}];
$acrostic[$i] = $suitable_words[array_rand($suitable_words)]; // Pick any one
}
if($i==$length)
{
$found = true;
break 2;
}
}
}
$program_end = microtime(true);
if($found)
{
echo join("\n",$acrostic),"\n";
}
else
{
echo "Nonesuch.\n";
}
echo "\nThis program took ",($program_end-$program_start)," seconds\n",
"to produce the above result, of which ",($program_end-$search_start),"\n",
"were spent searching.";
php -f acrostic.php 12 12
southernmost
uniprocessor
pennsylvania
episcopalian
radiophysics
stroboscopic
thoroughfare
indoeuropean
transshipped
indisputable
ombudsperson
northernmost
This program took 1.5061788558959961 seconds
to produce the above result, of which 0.20378994941711426
were spent searching.
Incidentally, it often returned results for a 12x12 double acrostic in less than 1/20 of a second of searching, and occasionally less than 1/50.