LoginSignup
0
0

More than 5 years have passed since last update.

その年の「素数の日」を探した話 (エラトステネスの篩のPerl実装)

Posted at

この記事は?

とある場所で発表させてもらった「素数休日をとろう」の実装のまとめです。
 SlideShare:素数休日をとろう

「素数の日」の定義

年月日を並べた8桁の数字、例えば2016/6/16であれば20160616など対象とし、
その数値が素数であれば「素数の日」とここでは定義しています。
この定義に従うと、20160616は2の倍数であるため素数の日ではありませんが、
20160611は素数の日です。

実装

環境情報

項目 情報
OS CentOS Linux release 7.2.1511
Perl v5.16.3

手法

素数算出には「エラトステネスの篩」アルゴリズムを採用
Wikipedia:エラトステネスの篩

コード

PrimeDate.pl
#!/usr/bin/perl
#------------------------------------
# Author        : Hiroki.lzh
# Descripsion   : Output PrimeDate of the year
#------------------------------------

#---------------------------
#  [Module] Using Modules
#---------------------------
use strict;
use warnings;
use Getopt::Long;
use Time::Local;

#---------------------------
#  [Config] System Config
#---------------------------
my $version     ="1";
my $revision    ="0";
my $revdate     ="2015/06/04";
my $sysname     ="PrimeDate";

#---------------------------
#  [Func] SetOption
#       Return
#               NUM = Normal Exec, Output -y YEAR or this year.
#       Exit
#               0 = Normal Exit
#---------------------------
sub SetOption() {
        my %opts = ();
        GetOptions(\%opts, 'version', 'help', 'year=i');

        if( defined $opts{version} == 1) {
                printf("%s ver.%s.%s (created %s)\n", $sysname, $version, $revision, $revdate);
                exit 0;
        } elsif ( defined $opts{help} == 1) {
                print   "Usage: $0 [-hv] [-y] YEAR \n\n".
                        "Options:\n".
                        "  -h --help \t Give this help.\n".
                        "  -v --version \t Display version number.\n".
                        "  -y num or --year num \t Set Year to investigate.\n";
                exit 0;
        } elsif ( defined $opts{year} == 1) {
                return $opts{year};
        } else {
                (my $sec, my $min,my $hour,my $mday, my $mon, my $year) = localtime(time);
                $year += 1900;
                return $year;
        }
}

#---------------------------
#  [Func] GetLastDay
#       Input
#               $1 = Year
#               $2 = Number of Month
#       Return
#               NUM = Last day of the month
#               -1  = Error
#---------------------------
sub GetLastDay {
        my($year, $mon) = @_;
        if(!$year || !$mon) {return -1;}
        #if($year < 1900 || $year > 2023) {return -1;}
        if($mon < 1 || $mon > 12) {return -1;}
        if($mon == 12) {$mon = 0;}
        my $time = timelocal(0, 0, 0, 1, $mon, $year-1900);
        $time -= 60*60*24;
        my @date = localtime($time);
        return $date[3];
}

#---------------------------
#  [Func] PrimeNumbers
#       Input
#               $_[0] = YEAR
#       Return
#               @prime_numbers = Prime List
#---------------------------
sub PrimeNumbers {
        my $chk = $_[0];
        my @numbers = (2..$chk);
        my @prime_numbers;
        my $chksqrt = sqrt $chk;
        while(1){
                if($numbers[0] > $chksqrt){
                        push @prime_numbers, @numbers;
                        last;
                }
                my $number = shift @numbers;
                #print "DEBUG :: $number / $chksqrt \n";
                push @prime_numbers, $number;
                @numbers = grep { $_ % $number != 0 } @numbers;
        }

        return @prime_numbers;
}

#---------------------------
#  [Main] Main Programs
#---------------------------

# OptionCheck
my $year = &SetOption();

print "=================\n";
print "YEAR: $year\n";
# Get Target Days
print "=================\n";
print "TargetList:\n";
my @targets;
for (my $month = 1; $month < 13; $month++){
        my $lastday = &GetLastDay($year,$month);
        for (my $day = 1; $day < $lastday+1 ; $day++){
                my $setday = sprintf("%04d%02d%02d",$year,$month,$day);
                push(@targets,$setday);
                print "$setday\n";
        }
}

# Check Prime Number of Year
print "=================\n";
print "Prime Numbers of $year:\n";

## Get the last day of the year 's data
my @numbers = &PrimeNumbers($targets[$#targets]);

foreach my $cnt (@targets) {
        if (grep {$_ == $cnt} @numbers ){
                print " ----> $cnt is Prime Date!\n";
        } else {
                #print "$cnt is not prime... \n";
        }
}

以上

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0