pseudoprimesをゴルフしましょう!


9

はじめに/背景

、最近の議論暗号チャット私は議論するために/のヘルプ挑戦されたフェルマー素数判定テストとカーマイケル数を。このテストは、a^(p-1) mod p==1常に素数に当てはまるがp、常にコンポジットには当てはまらないという前提に基づいています。カーマイケル番号は、基本的にはフェルマートのテストで最悪の敵です。取得するために同時に素数にならないように選択aする必要ある番号です。が共素数でない場合、本質的には、自明ではない因子を見つけましたpa^(p-1) mod p!=1apそして、誰もが知っているように、因数分解は非常に難しい場合があります。特に、すべての要素が十分に大きい場合。これで、Fermatテストが実際にはあまり使用されない理由がよくわかります(より優れたアルゴリズムがあります)。これは、(セキュリティの観点から)防御者としてのあなたが同じような量の作業を行わなければならない数があるためです。攻撃者(つまり、数を因数分解します)。

これらの数値が魅力的である理由がわかったので、可能な限り最短の方法で数値を生成します。必要に応じて、生成したコードを記憶することができます。

カーマイケル番号、OEISではA002997としても知られています。関連する課題はすでに
ありますが、サイズではなく速度が最適化されているため、ここからのエントリは競争力がありません。同じ議論が逆の方向にも当てはまり、ここのエントリはサイズを優先して速度とトレードオフをする可能性があります。

仕様

入力

これは標準のチャレンジなので、正または負でない整数nを入力として使用します。n必要に応じて、0または1のインデックスを付けることができます(指定してください)。

出力

出力は、必要にn応じて、-番目のカーマイケル番号または最初のnカーマイケル番号のいずれかになります(指示してください)。

仕様

整数xは、xが複合である場合にのみカーマイケル数であり、のすべての整数yについてgcd(x,y)=1、それを保持しy^(x-1) mod x==1ます。

誰が勝ちますか?

これはなので、バイトで最短のコードが優先されます!
標準のIOと抜け穴のルールが適用されます。

テストケース

最初のいくつかのカーマイケル番号は次のとおりです。

 561,1105,1729,2465,2821,6601,8911,10585,15841,
 29341,41041,46657,52633,62745,63973,75361,101101,
 115921,126217,162401,172081,188461,252601,278545,
 294409,314821,334153,340561,399001,410041,449065,
 488881,512461

回答:



6

Python 2、92バイト

f=lambda j,n=1:j and f(j-([(k/n)**~-n%n for k in range(n*n)if k/n*k%n==1]<[1]*~-n),n+1)or~-n

オンラインでお試しください!

糖蜜のように1インデックス付きで遅い。

リスト内包表記では、Dennisの方法nを使用して、すべての整数素数(nの総称)に生成してからx**~-n%n、それらすべてについて計算します。このリストを呼び出しましょうL

カーマイケル番号を検出するために、このリストを辞書式に、1からなるリストと比較しn-1ます。なぜこれが機能するのですか?

の各要素Lは正の整数です:(k/n)is coprime to n、so (k/n)**~-nis is、so (k/n)**~-n%n > 0。したがって、可能な値はL、辞書式順序 [1]*(n-1)は、完全に1 未満の 値で構成される値よりも少なくなりn-1ます。(L含めることはできません以上以下n-1のように値nを超えることはできませんn-1totatives比較が好きなので![1,1,1,1,3] < [1,1,1,1]出ています。)

n-1エントリが未満であることを確認すると、それがL確実にn合成されます。(n-1totative を持つことは素数性と同等の条件です。)そして、カーマイケル数であるための条件は、のすべての要素がL等しいことです1。したがって、この辞書式比較により、対象Lのが正確に検出されます。

Xcoder氏は、再帰的なラムダ形式に切り替えることでバイトを節約しましjた。カーマイケル番号に到達するたびにカウントダウンし、n再帰するたびにカウントアップします。したがって、一度jゼロにn-1達すると、original_value_of_j'番目のカーマイケル数に等しくなります。


5

ゼリー 12  11 バイト

-1バイトのおかげでマイルミスターXcoder(カーマイケル関数原子とそのゴルフの使用)

%Æc’=ÆP
⁹Ç#

n最初のnカーマイケル番号のリストを取得して返すモナディックリンク。

オンラインでお試しください!

どうやって?

カーマイケル関数のビルトインがあることを除いて、前の例(下記)によく似ています。これは、最小の累乗を生成し、その累乗に引き上げられた入力は、すべての整数の累乗を法として1に合同であり、その整数に素数になります。したがって、より少ないバイトで誤検知(プライム)を除外し、より高速なコードを作成できます!

%Æc’⁼ÆP - isCarmichael: number, n (any integer)
 Æc     - Carmicael function of n
%       - n modulo that
   ’    - decremented (0 for Carmichael numbers and primes)
     ÆP - is n prime? (1 for primes 0 otherwise)
    ⁼   - equal?

⁹Ç# - Main link: number, n
  # - count up finding the first n values satisfying:
 Ç  - ...condition: call the last link as a monad
⁹   - ...starting with a value of: literal 256

前の12バイト

Ṗ*%⁼Ṗ_ÆP
⁹Ç#

オンラインでお試しください!(うん、それはのためにタイムアウトしますn=3)。

どうやって?

数は、cそれが合成であり、それは任意の整数、ことは事実である場合、カーマイケル数であるxに上げ、cと合同であるxモジュロc

私たちはxx=cそれ自体が肯定的なものかどうかを確認するだけで済みます。

x=cチェックではx、累乗がmodulo にx合同であるかどうかがチェックされます。これはtrueであるため、これをチェックする必要はありません(これによりコードが短くなります)。xx

Ṗ*%⁼Ṗ_ÆP - Link 1, isCarmichaelNumber: integer c (greater than 1)
Ṗ        - pop c (uses the implicit range(c)) = [1, 2, 3, ..., c-1]
 *       - raise to the power of c (vectorises) = [1^c, 2^c, 3^c, ..., (c-1)^c]
  %      - modulo by c (vectorises) = [1^c%c, 2^c%c, 3^c%c, ..., (c-1)^c%c]
    Ṗ    - pop c = [1, 2, 3, ..., c-1]
   ⁼     - equal? (non-vectorising) = 1 if so, 0 if not
      ÆP - isPrime?(c) = 1 if so, 0 if not
     _   - subtract = 1 if Carmichael 0 if not
         -     (Note the caveat that c must be an integer greater than 1, this is because
         -      popping 1 yields [] thus the equality check will hold; same for 0,-1,...)

⁹Ç# - Main link: number, n
  # - count up finding the first n values satisfying:
 Ç  - ...condition: call the last link as a monad
⁹   - ...starting with a value of: literal 256

また、12バイトですが、Carmichaelアトムを使用して、最初の33を1分未満で計算します
マイル

組み込みのカーマイケル機能を使用して11バイト
Xcoder氏2017年

@ Mr.Xcoder私は別々に投稿されたマイルを提案するつもりでした、それからあなたのものを見て、それからあなたのコメントを見て削除しました。dvは、誰かがこれよりもマイルのコメントに類似していると考えているためかもしれませんが、あなたが単独で同じものを見つけなかったと思う理由はないので、それは奇妙な理由だと思います(私は知っています。そのようなことを何度も行ったことがあります)。必要に応じて11を投稿しますが、あなたまたはマイルがクレジットを受け取るべきだと思います。
ジョナサンアラン

@miles too ... ^
Jonathan Allan

@JonathanAllan自分で投稿してください。言及マイルと私の貢献、と私はどちらかのマイルの心を考えていない:-)(ちなみに私もマイル表示されませんでしたはコメントを: - /私の答えを投稿する前に)
ミスターXcoder

2

ECMAScript Regex、86 89バイト

警告:単項正規表現の魔法を台無しにしたくない場合は、これを読んではいけません。あなたがこの魔法を自分で理解することに挑戦したい場合は、まずECMAScriptの正規表現のいくつかの問題を解決することから始めることを強くお勧めします。1つずつ解決するための連続したネタバレのタグ付き推奨問題のリストについては、この以前の投稿参照してください

^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$))((?=(xx+?)\5*$)(?=(x+)(\6+$))\7(?!\5*$)){2,}x$

オンラインでお試しください!

# Match Carmichael numbers in the domain ^x*$ using Korselt's criterion
# N = input number (initial value of tail)
^
(?!
    # Iterate through factors \1, with \2 = \1-1, for which \2 does not divide into N-1
    (x(x+))
    (?!\2*$)           # Assert N-1 is not divisible by \2
    \1*(?=\1$)         # Assert N is divisible by \1; tail = \1
    # If the factor \1, which already passed the aboved tests, is prime, then fail the
    # outside negative lookahead, because N is not a Carmichael number.
    (?!(xx+)\3+$)
)
# Assert that N has at least 2 unique prime factors, and that all of its prime factors
# are of exactly single multiplicity (i.e. that N is square-free).
(
    (?=(xx+?)\5*$)     # \5 = smallest prime factor of tail
    (?=(x+)(\6+$))     # \6 = tail / \5 (implicitly); \7 = tool to make tail = \6
    \7                 # tail = \6
    (?!\5*$)           # Assert that tail is no longer divisible by \5, i.e. that that
                       # prime factor was of exactly single multiplicity.
){2,}
x$

この正規表現の主な魔法は、Nのすべての素因数が正確に単一の多重度であることを主張する部分にあります。これは、長さが4乗のMatch文字列Find the Smoothest Number正規表現で使用されるのと同じトリックです。最小の素因数で暗黙の除算を繰り返します。

また、Nに完全な二乗係数がない(つまり、Nに二乗がない)ことを直接テストすることもできます。これは、私の豊富な数の正規表現の投稿の段落で簡単に説明されている乗算アルゴリズムのバリアントを使用して、数が完全な正方形であるかどうかをテストします。これはスポイラーです。ですから、高度な単項正規表現の魔法を台無しにしたくない場合は、これ以上読み進めないでください。この魔法を自分で理解するためにショットを撮りたい場合は、この以前の投稿の連続したネタバレのタグが付いた推奨問題のリストからいくつかの問題を解決することから始めて、数学的な洞察を個別に考え出そうとすることを強くお勧めします。

ただし、このアルゴリズムでこの問題を使用しても、メリットはありません。その結果、97バイトのサイズが大きくなり、正規表現が遅くなります。素数の多重度テスト(1つのループで少なくとも2つの素数があり、それぞれが単一の多重度であることをアサートする)がない場合、Nが複合であることを個別にアサートする必要があります。

^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((xx+)\5*(?=\5$))?(x(x*))(?=(\6*)\7+$)\6*$\8)(xx+)\9+$

オンラインでお試しください!


 ^
 (?!
     # Iterate through factors \1, with \2 = \1-1, for which \2 does not divide into N-1
     (x(x+))
     (?!\2*$)           # Assert N-1 is not divisible by \2
     \1*(?=\1$)         # Assert N is divisible by \1; tail = \1
     # If the factor \1, which already passed the aboved tests, is prime, then fail the
     # outside negative lookahead, because N is not a Carmichael number.
     (?!(xx+)\3+$)
 |
 # Assert that N is square-free, i.e. has no divisor >1 that is a perfect square.
     ((xx+)\5*(?=\5$))?  # cycle tail through all of the divisors of N, including N itself
     # Match iff tail is a perfect square
     (x(x*))             # \6 = potential square root; \7 = \6 - 1
     (?=
         (\6*)\7+$       # iff \6 * \6 == our number, then the first match here must result in \8 == 0
     )
     \6*$\8              # test for divisibility by \6 and for \8 == 0 simultaneously
 )
 (xx+)\9+$               # Assert that N is composite
 


2
(厳密に言えば、これはdecision-problem答えですが、課題はsequence課題です。)おそらく、より強力な正規表現のバリアントでは、利用可能な二乗除数のより直接的なテストがあるでしょうか?
Neil

@ニールそうです、私は二乗除数を直接テストすることでゴルフをすることができます。ECMAでは、追加の機能は必要ありません。しかし、それはそれをはるかに遅くします(そして、私はそれをネタバレタグの下に隠したいと思います)。両方のバージョンを含めたいと思います。
デッドコード'25年

はい、それは私がすでに書いた正規表現の質問を見つけることは非常に面倒です、それは正しいタイプの挑戦ではありません。回答を削除する必要がありますか?
デッドコード'25年

@ニールここに行きます。私はあなたのアイデアを使ってアルゴリズムを実装しました。これがおそらく私が自分でそれを追求することを考えなかった理由です。is-compositeテストが必要なため、実際にはより長い正規表現になります。
デッドコード

(サイトルールの下では、答えを削除する必要があります。はい)。Retina正規表現などの追加機能を使用すると^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((^x|xx\5){2,})\4*$)(xx+)\6+$、それを、またはおそらく72バイト未満にまで減らすことができると思いました。
Neil


1

Retina、94バイト

\d*$
x
"$+"}/^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((^x|xx\5){2,})\4*$)(xx+)\6+$/^+`$
x
x

オンラインでお試しください!1インデックス付き。高速ではないためn>5、TIOでタイムアウトします。説明:

\d*$
x

現在の値を増やします。最初のパスでは、これもn出力バッファーから削除されます(ただし、$+引き続きアクセスできます)。

/^(?!(x(x+))(?!\2*$)\1*(?=\1$)(?!(xx+)\3+$)|((^x|xx\5){2,})\4*$)(xx+)\6+$/

現在の値がカーマイケル数かどうかをテストします。これは、@ Deadcodeの代替アルゴリズムを使用します。これは、.NET / Perl / PCRE正規表現を使用して記述された方が平方検出が短いためです。

^+`

現在の値がカーマイケル数になるまで繰り返します。

$
x

現在の値を増やします。

"$+"}

最初の増分と上記のループn時間を繰り返します。

x

結果を10進数に変換します。


0

Haskell、95バイト

s=filter
c n=s(\x->let l=s((1==).gcd x)f;f=[1..x-1]in l/=f&&all(\y->y^(x-1)`mod`x==1)l)[1..]!!n

オンラインでお試しください!

Degolfed:

-- function to filter out Carmichael numbers
filterFunction x = 
    let coprimes = filter ((1 ==) . gcd x) lesserNumbers
        lesserNumbers = [1 .. x - 1]
    in
        -- the number x is Carmichael if it is not prime
        lesserNumbers /= coprimes && 
            -- and all of its coprimes satisfy the equation
            all (\y -> y ^ (x - 1) `mod` x == 1) coprimes

-- get n'th Carmichael number (zero-based)
c n = filter filterFunction [1..] !! n
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.