Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re: Anagrams & Letter Banks

by Laurent_R (Canon)
on Oct 28, 2017 at 11:31 UTC ( [id://1202225]=note: print w/replies, xml ) Need Help??


in reply to Anagrams & Letter Banks

Hi dominick_t,

I looked again at the OP, especially at its original content ("long post") before you added the new introduction, and I think I finally understood what you were trying to do.

In the code below, I first traverse the array of words looking for words without repeated letters and store them in the %signatures hash (storing them in anonymous arrays, because two different words may have the same signature if they are anagrams, such as "ab" and "ba" in my list of words).

Then I read the array a second time, skip words without duplicate letters (already stored in the hash), build a signature from the de-duplicated letters; if this signature is found in the %signatures hash, then we've found a word using the same letters as one of the words with no repeated letters and can add it in the array corresponding to this hash entry.

At the end, the program prints every hash entry for which there is more than one word in the anonymous array.

#!/usr/bin/perl use strict; use warnings; my (%seen, %signatures); my @words = qw / ba ab aabb aaabbb xxyy xxxyyy baaab baba xxy xyz ABBA + dcdccd cd/; for my $word (@words) { chomp $word; # not needed here, but may be useful when reading f +rom a file or a DATA section my $word = lc $word; next if $seen{$word}++; next if $word =~ /(.).*\1/; # skip if the word has repeated lette +rs my $signature = join "", sort split //, $word; push @{$signatures{$signature}}, $word; } for my $word (@words) { chomp $word; my $word = lc $word; next unless $word =~ /(.).*\1/;; # skip words already stored (h +aving no duplicate letters) my %unique_letters = map { $_ => 1 } split //, $word; # could use + the uniqstr function of Lists::Util my $signature = join "", keys %unique_letters; push @{$signatures{$signature}}, $word if exists $signatures{$sign +ature}; } for my $key (keys %signatures) { if (scalar @{$signatures{$key}} > 1) { print "@{$signatures{$key}}\n" } }
With the data in the @words array used in the code above, I obtain the following output:
ba ab aabb aaabbb baaab baba abba cd dcdccd
which seems to be what you're looking for.

Note that is probably not how I would usually write this, my code would probably be quite a bit shorter, but I tried to avoid colloquial (too idiomatic) Perl and to keep it very simple, doing things step by step.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1202225]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (3)
As of 2024-04-16 04:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found