スキップしてメイン コンテンツに移動

Project Euler - Problem 35

問題

  • 原文

    How many circular primes are there below one million?

  • 日本語訳

    100万未満の巡回素数は何個か?

解答

回転させた数値がすべて素数ということは、すべての桁が奇数でなければいけません(ただし2を除く)。

追記

匿名氏にコメントでご指摘頂いたのでコードを一部修正しました。 いずれかの桁に5がある場合も、回転させると必ず5の倍数が現れるので除外できます。

もっと追記

前の修正に間違いが入っているのをご指摘頂いたので修正しました。 5自体は素数なので、巻き添えで除外してはいけません。

#!/usr/bin/env perl

use strict;
use warnings;
use feature qw/say state/;
use List::MoreUtils qw/all none/;

sub is_prime($) {
  state %memos;
  my $n = shift;
  return 0 if $n < 2;
  return 1 if $n == 2;
  return 1 if $n == 3;
  return $memos{$n} if exists $memos{$n};
  $memos{$n} = none { $n % $_ == 0 } 2 .. sqrt $n;
}

sub rotate($) {
  my $n = shift;
  substr($n, 1) . substr($n, 0, 1);
}

sub rotations($) {
  my $n = shift;
  my %seen = ($n => 1);
  $seen{$n} = 1 until exists $seen{$n = rotate $n};
  keys %seen;
}

sub is_circular_prime($) {
  state %memos;
  my $n = shift;
  return 0 if $n =~ /[024568]/ and $n != 2 and $n != 5;
  return $memos{$n} if exists $memos{$n};

  my @rotations = rotations $n;
  my $is_circular_prime = all { is_prime $_ } @rotations;
  (@memos{@rotations} = ($is_circular_prime) x @rotations)[0];
}

say 0 + grep { is_circular_prime $_ } 1 .. 1_000_000;

コメント

  1. どこかの桁に "5" が含まれている数も除外できますよ。

    返信削除
  2. あ、なるほど。ご指摘有り難うございます。

    返信削除
  3. コードを実行してみたのですが、答えが本当の答えより 1 だけ小さいようです。

    もしかして 5 も除外されてませんか?

    返信削除
  4. ご指摘有り難うございます。恥ずかしながらその通りです。
    直したら確認するべきでした。気をつけます。

    返信削除

コメントを投稿