Carmichael 함수 계산


36

과업 설명

정수론에서, 카 마이클 함수  λ는 양의 정수 얻어  N 복귀 최소 양의 정수 K 있도록한다는 K 각 정수 번째의 파워 서로 소n은 1 개 모듈 동일 N을 .

양의 정수 n이 주어지면 솔루션은 λ (n)을 계산해야합니다 . 바이트 단위의 가장 짧은 코드가 이깁니다.

프로그램은 이론적으로 임의로 큰 입력에 대해 작동해야하지만 효율적일 필요는 없습니다.

모든 λ (n) 의 순서 는 OEIS A002322 입니다.

ungolfed 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) 이 이중에 적합 하다고 가정 할 수 있습니까 ?
Dennis

2
예, 그렇습니다. 마찬가지로 이론적으로기본 유형이 임의로 정확하고 크다고 가정합니다 (나는 그것이 합의라고 생각했지만 확실하지 않습니다).
Lynn

답변:



29

파이썬, 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 대신 True 를 반환하여 추가 바이트를 저장할 수 있습니다 .

대체 구현

동일한 접근 방식을 사용하여 목록 이해를 사용하지 않는 @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)

배경

정의와 표기법

사용 된 모든 변수는 정수를 나타냅니다. n , kα양의 정수 를 나타내고 ; 및 p는 긍정적 나타내는 것이다 프라임 .

| B 경우 B는 로 나누어 있을 경우, 즉, Q 되도록 B = QA .

ab 가 동일한 잔차 모듈로 m을 갖는 경우 a m b ( mod m) , 즉 m | a-b .

λ (n)k ≡ 1 ( mod n) 과 같이 가장 작은 k 입니다 . 즉, n | K - 1 - 모든 에 서로 소있다 N .

F (N)은 최소이고 K 되도록 2K + 1K + 1 ( 개조 N) - 즉, 그와 같은 N | a k + 1 (a k -1) – 모두 a .

λ (n) ≤ f (n)

수정 N 및하자 하는 서로 소 N을 .

의 정의에 의해 F , N | a f (n) +1 (a f (n) -1) . 이후 및 n은 공통의 주요 요인이 없다, 어느 쪽도하지 않는다 F (N)를 1N , 그 의미하는 N을 | a f (n) -1 입니다.

이후 λ (n)의 최소 정수이며 , k는 그러한 | N K - 1 모든 정수의 에 서로 소있는 N은 , 그 다음 λ (N) ≤ F (N)를 .

λ (n) = f (n)

이미 부등식 설정 했으므로 λ (N) ≤ F (N)을 ,이 있는지 확인하기에 충분하다 K = λ (n)을 만족하는 조건을하도록 정의 F , 즉, 그 N | λ (n)를 +1 (a λ (N) - 1) 모든 . 이를 위해 p α | p α | 때마다 a λ (n) +1 (a λ (n) -1) n .

λ (k) | λ (n) 언제나 k | n ( source )이므로 (a λ (k) -1) (a λ (n) -λ (k) + a λ (n) -2λ (k) + ⋯ + a λ (k) + 1) = a λ (N) - 1 및, 따라서, λ (K) - (1) | a λ (n) -1 | λ (n)를 +1 (a λ (N) - 1) .

만약 및 P α 의 정의에 의해, 서로 소입니다 λ 와 위, P는 α | a λ (p α ) -1 | 원하는대로 λ (n) +1 (a λ (n) -1)이 뒤 따른다.

만약 A = 0 , 다음 λ (n)를 +1 (a λ (N) - 1) = 0 인 모든 정수로 나누어.

마지막으로, ap α 가 공통 소인수를 갖는 경우를 고려해야합니다 . 이후 p는 소수, 이것은 그 의미 | 페이지를 . 카 마이클 정리p> 2 또는 α <3 이면 λ (p α ) = (p-1) p α-1 이고 그렇지 않으면 λ (p α ) = p α-2 임을 설정 합니다. 모든 경우에 λ (p α ) ≥ p α-2 ≥ 2 α-2 > α-2 입니다.

따라서 λ (n) + 1 ≥ λ (p α ) + 1> α-1 이므로 λ (n) + 1 ≥ αp α | p λ (n) +1 | λ (n)를 1 | λ (n)를 +1 (a λ (N) - 1) . 이것으로 증명이 완료됩니다.

작동 원리

f (n)λ (n) 의 정의는 a의 모든 가능한 값을 고려 하지만 [0, ..., n-1]있는 값 을 테스트하는 것으로 충분합니다 .

하면 F가 (N, K)를 호출하고, 그 계산 K + 1 (a K - 1) % N 의 모든 값에 대해 하다 범위에서 0 이하의 경우 만 N | K + 1 (a K - 1) .

계산 된 모든 잔기가 0이면 k = λ (n) 이고 False를any 반환 하므로 f (n, k)1을 반환합니다 .

반면 k <λ (n) 에서는 01-any(...) 을 반환 하므로 f 는 증가 된 값 k로 재귀 적으로 호출 됩니다. 리딩 은 f (n, k + 1) 의 반환 값을 증가 시키므로 [1, ..., λ (n)-1의 모든 정수에 대해 1f (n, λ (n)) = 1을 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
감사! 그 동안 목록 이해를 사용하는 대신 재귀의 이점을 무효화하는 알고리즘이 개선되었습니다.
Dennis

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@#)&.
마일

@ 마일이 멋지게 발견되었습니다! 56 바이트를 세어 볼 수 있어요?
Greg Martin

예, 57 바이트 입니다.
마일

분명히 나는 ​​심지어 내 계산 골프를하려고합니다 .... : /
Greg Martin

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 of esolang이며 템플릿을 인스턴스화하는 C ++ 컴파일러에 의해 해석됩니다. 기본 최대 템플릿 깊이 g++는 λ (35)를 수행 할 수 있지만 λ (101)을 수행 할 수는 없습니다 (게으른 평가는 상황을 악화시킵니다).


10

하스켈, 57 56 바이트

f n=[k|k<-[1..],and[mod(m^k)n<2|m<-[1..n],gcd m n<2]]!!0

8

젤리, 2 바이트

Æc

@Lynn 내장 감사합니다


31
............. ._.
Maltysen

10
나는 엄청나게 구체적인 내장 기능을 구현하는 요점을 결코 이해하지 못합니다.
Fatalize

31
이것은 이 도전을 위해 특별히 만들어진 언어에 거의 추가 된 것입니다. Lynn이 2 일 전에 커밋, @Lynn이 오늘 도전
edc65

5
@ edc65이 빌트인은이 도전과 그 파생물을 제외하고는 거의 쓸모가 없다.
페이탈 라이즈

3
글쎄, Carmichael 함수는 숫자 이론에서 중요합니다 (현재 최고 답변이 반영하는 것처럼). 나는 그것을 쓸모가 없다고 부르지 않을 것입니다.
Greg Martin


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:]

카 마이클 함수는 λ ( n )이고 관련 함수는 φ ( n )입니다.

p = 2 인 경우 λ ( p k ) = φ ( p k ) / 2 인 정의를 사용 하고 k > 2 인 경우 φ ( p k )를 사용합니다. 다음에, 일반에 대해 N = P (1) K (1) P (2) K (2)P 케이 , λ ( N [λ () = LCM P 1 K 1 ) λ ( P 2 K 2 ) ⋯ λ ( p는 케이 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는 특이한 소수이며 λ (2 ^ a) = 2 ^ {a-2} (2 ^ {아님) a-1}) a≥3 일 때.
Greg Martin

그것을 찾아 주셔서 감사합니다, 심지어 내 자신의 출력을 읽을 수없는 것 같습니다
마일

당신은 때때로 혼자가 아닙니다 .... :)
Greg Martin

5

실제로, 30 28 25 19 26 바이트

카 마이클 함수 의 최소 공배수 (LCM)로 정의되는 최대 전력을위한 주요한 으로 나눈다 것을 . 소수가를 제외한 모든 소수 에 대해 카 마이클 함수는 오일러 계급 함수와 동일 하므로 대신 사용 합니다. where 의 특별한 경우에 , 우리 는 프로그램의 시작 부분으로 나누는 지 확인하고, 그렇다면 프로그램을 2로 나눕니다.λ(n)n = p_0**k_0 * p_1**k_1 * ... * p_a**k_aλ(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 totientgcd내장을 사용합니다. 실제로 lcm직접 직접 가지고 있다면 이것은 더 짧을 것입니다 .하지만 나는 그것을 많이 신경 쓰지 않으며 어쨌든 최대 4 바이트 만 노크합니다.
Sherlock9

1
* a가 정확히 두 개의 숫자의 목록 인 경우 lcm (* a) = product (* a) / gcd (* a)는 true입니다. 그러나 더 긴 목록에 대해서는 일반적으로 거짓입니다 (예 : * a가 {6,10,15}이면 정답 60 대신 900을 나타냄). [그 문제에있어서 * a는 하나의 숫자 목록이기도합니다.] 그리고 OP에 나열된 테스트 사례의 절반 이상에 대해 잘못된 답변을 얻었는지 확인할 수 있습니다.
Greg Martin

@GregMartin 감사합니다. 결정된.
Sherlock9

4

자바 스크립트 (ES6) 143 135 바이트

편집 : Neil 덕분에 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)

데모

이에 대한 작업을 수행하지만 651110000는 조금 느린 경향으로, 나는 여기에 포함되지 않습니다.

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()]. 여기에는 한 가지가 아니라 두 가지 특별한 경우가 필요하지만 여전히 앞서 있습니다.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
Neil

2

루비, 101 86 91 90 바이트

내 실제 답변 의 루비 포트 . 골프 제안을 환영합니다.

편집 : -4 바이트는 제거 a하고 +9 바이트는 버그를 수정하여 1반환 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=. 불행히도, 당신 nil은 n = 1 :(로 (n.prime_division<<[2,1])수정합니다. 골퍼가 있는지 확실하지 않습니다.
m-chrzan

(n%8<1?n/2:n).prime_division...다른 2 바이트를 저장합니다.
m-chrzan 2018 년

@ m-chrzan a은 초기 골프 시도의 잔재입니다. 에 대한 알림에 대한 감사 a와 위로의 머리에 1.
Sherlock9

.reduce :lcm대신을 사용하여 바이트를 저장할 수 있습니다 .reduce(:lcm).
Cyoce

1

자바 스크립트 (ES 2016) 149

JS로 포팅 된 파이썬 레퍼런스 구현. 일부 공상 Pyhton의 내장처럼, JS에 빠져 gcdpow, 및 배열 이해는 ES 6. 파이어 폭스에서이 작품에서 표준이 아니다.

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;
Olivier Grégoire

1

자바, 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골프 gcd와 에 의해 제거 modPow했습니다 int.
  3. 202-> 194 바이트
    • 루핑 modPow-> 재귀
  4. 194-> 192 바이트
    • ==1-> <2(모든 테스트 사례에서 작동하는 것으로 보이며 다른 숫자는 모릅니다.)

야! 출력이 예상과 다르다는 것을 알았습니다. 예상 결과에 대한 질문을 참조하십시오. 개인적으로, 나는 종종 골프를 시작하기 전에 단위 테스트를 작성하는데 도움이된다! 문제는 정수의 modPow 일 수 있다고 생각합니다.이 문제도 있었고 결국 BigInteger를 사용했습니다.
Master_ex

흠 ... 놀랍습니다. 모든 테스트에서 테스트가 실행되도록했습니다. 무엇이 잘못되었는지 확인하겠습니다.
Olivier Grégoire

1
@Master_ex 나는 그것을 고쳤다. 이전 버전으로 돌아가는 것은 괜찮습니다.
Olivier Grégoire

나는 재귀 적 modpow 방법이 p매우 영리 하다고 생각합니다 . 처음에는 정수 만 사용하려고했지만 대답에서 언급했듯이 정밀도 문제가 있었기 때문에으로 이동했습니다 BigInteger(즉, 대신 Math.pow(3, 100)%101반환 ). 각 반복에서 모드를 수행하기 때문에 구현에 영향을 미치지 않습니다. 그러나 여전히 버그로 고통 받고 있습니다. 큰 경우에도 여전히 잘못된 결과가 반환 될 수 있습니다. 또한 재귀 로 인해 기본 스택 크기의 큰 입력에 대해 쉽게 발생할 수 있습니다. 60.01m pStackOverflowError
Master_ex

@Master_ex 그렇습니다 int. 타입 제한의 결과입니다 . 정수 대신 long을 사용할 수 있습니다 .8 바이트가 더 있습니다. 그러나 내 견해로는 모든 테스트 사례가 유효하므로 그대로 두십시오. StackOverflowError일어날 수 있지만 재귀가 작동하는 방식입니다. 32 스택으로 제한하는 방법이 있지만 더 많은 바이트를 사용합니다. 이 구현은 깨지기 쉬우므로 그렇습니다. 그러나 테스트 사례에는 충분합니다.
Olivier Grégoire

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];
}

더 골프에 대한 제안은 환영합니다 :-)

최신 정보

  • 상태를 유지하는 함수 외부의 요소가 없습니다.
  • Olivier Grégoire의 조언을 따르고 1 바이트를 절약했습니다. B()
  • k()방법 및 p(공동 프라임) 세트를 제거했습니다 .
  • int로 캐스팅 할 필요가 없습니다.
  • varag를 추가하고 while 대신에 사용합니다.

당신은 (, 여기 저기 등을 바꿈, 의견)를 ungolfed 버전이 수
OldBunny2800

@ OldBunny2800 : 예, 물론입니다. 그러나 나는 오늘 바쁘기 때문에 오늘 나중에 할 것입니다!
Master_ex

@ OldBunny2800 : 나는 ungolfed 버전을 추가했습니다 :-)
Master_ex 18:39에

흠 ... 이것이 함수도 프로그램도 아닌지 잘 모르겠습니다. 함수 인 경우 외부에 상태를 유지하는 요소가있어 사실상 메소드가됩니다 (함수는 외부 입력이없는 순수한 입력-> 출력입니다). 프로그램 인 경우 전체 메인 메소드가 누락됩니다. 내 해석이 틀렸다면 알려주세요! k(int)루프 에 포함 시키는 것이 하나의 라이너이기 때문에 더 좋을 것이라고 생각합니다 . 또한 상수 O도 c방법에 넣을 수 있습니다 . 그렇게하면 바이트를 이길 것입니다!
Olivier Grégoire

구체적으로, while(n>1&&!p.stream().allMatch(x->B((int)x).modPow(B(k), B(n)).equals(O)))면도 바이트 수정 당신이 설정 및 방법에 일정을 다시 세우면 내가 언급 한 문제를. 또한 바이트를 면도 하려면 O두 번 사용 B(1)하고 바꿉니다.
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, 2782762772265256243140134125 바이트

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.