素因数分解


Twitter素数がどうのこうのというのを見かけたので書いてみた。


元々のは素数計算(素数の生成?)のようでしたが、見た時に頭に浮かんだのは素因数分解だったので・・・。書いてる途中で気付きましたが、まあ・・・。

factor.pl

#!perl
use strict;
use warnings;

my $input = $ARGV[0] or die 'no input error.';
if($input =~ /^\d+$/) {
    print " $input = (1)";
    print " * $_" for &factor($input);
}
exit;

sub factor {
    my $value = shift or return;
    my @plist;
    my $f; $f = sub {
        my $p = shift;
        while($value % $p == 0) {
            push(@plist, $p);
            $value /= $p;
        }
    };
    $f->(2);
    for(my $i = 3; $i <= $value; $i += 2) {
        $f->($i);
    }
    return @plist;
}


こんな感じで。


大きい素数を持つ数字を扱うとかなり処理に時間がかかります。

素数の性質って、2以外は奇数、ということくらいしか思いつかなかったので・・・。

※ちなみに素因数分解する数字の1/2までの素数を予め持ってるっつーのが効率良いのかな。


最初、再帰的に処理するのかな〜。とか思い浮かべながら書いてたんですけど必要無かったですね。

まっ関数内関数を書いてみたかったんですけどね。んー、どういう場面で使えばいいのかは掴めてませんが・・・。

とりあえず、これくらいのならば10分前後で書けるようになったかな。




prime.pl

#!perl
use strict;
use warnings;

my $input = $ARGV[0] or die 'no input error.';
my $continue = $ARGV[1];
if($input =~ /^\d+$/) {
    print " prime:\n";
    print "\t> $_\n" for &prime($input, $continue);
}
exit;

sub prime {
    my $value = shift or return;
    my $start = shift;
    unless($start) { $start = 2; }
    my @plist;
    my $f; $f = sub {
        my $p = shift or return;
        for(my $i = 2; $i <= $p / 2; $i++) {
            if($p % $i == 0) { return; }
        }
        return 1;
    };
    for(my $p = $start; scalar(@plist) < $value; $p++) {
        if($f->($p)) { push(@plist, $p); }
    }
    return @plist;
}

ちろっと改変して、素数を算出するスクリプトにしてみました。引数個数分の素数を算出します。
Cスタイルのfor文使いまくりですが、好きなのでしかたありません。。。

基本的な部分は変わって無いので重いです。。。