カーマイケル関数を計算する


36

タスクの説明

数論では、カーマイケル関数 λは正の整数かかり  N戻る以上の正の整数kのようにk個の各整数の乗互いに素、nは 1に等しいモジュロNを

正の整数nが与えられた場合、解はλ(n)を計算する必要があります。バイト単位の最短コードが優先されます。

プログラムは理論的には任意の大きな入力に対して機能するはずですが、効率的である必要はありません。

ヒント

すべてのλ(n)のシーケンスはOEIS A002322です。

未実装のPython実装は次のようになります

from fractions import gcd

def carmichael(n):
    coprimes = [x for x in range(1, n) if gcd(x, n) == 1]
    k = 1
    while not all(pow(x, k, n) == 1 for x in coprimes):
        k += 1
    return k

(Pythonでは、pow(A, B, C)効率的に計算しpow(A, B) % Cます。)

テストケース

Input    Output
1        1
2        1
3        2
10       4
35       12
101      100
530      52
3010     84
6511     3056
10000    500

何をしない理論的には、ここで意味ですか?入力nが16ビット整数に収まると仮定できますか?n ^λ(n)がdoubleに適合すると仮定できますか?
デニス

2
はい、はい、私は言うでしょう。のように、理論的に、ネイティブ型がarbitrarily意的に正確で大きいふりを含んでいます(これはコンセンサスだと思っていましたが、よくわかりません)。
リン

回答:



29

Python、76 73 67バイト

f=lambda n,k=1:1-any(a**-~k*~-a**k%n for a in range(n))or-~f(n,k+1)

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

さらにバイトを返すことによって保存することができたの代わりに、1

代替実装

同じアプローチを使用して、リスト内包表記を使用しない@feersumによる次の実装もあります。

f=lambda n,k=1,a=1:a/n or(a**-~k*~-a**k%n<1)*f(n,k,a+1)or-~f(n,k+1)

この実装にはO(nλ(n)時間を必要とすることに注意してください。実際にスコアを66バイト減らしながら効率を劇的に改善できますが、関数は入力2に対してTrueを返します

f=lambda n,k=1,a=1:a/n or~-a**k*a**-~k%n<1==f(n,k,a+1)or-~f(n,k+1)

バックグラウンド

定義と表記

使用される変数はすべて整数を示します。nk、およびα正の整数を表します。そしてpは正表します素数を

| Bの場合、Bはで割り切れるがある場合、すなわち、QなるようにB = QA

≡B(モッズメートル)場合とbが同じ残基モジュロ持ってメートルを場合、すなわち、M | a-b

λ(n)が最小となるKのようにK ≡1(MOD N) -すなわち、例えばそのN | a k -1nと互いに素であるすべて a に対して

F(n)が最小となるKよう2K + 1K + 1MOD N) -すなわち、例えばそのN | a k + 1(a k -1) –すべてのaに対して

λ(n)≤f(n)

nを修正し aをnと互いに素にします。

fの定義により、n | a f(n)+1(a f(n) -1)。以来およびnは、共通の素因数を持たないでもないんF(n)は1をnはその意味、| nは a f(n) -1

以来、λ(n)が最小の整数であり、kのようにN | a k -1nと互いに素であるすべての整数aについてため、λ(n)≤f(n)となります。

λ(n)= f(n)

不等式λ(n)≤f(n)をすでに確立しているので、k =λ(n)fを定義する条件、つまりn | λ(N)+1λ(N) - 1)すべてのため。この目的のために、私たちはその確立うp個のαを | λ(N)+1λ(N) - 1)たびにp個のα | n個

λ(k)| λ(n)は常にk | Nソース)ので、λ(k) - 1)(λ(N)-λ(K) + λ(N)-2λ(K) +⋯+ λ(K) + 1)= A λ(n)を - 1と、従って、λ(k) - 1 | λ(n)を - 1 | λ(N)+1λ(N) - 1)

もしおよびP αの定義により、互いに素λ以上、p個のα | λ(p個のα - 1 | 必要に応じてaλ(n)+1aλ(n) -1)が続きます。

もし= 0、次いで、λ(N)+1λ(N) - 1)= 0、全ての整数で割り切れます。

最後に、我々は、ケース検討しなければならないとpはα、共通の素因数を持っています。pは素数なので、これはp | Aカーマイケルの定理はp> 2またはα<3の場合はλ()=(p-1)pα-1、それ以外の場合はλ()= pα-2あることを確立します。すべての場合において、λ()≥p - 2≥2α -2 >α-2です。

したがって、λ(N)+ 1≥λ(P α)+ 1>α - 1、そうλ(N)+ 1≥α及びP α | P λ(n)を+1 | λ(n)を+1 | aλ(N)+1λ(N) - 1) 。これで証明が完了しました。

使い方

f(n)λ(n)の定義はaのすべての可能な値を考慮しますが[0、...、n-1]にある値をテストすれば十分です。

場合fは(N、k)が呼び出され、それは計算K + 1K - 1)%Nの全ての値のためである範囲で0を場合にのみN | a k + 1(a k -1)

計算されたすべての剰余がゼロの場合、k =λ(n)Falseany返すため、f(n、k)1を返します。

一方、k <λ(n)の場合1-any(...)0が返されるため、fkの増分値で再帰的に呼び出されます。主要-~インクリメントの戻り値F(N、K + 1) 、我々は追加そう1F(N、λ(N))= 1回ですべての整数のための[1、...、λ(N) - 1 ]。したがって、最終結果はλ(n)です。


リスト内包表記の代わりに、再帰で少なくとも4つ保存できます:f=lambda n,k=1,a=1:a/n or(a**k*~-a**k%n<1)*f(n,k,a+2-n%2)or-~f(n,k+1)(n **λ(n)時間かかるのが嫌な場合は、1バイトを追加し直してください)。
feersum

1
ありがとう!その間、リストの内包表記を使用する代わりに再帰の利点を無効にするように見えるアルゴリズムの改善を発見しました。
デニス

14

組み込みのないMathematica、58 57バイト

エラーを発見してくれたMartin Enderに感謝します。

1バイト節約してくれたマイルに感謝します!(私には2のように思えた)

ビルトインはまったく問題ありませんが、ブルートフォースを使用せずに実装したい人のために、Carmichael関数の式を示します。

LCM@@(EulerPhi[#^#2]/If[#==2<#2,2,1]&@@@FactorInteger@#)&

pが素数の場合、Carmichael関数λ(p ^ r)はφ(p ^ r)=(p-1)* p ^(r-1)と等しくなります。ただし、p = 2およびr≥3の場合は例外です。それは半分、つまり2 ^(r-2)です。

nの素数分解がp1 ^ r1 * p2 ^ r2 * ...に等しい場合、λ(n)は{λ(p1 ^ r1)、λ(p2 ^ r2)、..の最小公倍数に等しくなります。 。}。

ランタイムは、最初に整数を因数分解することよりも一瞬です。


57バイトEulerPhiを取得するLCM@@(EulerPhi[#^#2]/If[#==2<#2,2,1]&@@@FactorInteger@#)&ために使用できます。
マイル

@milesが見事に発見されました!56バイトを数えますが、確認できますか?
グレッグマーティン

ええ、57 バイトです。
マイル

明らかに私も....ゴルフに私のカウントをしてみてください:/
グレッグ・マーティン

12

有害見なされるテンプレート、246バイト

Fun<Ap<Fun<If<Eq<A<2>,T>,A<1>,And<Eq<Ap<Fun<If<A<1>,Ap<A<0>,Rem<A<2>,A<1>>,A<1>>,A<2>>>,A<1,1>,A<2>>,T>,Sub<Ap<Fun<Rem<If<A<1>,Mul<A<2,1>,Ap<A<0>,Sub<A<1>,T>>>,T>,A<1,2>>>,A<1>>,T>>,Ap<A<0>,Add<A<1>,T>,A<1,1>>,Ap<A<0>,A<1>,Sub<A<2>,T>>>>,T,A<1>>>

名前のない関数(名前のある関数があるわけではありません)。

これは忘れられた私のesolangであり、テンプレートをインスタンス化するC ++コンパイラによって解釈されます。デフォルトの最大テンプレート深度でg++、λ(35)は実行できますが、λ(101)は実行できません(遅延評価は事態を悪化させます)。



8

ゼリー、2バイト

Æc

組み込み、@ Lynnをありがとう


31
............. ._。
マルティセン

10
そのようなばかげた特定の組み込みを実装することのポイントを私は決して理解しません。
-19:

31
これは、この課題のために特別に作成された言語へのほとんど追加です。リンによるコミット2日前、今日の
@Lynn

5
@ edc65このビルトインは、このチャレンジとその派生物以外ではほとんど役に立たないことは言うまでもありません。
16

3
まあ、カーマイケル関数は(現在の一番の答えが反映しているように)数論で重要なので、私はそれを役に立たないとは言いません。
グレッグマーティン


6

ルビー、 59 56バイト

->x{a=1..x
a.detect{|k|a.all?{|y|x.gcd(y)>1||y**k%x<2}}}

5

J、28 27バイト

[:*./@(5&p:%2^0=8&|)2^/@p:]

Carmichael関数はλ(n)であり、tientient関数はφ(n)です。

用途λ(定義のp K)=φ(PのK)/ 2であれば、P = 2、K > 2そうφ(PのK)。次に、一般的なn = p 1 k 1 p 2 k 2p i k iの場合、λ(n)= LCM [λ(p 1 k 1)λ(p 2 k 2)⋯λ(p i k i)] 。

使用法

複数の入出力をフォーマットするために使用される追加コマンド。

   f =: [:*./@(5&p:%2^0=8&|)2^/@p:]
   f 530
52
   (,.f"0) 1 2 3 10 35 101 530 3010 6511 10000
    1    1
    2    1
    3    2
   10    4
   35   12
  101  100
  530   52
 3010   84
 6511 3056
10000  500

説明

[:*./@(5&p:%2^0=8&|)2^/@p:]  Input: integer n
                          ]  Identity function, get n
                    2   p:   Get a table of prime/exponent values for n
                     ^/@     Raise each prime to its exponent to get the prime powers of n
[:    (            )         Operate on the prime powers
                8&|            Take each modulo 8
              0=               Test if its equal to 0, 1 if true else 0
            2^                 Raise 2 to the power of each
       5&p:                    Apply the totient function to each prime power
           %                   Divide it by the powers of 2
  *./@                       Reduce using LCM and return

これは、10000(正しい500ではなく1000)に対して間違った答えを与えます。実際、8の倍数ごとに2が固有の素数であり、λ(2 ^ a)= 2 ^ {a-2}(2 ^ {ではありません) a-1})a≥3の場合。
グレッグマーティン

それをキャッチしてくれてありがとう、私は自分の出力を読むことすらできないようです
マイル

あなたは時々一人ではありません。...:)
グレッグマーティン

5

実際には、30 28 25 19 26バイト

Carmichael関数は、λ(n)に分割される最大素数のn = p_0**k_0 * p_1**k_1 * ... * p_a**k_a最小公倍数(LCM)として定義されます。プライムがである場合を除いて、すべてのプライムべき乗に対して、カーマイケル関数はオイラーのトーティエント関数に相当するため、代わりに使用します。where の特殊なケースでは、プログラムの先頭で分割するかどうかを確認し、分割する場合は2で分割します。λ(p_i**k_i)p_i**k_in2λ(n) == φ(n)φ(n)2**kk ≥ 32**3 = 8n

残念ながら、実際には実際にはLCMが組み込まれていないため、ブルートフォースLCMを作成しました。ゴルフの提案を歓迎します。オンラインでお試しください!

;7&Yu@\w`iⁿ▒`M╗2`╜@♀%ΣY`╓N

アンゴルフ

         Implicit input n.
;        Duplicate n.
7&       n&7 == n%8.
Yu       Logical NOT and increment. If n%8 == 0, return 2. Else, return 1.
@\       Integer divide n by 2 if n%8==0, by 1 otherwise.
          Thus, we have dealt with the special case where p_i == 2 and e_i >= 3.
w        Full prime factorization of n as a list of [prime, exponent] lists.
`...`M   Map the following function over the prime factorization.
  i        Flatten the array, pushing exponent, then prime to the stack.
  ⁿ▒       totient(pow(prime, exponent)).
╗        Save that list of totients in register 0.
2`...`╓  Get the first two values of n where the following function f(n) is truthy.
         Those two numbers will be 0 and our LCM.
  ╜@       Push the list in register 0 and swap with our n.
  ♀%       Get n mod (every number in the list)
  Σ        Sum the modulos. This sum will be 0, if and only if this number is 0 or LCM.
  Y        Logical NOT, so that we only get a truthy if the sum of modulos is 0.
N        Grab the second number, our LCM. Implicit return.

2
実際、わずか19バイトでこれをどのように行ったかはわかりません。
バッファーオーバーリード

@TheBitByte totientおよびgcd組み込みの使用。Actuallyがlcm直接持っていればこれは短くなりますが、私はそれほど気にしませんし、とにかくせいぜい4バイトしか使いません。
Sherlock9

1
* aが正確に2つの数字のリストである場合、lcm(* a)= product(* a)/ gcd(* a)であるという主張は真です。ただし、一般に長いリストでは偽です(例:* aが{6,10,15}の場合、60の正解ではなく900になります)。[さらに言えば、間違っているのは* aも1つの数字のリストです!]そして、OPにリストされているテストケースの半分以上で間違った答えが得られることを確認できます。
グレッグマーティン

@GregMartin頭を上げてくれてありがとう。一定。
シャーロック

4

JavaScript(ES6)、143 135バイト

編集:ニールのおかげで8バイト保存

関数型プログラミングを使用した実装。

n=>(A=[...Array(n).keys()]).find(k=>k&&!c.some(c=>A.slice(0,k).reduce(y=>y*c%n,1)-1),c=A.filter(x=>(g=(x,y)=>x?g(y%x,x):y)(x,n)==1))||1

非ゴルフとコメント

n =>                                          // Given a positive integer n:
  (A = [...Array(n).keys()])                  // Build A = [0 ... n-1].
  .find(k =>                                  // Try to find k in [1 ... n-1] such as
    k && !c.some(c =>                         // for each coprime c: c^k ≡ 1 (mod n).
      A.slice(0, k).reduce(y =>               // We use reduce() to compute
        y * c % n, 1                          // c^k mod n.
      ) - 1                                   // Compare it with 1.
    ),                                        // The list of coprimes is precomputed
    c = A.filter(x =>                         // before the find() loop is executed:
      (                                       // for each x in [0 ... n-1], keep
        g = (x, y) => x ? g(y % x, x) : y     // only integers that verify:
      )(x, n) == 1                            // gcd(x, n) = 1
    )                                         // (computed recursively)
  ) || 1                                      // Default result is 1 (for n = 1)

デモ

それがために仕事をしていますが6511して10000、それは少し遅くなる傾向にあるように、私はここには含まれません。

let f =
n=>(A=[...Array(n).keys()]).find(k=>k&&!c.some(c=>A.slice(0,k).reduce(y=>y*c%n,1)-1),c=A.filter(x=>(g=(x,y)=>x?g(y%x,x):y)(x,n)==1))||1

console.log(f(1));     // 1
console.log(f(2));     // 1
console.log(f(3));     // 2
console.log(f(10));    // 4
console.log(f(35));    // 12
console.log(f(101));   // 100
console.log(f(530));   // 52
console.log(f(3010));  // 84


1
JSは0..n-1範囲を非常に簡単に行うことができます[...Array(n).keys()]。これには、1つではなく2つの特別なケースが必要ですが、私はまだ先を行っていますn=>(a=[...Array(n).keys()]).find(k=>k&&!c.some(c=>a.slice(0,k).reduce(y=>y*c%n,1)-1),c=a.filter(x=>(g=(x,y)=>x?g(y%x,x):y)(x,n)==1))||1
ニール

2

Ruby、101 86 91 90バイト

実際の回答の Rubyへの移植。ゴルフの提案を歓迎します。

編集:削除すると-4バイトa1返されたバグを修正すると+9バイトnil。Cyoceのおかげで-1バイト。

require'prime'
->n{((n%8<1?n/2:n).prime_division<<[2,1]).map{|x,y|x**~-y*~-x}.reduce :lcm}

アンゴルフ

require 'prime'
def carmichael(n)
  if n%8 < 1
    n /= 2
  end
  a = []
  n.prime_division.do each |x,y|
    a << x**(y-1)*(x-1)
  end
  return a.reduce :lcm
end

必要ありませんa=。残念ながら、niln = 1のために戻ります:(。それを(n.prime_division<<[2,1])修正します。ゴルファーの道があるかどうかはわかりません。
m-chrzan

(n%8<1?n/2:n).prime_division...さらに2バイト節約します。
m-chrzan

@ m-chrzan aは、以前のゴルフの試みの名残です。についてのリマインダーaとありがとうございました1
シャーロック

.reduce :lcm代わりにを使用してバイトを保存できます.reduce(:lcm)
チョイス

1

JavaScript(ES 2016)149

JSに移植されたPythonリファレンス実装。いくつかの空想Pyhton組み込み関数は次のように、JSに欠けているgcdpow、配列の理解は、ES 6. Firefoxでこの作品では標準ではありません。

n=>eval('for(g=(a,b)=>b?g(b,a%b):a,p=(a,b,c)=>eval("for(r=1;b--;)r=r*a%c"),c=[for(_ of Array(i=n))if(g(i--,n)<2)i+1],k=1;c.some(x=>p(x,k,n)-1);)++k')

少ないゴルフ

n=>{
  g=(a,b)=>b?g(b,a%b):a
  p=(a,b,c)=>{ 
    for(r=1;b--;)
      r=r*a%c
    return r
  }
  c=[for(_ of Array(i=n)) if(g(i--,n)<2) i+1]
  for(k=1;c.some(x=>p(x,k,n)-1);)
    ++k
  return k
} 

再帰modpowは短い:p=(a,b,c)=>b?a*p(a,b-1,c)%c:1;
オリビエグレゴワール

1

Java、 209 207 202 194 192バイト

コード(96バイト):

n->{for(int x,k=1,a;;k++){for(a=1,x=0;++x<=n&&a<2;)a=g(x,n)<2?p(x,k,n):1;if(a<2||n<2)return k;}}

追加機能(96バイト):

int g(int a,int b){return b<1?a:g(b,a%b);}int p(int n,int p,int m){return p<2?n:n*p(n,p-1,m)%m;}

テストと未使用

import java.util.Arrays;
import java.util.function.IntUnaryOperator;

public class Main2 {

  static int g(int a,int b) { // recursive gcd
    return b < 1
        ? a
        : g(b,a%b);
  }

  static int p(int n, int p, int m) { // recursive modpow
    return p < 2
      ? n
      : n * p(n, p - 1, m) % m;
  }

  public static void main(String[] args) {

    IntUnaryOperator f = n -> {
      for(int x,k=1,a;;k++) { // for each k
        for(a=1,x=0;++x<=n&&a<2;) // for each x
          a=g(x,n)<2?p(x,k,n):1; // compute modpow(x,k,n) if g(x,n)
        if(a<2||n<2) // if all modpow(x,k,n)=1. Also check for weird result for n=1.
          return k;
      }
    };

    Arrays.stream(new int[]{1, 2, 3, 10, 35, 101, 530, 3010, 6511, 10000})
        .map(f)
        .forEach(System.out::println);
  }
}

ノート

  • 使用aであることは、int私が使用していた場合よりも短くなっているboolean私のテストを実行します。
  • はい、valueOfすべての新規のBigInteger場合は、個別の関数を作成するよりも短くなります(5つあり、ONE定数は無料です)。
  • アルゴリズムは@Master_ex 'アルゴリズムとは異なるため、単なるゴルフのリポストではありません。また、このアルゴリズムはgcd、同じ値に対して何度も計算されるため、効率が大幅に低下します。

ひげそり

  1. 209-> 207バイト:
    • if(...)a=...; -> a=...?...:1;
    • a==1 -> a<2
  2. 207-> 202バイト
    • BigIntegerゴルフgcdmodPowでなくしましたint
  3. 202-> 194バイト
    • ループmodPow->再帰的
  4. 194-> 192バイト
    • ==1-> <2(すべてのテストケースで機能すると思われますが、他の数値ではわかりません。)

おい!私は出力が期待されていないことに気づきました。予想される結果については質問をご覧ください。個人的には、コードのゴルフを始める前にユニットテストを書くことがよくあります。問題は整数のmodPowである可能性があると思います。この問題もあったため、最後にBigIntegerを使用しました。
Master_ex

うーん...私は驚いた、すべての変更でテストを実行させた。何が間違っているのかを確認します。
オリビエグレゴワール

1
@Master_ex修正しました。前のバージョンに戻っても問題ありません。
オリヴィエグレゴワール

再帰的なmodpowメソッドはpかなり賢いと思います。私も最初は整数のみを使用しようとしましたが、答えで述べたように、精度の問題があったため、移動しましたBigInteger(つまりの代わりにMath.pow(3, 100)%101戻り60.0ました1)。各反復でmodを実行するため、実装はこれに影響されません。ただし、まだバグがあります。大規模なm p場合でも、間違った結果が返されることがあります。また、再帰のためにStackOverflowError、デフォルトのスタックサイズの大きな入力では簡単に発生する可能性があります。
Master_ex

@Master_exはい、それはint型の制限の結果です。intの代わりにlongを使用できます。これは8バイト余分になります。しかし、私の考えでは、すべてのテストケースは有効であるため、そのままにしておきます。StackOverflowError起こる可能性がありますが、それが再帰の仕組みです。32スタックに制限するメソッドが存在しますが、これらはさらに多くのバイトを使用します。この実装は脆弱です、はい、あなたは完全に正しいです。ただし、テストケースには十分な強度があります。
オリビエグレゴワール

1

Java8 38 19 + 287 295 253 248 241 = 325 333 272 267 260バイト

BigInteger B(int i){return new BigInteger(""+i);}int c(int...k){int n=k[0];for(k[0]=1;n>1&!java.util.stream.IntStream.range(0,n).filter(i->B(n).gcd(B(i)).equals(B(1))).allMatch(x->B(x).modPow(B(k[0]),B(n)).equals(B(1)));k[0]++);return k[0];}

インポート、19バイト

import java.math.*;

説明

これは単純な実装です。共素数はで計算されますSet pすべてのk乗が1モジュロnに等しいかどうかを確認するために使用されます。

BigInteger精度の問題のために使用する必要がありました。

使用法

public static void main(String[] args) {
    Carmichael c = new Carmichael();
    System.out.println(c.c(3)); // prints 2
}

非ゴルフ

// returns the BigInteger representation of the given interger
BigInteger B(int i) {
    return new BigInteger(""+i);
}
// for a given integer it returns the result of the carmichael function again as interger
// so the return value cannot be larger
int c(int... k) {
    int n = k[0];
    // iterate k[0] until for all co-primes this is true: (x^n) mod n == 1, if n==1 skip the loop
    for (k[0]=1;n > 1 && !java.util.stream.IntStream.range(0, n)
                .filter(i -> B(n).gcd(B(i)).equals(B(1)))
                .allMatch(x -> B((int) x).modPow(B(k[0]), B(n)).equals(B(1)));k[0]++);
    return k[0];
}

もっとゴルフをする提案は大歓迎です:-)

更新

  • 状態を保持する関数以外の要素はありません
  • OlivierGrégoireのアドバイスに従い、1バイトを保存しました B()
  • k()メソッドとp(コプライム)セットを削除しました。
  • intへの不要なキャストを削除しました。
  • varagを追加し、whileの代わりに使用します。

あなたは(、&そこここなどを改行、コメント付き)ungolfedバージョンを持つことができます
OldBunny2800

@ OldBunny2800:そうだね。ただし、忙しいので、今日は後でやります!
Master_ex

@ OldBunny2800:未追加バージョンを追加しました:-)
Master_ex

うーん...これが関数でもプログラムでもないのでカウントされるかどうかはわかりません。関数の場合、状態を保持する要素が外部にあり、事実上のメソッド(関数は外部状態のない純粋な入力->出力)になります。プログラムの場合、メインメソッド全体が欠落しています。私の解釈が間違っている場合、教えてください!k(int)ワンライナーで実行できるため、ループに含める方が良いと思います。さらに、定数Oもcメソッドに入れることができます。そうすることでバイトを獲得できると思います!
オリビエグレゴワール

Concretely, while(n>1&&!p.stream().allMatch(x->B((int)x).modPow(B(k), B(n)).equals(O))) shaves bytes and fixes the issues I mentioned if you put the set and the constant back into the method. Also, you use O twice, replace by B(1) to shave bytes.
Olivier Grégoire



0

ラケット218バイト

(λ(n)(let((fl #f)(cl(for/list((i n) #:when(coprime? n i))i)))(for/sum((k(range 1 n))#:break fl)(set! fl #t)
(for((i(length cl))#:break(not fl))(when(not(= 1(modulo(expt(list-ref cl i)k)n)))(set! fl #f)))(if fl k 0))))

ゴルフされていないバージョン:

(require math)
(define f
  (λ(n)
    (let ((fl #f)
          (cl (for/list ((i n) #:when (coprime? n i))
                i)))
             (for/sum ((k (range 1 n)) #:break fl)
               (set! fl #t)
               (for ((i (length cl)) #:break (not fl))
                 (when (not (= 1 (modulo (expt (list-ref cl i) k) n)))
                   (set! fl #f)))
               (if fl k 0)))))

テスト:

(f 2) 
(f 3)
(f 10)
(f 35)
(f 101)
(f 530)
(f 3010)
(f 6511)
(f 10000)

出力:

1
2
4
12
100
52
84
3056
500

0

C、278276272265265256243140134125バイト

k,x,a,b,t,d;l(n){for(k=d=1;d;)for(d=x=0;++x<n;d=a<2&t>1?k++:d){for(a=x,b=n;t=b;a=t)b=a%b;for(t=1,b=k;b--;t=t*x%n);}return k;}

これは、遅いモジュラーべき乗アルゴリズムを使用し、GCDを頻繁に計算し、メモリをリークしません!

ゴルフをしていない:

int gcd( int a, int b ) {
  int t;
  while( b ) {
    t = b;
    b = a%b;
    a = t;
  }
  return a;
}
int pw(int a,int b,int c){
  int t=1;
  for( int e=0; e<b; e++ ) {
    t=(t*a)%c;
  }
  return t;
}
int carmichael(int n) {
  int k = 1;
  for( ;; ) {
    int done = 1;
    for( int x=1; x<n; x++ ) {
      if( gcd(x,n)==1 && pw(x,k,n) != 1 ) {
        done = 0;
        k++;
      }
    }
    if( done ) break;
  }
  return k;
}

Ideoneでお試しください


0

公理129バイト

c(n)==(r:=[x for x in 1..n|gcd(x,n)=1];(v,k):=(1,1);repeat(for a in r repeat(v:=powmod(a,k,n);v~=1=>break);v<=1=>break;k:=k+1);k)

少ないゴルフ

cml(n)==
 r:=[x for x in 1..n|gcd(x,n)=1];(v,k):=(1,1)
 repeat 
   for a in r repeat(v:=powmod(a,k,n);v~=1=>break)
   v<=1=>break
   k:=k+1
 k

結果

(3) -> [i,c(i)] for i in [1,2,3,10,35,101,530,3010,6511,10000]
   Compiling function c with type PositiveInteger -> PositiveInteger

   (3)
   [[1,1], [2,1], [3,2], [10,4], [35,12], [101,100], [530,52], [3010,84],
    [6511,3056], [10000,500]]
                                             Type: Tuple List PositiveInteger
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.