#!/usr/bin/env perl use 5.010; use strict; use warnings; use autodie; # Possibly read from command line, database, file, etc. my @in_patterns = qw{..AA.BB... AB.BA.......}; # Prefer exclusion (blacklist) over inclusion (whitelist). # Here, exclude proper nouns # and any words with non-alphabetic characters. # Note: in other scenarios, whitelists are better; # e.g. only allow access to X, Y & Z. my $blacklist_re = qr{(?:^[A-Z]|[^A-Za-z])}; # Point to your preferred dictionary. Some on my system: #my $dict = '/usr/share/dict/words'; # --> linux.words my $dict = '/usr/share/dict/strine'; # --> australian-english open my $dict_fh, '<', $dict; for my $in_pat (@in_patterns) { say "*** Input Pattern: $in_pat"; my $len = length $in_pat; my $match_re = ''; my %seen; my $count = 0; for my $char (split //, $in_pat) { if ($char eq '.') { $match_re .= '.'; } elsif (! $seen{$char}) { $match_re .= '(.)'; $seen{$char} = ++$count; } else { $match_re .= "\\$seen{$char}"; } } say "*** Match Pattern: $match_re"; my $qr_re = qr{^$match_re$}; say "*** QR Regex: $qr_re"; seek $dict_fh, 0, 0; while (<$dict_fh>) { chomp; next unless length($_) eq $len; next if $_ =~ $blacklist_re; next unless $_ =~ $qr_re; say; } } #### *** Input Pattern: ..AA.BB... *** Match Pattern: ..(.)\1.(.)\2... *** QR Regex: (?^:^..(.)\1.(.)\2...$) barrelling barrenness ... tunnellers tunnelling *** Input Pattern: AB.BA....... *** Match Pattern: (.)(.).\2\1....... *** QR Regex: (?^:^(.)(.).\2\1.......$) minimisation monomaniacal ... reverberates secessionist