読者です 読者をやめる 読者になる 読者になる

初代Masteries

きっとモヒカンにもなれないお前たちに告げる!!!

Project Euler - Problem 21

旅行中はお休みを頂いておりましたが, そろそろ復帰します.
4月1日より, 毎週月・水・金曜日に1問ずつProject Eulerの問題に取り組んでいきます.

今後の予定ですが, ひとまず自分のスキル的に問題が解けなくなるか, 50問あたりに達した時点で, リファクタリングというか, 今まで解いた問題を再度解き直す/書きなおすというのをやってみようと思っています.
...というわけで, 今後とも宜しくおねがいします!

Problem 21

10000未満の友愛数の和を求める問題. 友愛数は親和数とも呼ぶそうです.
友愛数といえば, 「博士の愛した数式」という本に乗ってましたね.
d(n)がnの真の約数の和であるとき, d(a) = bかつd(b) = aが成り立つaとb(但しa≠b)を友愛数と定義するようです.

use strict;
use warnings;
use List::Util qw/sum/;

my @sum_factors;
my $total;

for my $i (1..9999) {
    $sum_factors[$i] = sum_factors($i);
}

for my $key (1..9999) {
    my $value = $sum_factors[$key];
    $total += $key if defined $sum_factors[$value] && $key != $value && $sum_factors[$value] == $key;
}
print "$total\n";

sub sum_factors {
    my $n = shift;

    my @factors = grep { $n % $_ == 0 } 1..sqrt($n);
    push (@factors, map { $n == $_ ** 2 ? () : $n / $_ } reverse @factors[1..$#factors]);

    return sum(@factors);
}

一旦全ての数の約数の和を求めて, そこから友愛数を求めていく感じです.