字谜平方数

作者:Andrei Osipov

https://projecteuler.net/problem=98

将单词 CARE 中的每个字母分别替换为 1、2、9 和 6,我们可以得到一个平方数:1296 = 36²。值得注意的是,使用相同的数字替换,其字谜 RACE 也能构成一个平方数:9216 = 96²。我们将 CARE(和 RACE)称为平方字谜词对,并进一步规定不允许出现前导零,也不允许不同的字母具有相同的数字值。

使用 words.txt https://projecteuler.net/project/resources/p098_words.txt(一个包含近两千个常用英语单词的 16K 文本文件),找出所有平方字谜词对(回文词不视为自身的字谜)。

由任何此类词对成员构成的最大平方数是多少?

注意:所有形成的字谜都必须包含在给定的文本文件中。

源代码:prob098-andreoss.pl

use v6;

sub correspond([$word1, $word2], [$num1, $num2]) {
    $word2.trans($word1 => ~$num1) eq $num2   &&
    $num2.trans( ~$num1 => $word1) eq $word2;

}

sub anagrams(@x) {
    my %aux;
    my %result;

    %aux{$_.comb.sort.join}.push: $_
        for @x;

    for %aux.kv -> $k, @v {
        next if +@v < 2; ;
        %result{@v[0].chars}.push:
                +@v == 2
                  ?? @v.item
                  !! |@v.combinations(2).map(*.item);
    }

    %result;
}


sub MAIN(Bool :$verbose = False,
         Str  :$file    = $*SPEC.catdir($*PROGRAM-NAME.IO.dirname, 'words.txt')) {

    die "$file is missing" unless $file.IO.e;

    my @words = sort unique $file.IO.slurp.split: / <[,"]>+ /;

    my %words   =  anagrams(@words);
    my $longest-word = %words.keys.max;

    my %squares =  anagrams(
        (1 ... (10**($longest-word + 1).sqrt)) »**» 2
    );

    say max do for 3 ... $longest-word -> \size {
        next unless %words{size};
        |do for @(%words{size}) -> @pair {
            next unless %squares{size};
            |do for @(%squares{size}) -> @nums {
                if correspond(@pair, @nums) {
                    $verbose and say "@pair[] => @nums[]" ;
                    max @nums;
                }
            }
        }
    }
}