note btrott A couple of comments:<p> 1) the open || die statement should actually be <code> open IN, \$infile or die "Can't open input file: \$!"; </code> For reasons of precedence.<p> 2) Here are some faster algorithms. One way is to use a hash to record which characters you've already placed into your substitution string. Here's the main loop: <code> my %set; my \$substit = ""; for (1..26) { my \$randchar; do { \$randchar = chr((int rand 26) + 65) } while \$set{\$randchar}++; \$substit .= \$randchar; } </code> This way you don't have to do a search through the string each time.<p> And here's an even better way of doing it: build a random permutation of the alphabet string. To do this, we'll actually need an array: <code> my @alpha = split //, "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; </code> Now we set another array equal to this one, then call the random shuffle algorithm on it: <code> my @crypt = @alpha; fisher_yates_shuffle(\@crypt); </code> which shuffles the array in place. Now all you need to do is get back the substitution string: <code> my \$substit = join '', @crypt; </code> Here's the definition of the fisher_yates_shuffle sub: <code> sub fisher_yates_shuffle { my \$array = shift; for (my \$i = @\$array; --\$i; ) { my \$j = int rand (\$i+1); next if \$i == \$j; @\$array[\$i, \$j] = @\$array[\$j, \$i]; } return join '', @\$array; } </code> (Taken directly from perlfaq4.)<p> I did some benchmarking on these, and here's what I got: <code> Benchmark: timing 5000 iterations of orig, f_yates, hash... orig: 33 secs (23.60 usr 0.00 sys = 23.60 cpu) f_yates: 5 secs ( 2.88 usr 0.00 sys = 2.88 cpu) hash: 13 secs ( 5.68 usr 0.00 sys = 5.68 cpu) </code> where "orig" is the one you posted, "f_yates" is the one using fisher_yates_shuffle, and "hash" is the one using a hash to record seen characters.<p> If I've messed anything up, let me know. 2774 2774