in reply to Cryptogram Generator
A couple of comments:
1) the open || die statement should actually be
For reasons of precedence.open IN, $infile or die "Can't open input file: $!";
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:
This way you don't have to do a search through the string each time.my %set; my $substit = ""; for (1..26) { my $randchar; do { $randchar = chr((int rand 26) + 65) } while $set{$randchar}++; $substit .= $randchar; }
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:
Now we set another array equal to this one, then call the random shuffle algorithm on it:my @alpha = split //, "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
which shuffles the array in place. Now all you need to do is get back the substitution string:my @crypt = @alpha; fisher_yates_shuffle(\@crypt);
Here's the definition of the fisher_yates_shuffle sub:my $substit = join '', @crypt;
(Taken directly from perlfaq4.)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; }
I did some benchmarking on these, and here's what I got:
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.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)
If I've messed anything up, let me know.
In Section
Code Catacombs