裏 RjpWiki

Julia ときどき R, Python によるコンピュータプログラム,コンピュータ・サイエンス,統計学

素数の日付を含む最長期間

2017年05月30日 | ブログラミング

素数の日付を含む最長期間

締め切りが 2017/05/30 10:00 AM なので,その 1 分後に投稿されるように予約

設問

日付をYYYYMMDD形式で表現し、8桁の数値としてみたとき、その値が素数かどうかを判定します。
1970年1月1日~2019年12月31日までの50年間のうち、素数がちょうど n 個含まれる期間で最長のものを考え、その日数を求めます。
なお、日数は両端の日付を含んで数えるものとします。
また、閏年は考慮するものとします。

例えば、n = 3 のとき、以下の青色で塗りつぶした範囲が最長になり、その日数は「202」です。

2015-04-11 : 素数
2015-04-12 : 開始日
2015-05-13 : 素数
2015-08-21 : 素数
2015-10-11 : 素数
2015-10-30 : 終了日
2015-10-31 : 素数

標準入力から n が与えられたとき、その最長日数を求め、標準出力に出力してください。
なお、n は1000以下の自然数とします。

【入出力サンプル】
標準入力
3

標準出力
202

-------------------------------------

R で書くと実行時間が1秒以内に収まらない

is.prime = function(n) {
    if (n %% 2 == 0) return(FALSE)
    else if(n %% 3 == 0) return(FALSE)
    maxitr = as.integer(sqrt(n))
    i = 1
    repeat {
        i = i+4
        if (i > maxitr) return(TRUE)
        else if (n %% i == 0) return(n == i)
        i = i+2
        if (i > maxitr) return(TRUE)
        else if (n %% i == 0) return(n == i)
    }
}

J.day = function(iy, jm, kd) {
    tmp = -(jm < 3)
    kd - 32075 + (1461 * (iy + 4800 + tmp))%/%4 + (367 * (jm - 2 - tmp * 12))%/%12 - (3 * ((iy + 4900 + tmp)%/%100))%/%4
}

date2 = function(jul) {
    l = jul + 68569
    n = (4 * l)%/%146097
    l = l - (146097 * n + 3)%/%4
    iy = (4000 * (l + 1))%/%1461001
    l = l - (1461 * iy)%/%4 + 31
    jm = (80 * l)%/%2447
    kd = l - (2447 * jm)%/%80
    l = jm%/%11
    jm = jm + 2 - 12 * l
    iy = 100 * (n - 49) + iy + l
    iy*10000+jm*100+kd
}

f = function(n) {
    begin = J.day(1970, 1, 1)
    end = J.day(2019, 12, 31)
    count = 0
    p.date = integer(1100)
    for (i in begin:end) {
        date = date2(i)
        if (is.prime(date)) {
            count = count+1
            p.date[count] = i
        }
    }
    Max = 0
    for (i in 1:(count-n-1)) {
        Max = max(Max, p.date[i+n+1]-p.date[i]-1)
    }
    cat(Max)
}
# f(scan(file("stdin", "r")))

# f(3) # 202
# f(10) # 413
# f(333) # 5771
# f(876) # 14708
# f(999) # 16724

awk で書いて少し速くなって,パスした

function isPrime(n,     maxitr, i) {
    if (n % 2 == 0) return 0
    else if(n % 3 == 0) return 0
    maxitr = int(sqrt(n))
    i = 1
    for (;;) {
        i = i+4
        if (i > maxitr) return 1
        else if (n % i == 0) return n == i
        i = i+2
        if (i > maxitr) return 1
        else if (n % i == 0) return n == i
    }
}

function Jday(iy, jm, kd,     tmp) {
    tmp = -(3 > jm)
    return kd - 32075 + int((1461 * (iy + 4800 + tmp))/4) + int((367 * (jm - 2 - tmp * 12))/12) - int((3 * (int((iy + 4900 + tmp)/100)))/4)
}

function revJday(jul,     l, n, iy, jm, kd) {
    l = jul + 68569
    n = int((4 * l)/146097)
    l = l - int((146097 * n + 3)/4)
    iy = int((4000 * (l + 1))/1461001)
    l = l - int((1461 * iy)/4) + 31
    jm = int((80 * l)/2447)
    kd = l - int((2447 * jm)/80)
    l = int(jm/11)
    jm = jm + 2 - 12 * l
    iy = 100 * (n - 49) + iy + l
    return iy*10000+jm*100+kd
}

function max(x, y) {
    return x >= y ? x : y
}

function f(n,     i, begin, end, count, primeDate, date, Max) {
    begin = Jday(1970, 1, 1)
    end = Jday(2019, 12, 31)
    count = 0
    for (i = begin; end >= i; i++) {
        date = revJday(i)
        if (isPrime(date)) {
        primeDate[++count] = i
        }
    }
    Max = 0
    for (i  = 1; count-n-1 >= i; i++) {
        Max = max(Max, primeDate[i+n+1]-primeDate[i]-1)
    }
    print Max
}
BEGIN {
f(3)
f(10)
f(333)
f(876)
f(999)
}

コメント
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする

PVアクセスランキング にほんブログ村

PVアクセスランキング にほんブログ村