#! perl -slw use strict; use Inline::Files; #! Not necessary for the algorithm. #! Just convenience in my test program #! If anyone else gets the following warnings from the #! above module, please let me know. =pod Comment only Use of uninitialized value in length at e:/Perl/site/lib/Inline/Files/Virtual.pm line 89, chunk 1. Use of uninitialized value in transliteration (tr///) at e:/Perl/site/lib/Inline/Files/Virtual.pm line 167, chunk 1. =cut #! Some silly hash keys for testing purposes. my @keys = qw(one two three four five six seven eight nine); #! Build an array of hashes from the __DATA__ section. #! The array above as keys, the words from each line as values my @AoH; push @AoH, do{ my $i=0; +{ map{ $keys[$i++] => $_ } split } } while ; #! Build a lookup table from one (any) hash's values. my %lookup = do{ my $i=1; map{ $_ => $i++ } values %{$AoH[0]} }; #! Build an array of substitute strings, mapping each value to a single char. #! I've used an offset of 65 to make things readable when testing. #! Start at chr(1) if your hashes have more than 222 values. #! You might need to specify [no utf-8] if you use values above 127? I'm not sure. my @subs; push @subs, join'', map{ chr 65+$lookup{$_} } values %{$_} for @AoH; #! XOR every substitute with every substitute, count the nuls in the result #! Accumulate them in an array in the same order as the subs. my @fits = ( (0)x@subs ); for my $i (0 .. $#subs) { $fits[$i] += scalar ($subs[$i] ^ $_) =~ tr/\0// for @subs; } #! The sort is a slightly funky (I wonder where I got that word from:) version of the ST sort. #! It feeds in and sorts on the values of the array and feeds out the indices of the sorted values. my @sorted = map{ $_->[1] } sort{ $b->[0] <=> $a->[0] } #! Descending sort, higher is better fit. map{ [ $fits[$_] => $_ ] } 0 .. $#fits; #! Output the values sets ordered by and prefixed with their relative 'fit'. print OUTPUT "$fits[$_] : @{[ values %{$AoH[$_]} ]}\n" for @sorted;