1. Qiita
  2. 投稿
  3. Ruby

8桁表示で素数日や連続素数日を探す

  • 5
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

よく「今日は素数の日だ」なんて話を聞いて気になったので探してみることにしました。

素数日とは

素数日とはyyyymmddで数値にした時に素数となる日付のことと定義します。
例えば2015年11月27日は20151127が素数なので素数日です。

素数は無限にありますので、素数日も無限にあると期待されます。

普通に探す

とりあえず2015年の素数日を探してみましょう。
こんな感じでしょうか?

require 'prime'
require 'date'

puts [*Date.new(2015, 1, 1).upto(Date.new(2015, 12, 31))].flat_map{|d|
    Prime.prime?(d.strftime('%Y%m%d').to_i) ? [d.to_s] : []
}
2015-01-11
2015-01-31
2015-02-27
2015-03-03
2015-03-27
2015-04-11
2015-05-13
2015-08-21
2015-10-11
2015-10-31
2015-11-27
2015-12-21
2015-12-27

13日、意外と少ないです。実はここ100年では1923年と並んで素数日の数が最小の年なんですね。(明日使える豆知識1)
多い時は30日以上あるのでかなり偏っていることがうかがえます。

双子素数日

ところで、双子素数といって、差が2の素数の組はよく研究対象になります。というわけで差が2日の双子素数日を探してみましょう。

require 'prime'
require 'date'

[*Date.new(2015, 1, 1).upto(Date.new(2020, 12, 31))].flat_map{|d|
    Prime.prime?(d.strftime('%Y%m%d').to_i) ? [d] : []
}.each_cons(2) {|d1, d2|
    puts d1, d2, "\n" if (d2-d1).to_i == 2
}
2016-04-01
2016-04-03

2016-10-19
2016-10-21

2017-03-01
2017-03-03

2017-09-01
2017-09-03

2019-02-27
2019-03-01

2020-01-09
2020-01-11

2020-01-21
2020-01-23

2020-07-21
2020-07-23

思ったよりありますね。ちなみに双子素数が無限にあるかどうかは未解決問題なので、双子素数日も無限にあるかどうかは不明です。月またぎでイレギュラーなものもあるのでなんとも言えませんが…

三つ子素数日

さらに三つ子素数というものを考えてみます。三つ子素数とは(p, p+2, p+6)または(p, p+4, p+6)の形のもので、(p, p+2, p+4)の形ではありません。なぜならばこの場合、必ず3の倍数を含むからです。

しかしながら、(当日・2日後・4日後)という素数日は存在の可能性があります。月や年の変わり目を含めば良いからです。

require 'prime'
require 'date'

[*Date.new(2015, 1, 1).upto(Date.new(2100, 12, 31))].flat_map{|d|
    Prime.prime?(d.strftime('%Y%m%d').to_i) ? [d] : []
}.each_cons(3) {|d1, d2, d3|
    if (d2-d1).to_i == 2 && (d3-d2).to_i == 2
        puts d1, d2, d3, "\n"
    end
}
2085-06-29
2085-07-01
2085-07-03

2087-04-29
2087-05-01
2087-05-03

というわけで、残念ながら次は2085年のようなので生きてるうちには拝めなさそうです(明日使える豆知識2)。

最後にタイトルにある連続素数日ですが、これも素数の場合は普通にはありませんね。(n, n+1)は必ずどちらかが2の倍数だからです。しかし、素数日の場合は月や年をまたげるのでした。31日(or2月29日)だけ起こる可能性があります。

require 'prime'
require 'date'

[*Date.new(2015, 1, 1).upto(Date.new(2020, 12, 31))].flat_map{|d|
    Prime.prime?(d.strftime('%Y%m%d').to_i) ? [d] : []
}.each_cons(2) {|d1, d2|
    puts d1, d2, "\n" if (d2-d1).to_i == 1
}
2017-08-31
2017-09-01

2018-07-31
2018-08-01

というわけで、次は2017年らしいです。ちなみに20201231-20210101は年をまたいだ連続素数日になります。これは1987-88シーズン以来33年ぶりの出来事です。(明日使える豆知識3)

まとめ

素数日、というものを定義して簡単に分布を調べてみました。結構多いなというのが印象です。コードとしては偶数の日を調べる必要はないし、最後の方はすべての日付を調べる必要がないので、もうちょっと高速に探す方法に直せそうです。