오일러의 참을성있는 함수 계산


27

배경

오일러 totient의 기능은 φ(n)보다 적은 전체 숫자의 수로서 정의 또는 같은지 n그하면에 서로 소 n, 즉, 사용할 수있는 값의 수 x0 < x <= n있는 gcd(n, x) == 1. 우리는 했어 totient - 관련 문제 이전에,하지만 단지 그것을 계산하는 결코 하나.

정수 함수를 정수로 맵핑하는 것은 OEIS A000010 입니다.

도전

정수가 주어지면 n > 0계산하십시오 φ(n). 명령 행 인수, 표준 입력, 함수 인수 또는 기타 합리적인 것을 통해 입력 할 수 있습니다. 표준 출력, 반환 값 또는 기타 합리적인 방법으로 출력 할 수 있습니다. 익명의 기능이 허용됩니다. 입력이 intC와 같이 정수를 저장하는 자연적인 방법을 오버플로하지 않을 것이라고 가정 할 수 있지만 최대 255 개의 입력을 지원 해야합니다 . 언어에 내장 된 강의 함수가있는 경우에는 사용할 수 없습니다.

φ(1) => 1
φ(2) => 1
φ(3) => 2
φ(8) => 4
φ(9) => 6
φ(26) => 12
φ(44) => 20
φ(105) => 48

바이트 단위의 최단 답변이 이깁니다. 귀하의 언어가 UTF-8 이외의 인코딩을 사용하는 경우 귀하의 답변에 언급하십시오.


4
요 전날 이것도 있었습니다 . 반복되는 응용 프로그램이 충분한 차이를 만들지 않는다고 생각하지만 다른 응용 프로그램을 닫으면 반복되는 응용 프로그램이 아무것도 추가하지 않는다고 생각하기 때문에 닫습니다. 즉, 더 큰 차이점은 내장 된 것을 허용하고 그렇지 않은 것입니다.
Martin Ender 2016 년

내장을 허용하지 않는 것은 분명히 대답에 영향을 미치지 않습니다.
Julie Pelletier

2
@JuliePelletier 왜 그렇습니까? 내 Mathematica의 대답은 그렇지 않으면 19 바이트 더 짧았을 것입니다.EulerPhi
Martin Ender

@JuliePelletier GCD는 GCD 계산이 해결하려는 의도 된 문제가 아니므로 허용됩니다. 물론,이 답변에서 바이트 수를 늘릴 수는 있지만 도전을 더 잘하지는 않습니다. 명확히하기 위해 편집 할 것입니다.
bkul

답변:


13

수학, 27 22 바이트

Range@#~GCD~#~Count~1&

정수를 가져 와서 반환하는 명명되지 않은 함수입니다.

@함수 호출에 대한 접두사 표기법 ~...~이고 (왼쪽 연관) 접두어 표기법을 제외하고 는 여기에서 설명하지 않아도되므로 위와 같습니다.

Count[GCD[Range[#], #], 1] &

11

MATL, 7 바이트

t:Zd1=s

당신은 TryItOnline 할 수 있습니다 . 가장 간단한 아이디어는 1에서 N까지의 벡터를 만들고 N을 사용하여 각 요소의 gcd를 취합니다 ( Zdgcd 수행). 그런 다음 1과 같은 요소를 찾아 벡터를 합하여 답을 얻으십시오.


내장은 _Zp궁금한 사람들을위한 것입니다.
David

10

J, 9 바이트

(-~:)&.q:

이것은 Jtiware의 관련 기능에 대한 에세이 를 기반으로합니다 .

감안 N = P (1) 1P 2 2 ∙∙∙ P K 전자 K P는 K가 의 주요한 요인 N 은 totient 함수 φ ( N ) = φ ( P 1 1 ) ∙ φ ( P 2 예는 2 ) ∙∙∙ φ ( P k 개의 전자 K ) = ( P 1 - 1)의 페이지 1 1 - 1 ∙ ( P 2 - 1)의 페이지 22 - 1 ∙∙∙ ( P는 K - 1) P는 K의 전자 K - 1 .

용법

   f =: (-~:)&.q:
   (,.f"0) 1 2 3 8 9 26 44 105
  1  1
  2  1
  3  2
  8  4
  9  6
 26 12
 44 20
105 48
   f 12345
6576

설명

(-~:)&.q:  Input: integer n
       q:  Prime decomposition. Get the prime factors whose product is n
(   )&     Operate on them
  ~:         Nub-sieve. Create a mask where 1 is the first occurrence
             of a unique value and 0 elsewhere
 -           Subtract elementwise between the prime factors and the mask
     &.q:  Perform the inverse of prime decomposition (Product of the values)

재귀를 사용하여 J에서 또 다른 솔루션을 만들기 위해 totient가 곱해진다는 사실을 사용하십시오.)
Leaky Nun

@LeakyNun 반복적 인 형식을 [:*/@({.(^-(^<:)){:)2&p:사용하더라도 24 바이트가 필요하고 내장 및 소수를 얻기 위해 내장을 사용하기 때문에 팩토링을 쉽게 할 수있는 방법이 없다고 생각 합니다. 아니면 더 짧은 방법이 있는데 보이지 않습니다.
마일


7

하스켈, 28 바이트

f n=sum[1|1<-gcd n<$>[1..n]]

상수 의 Haskell 패턴 일치를 사용합니다 . 여기의 트릭은 골프에 대한 표준이지만, 일반 청중에게 설명하겠습니다.

표현은 gcd n<$>[1..n]매핑 gcd n[1..n]. 즉,은을 계산 gcd하여 n각 번호 1n:

[gcd n i|i<-[1..n]]

여기에서 원하는 출력은 1항목 수 이지만 Haskell에는 count기능 이 없습니다 . filter만 유지 1하고 결과를 얻는 관용적 인 방법 length은 골프에 너무 길다.

대신,는 결과 list와의 filter목록 이해 [1|1<-l]로 시뮬레이션됩니다 l. 일반적으로 list comprehensions는 in과 같이 값을 변수에 바인딩 [x*x|x<-l]하지만 Haskell을 사용하면 패턴을 일치시킬 수 있습니다 (이 경우 constant) 1.

따라서의 각 일치 항목에 대해를 [1|1<-l]생성 하여 원본 목록의를 정확하게 추출 합니다. 전화 를 걸면 길이가 길어집니다.111sum


나는 이것이 실제로 이해하는 첫 번째 Haskell 답변이라고 생각합니다. 정말 멋진 언어이지만 대부분의 다른 언어와는 다릅니다 .
bkul

와우, 이해 패턴에서 패턴 일치가 철저해야한다고 생각했습니다. 트릭 주셔서 감사합니다.
Damien

7

파이썬 2, 44 바이트

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

덜 골프 :

f=lambda n:n-sum(f(d)for d in range(1,n)if n%d<1)

제수의 Euler 출원인의 n합이 n다음 과 같은 공식을 사용합니다 .

enter image description here

ϕ(n)그런 다음 의 값은 n사소한 제수에 대한 합계 를 뺀 것으로 재귀 적으로 계산할 수 있습니다 . 효과적으로, 이것은 정체성 함수에 대한 뫼비우스 역전 을하고 있습니다. 골프에서 Möbius 함수를 계산하기 위해 같은 방법을 사용했습니다 .

더 나은 기본 사례로 1 바이트를 저장 하고 각 루프 +n+1대한 초기 값을 다음과 같이 분산시킨 Dennis에게 감사합니다 .n-~



5

J, 11 바이트

+/@(1=+.)i.

용법

>> f =: +/@(1=+.)i.
>> f 44
<< 20

여기서 >>STDIN <<은 STDOUT입니다.

설명

+/ @ ( 1 = +. ) i.
               │
   ┌───────────┴┐
 +/@(1=+.)      i.
   │
 ┌─┼──┐
+/ @ 1=+.
    ┌─┼─┐
    1 = +.

>> (i.) 44            NB. generate range
<< 0 1 2 3 4 ... 43
>> (+.i.) 44          NB. calculate gcd of each with input
<< 44 1 2 1 4 ... 1
>> ((1=+.)i.) 44      NB. then test if each is one (1 if yes, 0 if no)
<< 0 1 0 1 0 ... 1
>> (+/@(1=+.)i.) 44   NB. sum of all the tests
<< 20

수직 트리 표현은 어떻게 얻었습니까? 나는 그것이 수평으로 만 생산된다고 생각했다.
마일

@ 마일 내가 직접 입력했습니다.
Leaky Nun

5

파이썬> = 3.5, 76 64 58 바이트

12 바이트 (!) 바이트의 골프를 해주신 LeakyNun에게 감사드립니다.

6 바이트를 골라 낸 Sp3000에 감사합니다.

import math
lambda n:sum(math.gcd(n,x)<2for x in range(n))

나는 파이썬이 얼마나 읽기 쉬운 지 사랑합니다. 이것은 골프를 쳐도 마찬가지입니다.


1
lambda n:sum(gcd(n,x)<2for x in range(n))
Leaky Nun

아, 파이썬은 마침내 gcd수학 모듈에 추가되었습니다 ! 나는 그것을 몰랐다.
rubik

5

정규식 (ECMAScript), 131 바이트

Deadcode 덕분에 최소한 -12 바이트 (채팅 중)

(?=((xx+)(?=\2+$)|x+)+)(?=((x*?)(?=\1*$)(?=(\4xx+?)(\5*(?!(xx+)\7+$)\5)?$)(?=((x*)(?=\5\9*$)x)(\8*)$)x*(?=(?=\5$)\1|\5\10)x)+)\10|x

온라인으로 사용해보십시오!

출력은 일치하는 길이입니다.

ECMAScript 정규식은 무엇이든 계산하기가 매우 어렵습니다. 루프 외부에 정의 된 모든 역 참조는 루프 동안 일정하며 루프 내부에 정의 된 모든 역 참조는 반복 할 때 재설정됩니다. 따라서 루프 반복에서 상태를 전달하는 유일한 방법은 현재 일치 위치를 사용하는 것입니다. 그것은 하나의 정수이고, 그것은 단지 감소 할 수 있습니다 (글쎄, 위치는 증가하지만 꼬리의 길이는 감소하며 이것이 우리가 수학 할 수있는 것입니다).

이러한 제한을 감안할 때 단순히 코 프림 수를 계산하는 것은 불가능한 것 같습니다. 대신에, 우리는 Euler의 공식 을 사용하여 계급을 계산합니다.

의사 코드에서 다음과 같이 표시됩니다.

N = input
Z = largest prime factor of N
P = 0

do:
   P = smallest number > P that’s a prime factor of N
   N = N - (N / P)
while P != Z

return N

이것에 대해 두 가지 모호한 점이 있습니다.

먼저 입력을 저장하지 않고 현재 제품 만 저장하므로 입력의 주요 요소를 어떻게 얻을 수 있습니까? 비결은 (N-(N / P))에 N과 같은 소인수> P가 있다는 것입니다. 새로운 소인수 <P를 얻을 수도 있지만 어쨌든 무시합니다. 우리는 가장 작은 것에서 가장 큰 것까지 주요 요소를 반복하고 다른 방법으로는 실패하기 때문에 작동합니다.

둘째, 루프 반복에서 두 개의 숫자를 기억해야합니다 (P와 N, Z는 상수이므로 계산하지 않습니다). 고맙게도이 두 숫자를 하나의 숫자로 쓸어 넘길 수 있습니다. 루프가 시작될 때 N은 항상 Z의 배수이고 P는 항상 Z보다 작습니다. 따라서 N + P를 기억하고 모듈로 P를 추출 할 수 있습니다.

약간 더 자세한 의사 코드는 다음과 같습니다.

N = input
Z = largest prime factor of N

do:
   P = N % Z
   N = N - P
   P = smallest number > P that’s a prime factor of N
   N = N - (N / P) + P
while P != Z

return N - Z

주석이 달린 정규식은 다음과 같습니다.

# \1 = largest prime factor of N
# Computed by repeatedly dividing N by its smallest factor
(?= ( (xx+) (?=\2+$) | x+ )+ )

(?=
        # Main loop!
        (
                # \4 = N % \1, N -= \4
                (x*?) (?=\1*$)

                # \5 = next prime factor of N
                (?= (\4xx+?) (\5* (?!(xx+)\7+$) \5)? $ )

                # \8 = N / \5, \9 = \8 - 1, \10 = N - \8
                (?= ((x*) (?=\5\9*$) x) (\8*) $ )

                x*
                (?=
                        # if \5 = \1, break.
                        (?=\5$) \1
                |
                        # else, N = (\5 - 1) + (N - B)
                        \5\10
                )
                x
        )+
) \10

그리고 보너스로…

정규식 (ECMAScript 2018, 일치 수), 23 바이트

x(?<!^\1*(?=\1*$)(x+x))

온라인으로 사용해보십시오!

출력은 일치 횟수입니다. ECMAScript 2018에서는 가변 길이 룩-비하인드 (오른쪽에서 왼쪽으로 평가됨)를 사용하여 입력과 함께 모든 숫자를 함께 계산할 수 있습니다.

이것은 독립적으로 Leaky Nun의 Retina 솔루션 에서 사용하는 것과 동일한 방법 이며, 정규식도 같은 길이 ( 및 상호 교환 가능 )입니다. 이 방법이 ECMAScript 2018 (.NET뿐만 아니라)에서도 작동하는 것이 흥미로울 수 있으므로 여기에 남겨 두겠습니다.

                        # Implicitly iterate from the input to 0
x                       # Don’t match 0
 (?<!                 ) # Match iff there is no...
                 (x+x)  # integer >= 2...
         (?=\1*$)       # that divides the current number...
     ^\1*               # and also divides the input

4

펄 6 ,  26 24  22 바이트

{[+] (^$^n Xgcd $n) X== 1}
{+grep 2>*,(^$_ Xgcd$_)}
{[+] 2 X>(^$_ Xgcd$_)}

설명:

{
  [+] # reduce using &infix:<+>
    2
    X[>] # crossed compared using &infix:«>»
    (
      ^$_    # up to the input ( excludes input )
      X[gcd] # crossed using &infix:<gcd>
      $_     # the input
    )
}

예:

#! /usr/bin/env perl6
use v6.c;

my  = {[+] 2 X>(^$_ Xgcd$_)};

say φ(1) # 1
say φ(2) # 1
say φ(3) # 2
say φ(8) # 4
say φ(9) # 6
say φ(26) # 12
say φ(44) # 20
say φ(105) # 48

say φ 12345 # 6576


4

줄리아, 25 바이트

!n=sum(i->gcd(i,n)<2,1:n)

sum함수는 간단합니다.이 함수를 사용하면 합산하기 전에 적용 할 수있는 기능을 제공 할 수 있습니다. 기본적으로 달리기 map와 같다는 것입니다 sum. 상대적 소수보다 작은 소수를 직접 계산합니다 n.


4

파이썬 2, 57 바이트

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

Ideone에서 테스트하십시오 .

배경

으로 오일러의 제품 공식 ,

Euler's product formula

여기서 φ는 오일러의 고지 함수를 나타내고 p 는 소수에 대해서만 변합니다.

소수를 식별하기 위해 우리는 Wilson 정리 정리를 사용합니다 .

corollary of Wilson's theorem

작동 원리

항상 변수 mk-1 계승의 제곱과 같습니다 . 실제로 인수의 이름은 기본적으로 k = 1 이고 m = 0입니다. 2 = 1 입니다.

만큼 K ≤ N , n*(k>n)평가하여 행 0 및 코드 다음 or실행 얻는다.

리콜 m%k보장 할 일을 하는 경우 m이 소수와 하지 않을 경우. 이 수단 x%k<m%k얻을 것입니다 진정한 두 경우 만 k는 소수이고, X 로 나누어 K .

이 경우 (n%k<m%k)*n/k수율 N / K , 및로부터 감산 N 과 이전 값으로 대체하는 N (1 - 1 / K)을 오일러 식 제품에서와 같이. 그렇지 않으면 (n%k<m%k)*n/k수율 0n 은 변경되지 않습니다.

상기를 계산 한 결과 증분 케이 와 승산 m 의 "오래된"값에 의해 K 2 따라서 간의 바람직한 관계를 유지하고, Km은 다음 호출 f를 업데이트 인수 재귀.

일단 k를 초과 N , n*(k>n)평가를 N 함수에 의해 리턴된다.


4

루비, 32 바이트

->n{(1..n).count{|i|i.gcd(n)<2}}

정수 n을 취하고 범위 (1..n)에있는 정수가 n과 같은 프라임 수를 나타내는 람다


안녕하세요, PPCG에 오신 것을 환영합니다! 이것은 훌륭한 첫 번째 게시물입니다.
NoOneIsHere6

프로그래밍 퍼즐과 코드 골프에 오신 것을 환영합니다! 이것은 훌륭한 첫 번째 해결책입니다.
bkul

고마워요, 그렇게 짧지는 않지만 개선이 가능한지 궁금합니다.
Redouane Red

3

Brachylog , 25 바이트

:{:1e.$pdL,?$pd:LcCdC}fl.

설명

Brachylog에는 아직 GCD가 내장되어 있지 않으므로 두 숫자에 공통 요소가 없는지 확인합니다.

  • 주요 술어 :

    :{...}fl.             Find all variables which satisfy predicate 1 when given to it as
                          output and with Input as input.
                          Unify the Output with the length of the resulting list
    
  • 술어 1 :

    :1e.                  Unify Output with a number between Input and 1
        $pdL              L is the list of prime factors of Output with no duplicates
            ,
             ?$pd:LcC     C is the concatenation of the list of prime factors of Input with
                          no duplicates and of L
                     dC   C with duplicates removed is still C
    


3

PowerShell v2 +, 72 바이트

param($n)1..$n|%{$a=$_;$b=$n;while($b){$a,$b=$b,($a%$b)};$o+=!($a-1)};$o

PowerShell에는 사용 가능한 GCD 기능이 없으므로 직접 롤백해야했습니다.

이것은 입력 을 받고 $n, 범위에서 루프로 파이프합니다 . 반복 할 때마다 우리는 두 도우미 변수를 설정 하고 다음 GCD의 실행 루프를. 우리가 확인하는 각 반복 은 여전히 ​​0 이 아니며 다음 루프 에 대한 이전 값 을 저장 합니다 . 그런 다음 출력 변수와 같은지 여부를 누적합니다.1$n|%{...}$a$bwhile$b$a%$b$b$b$a$a1$o . for 루프가 완료되면$o 파이프 라인에 하고 출력은 암시 적입니다.

어떻게 '의 예로서 while루프 작품, 고려 $n=20우리가있어 $_=8. 첫 번째 검사는 $b=20이므로 루프에 들어갑니다. 우리는 먼저 계산 $a%$b또는 8%20 = 8로 설정됩니다, $b같은 시간에 20에 세트를 가져옵니다 $a. 확인 8=0하고 두 번째 반복을 입력하십시오. 그런 다음이를 계산 20%8 = 4하여로 설정 $b한 다음로 설정 $a합니다 8. 확인 4=0하고 세 번째 반복을 입력하십시오. 이를 계산 8%4 = 0하여로 설정 $b한 다음로 설정 $a합니다 4. 0=0루프를 확인 하고 종료하면 GCD (8,20)$a = 4입니다. 따라서, !($a-1) = !(4-1) = !(3) = 0그래서 $o += 0우리는 그 일을 계산에 포함되지 않습니다.


3

요소, 50 바이트

[ dup iota swap '[ _ gcd nip 1 = ] filter length ]

범위 (만든다 IOTA ) N카레 N 얻는 함수로 GCD XN 모두 값 0 <= X <= N 결과 인 경우, 테스트 (1) . gcd xn 의 결과 가 1 인지 여부에 대한 원래 범위를 필터링 하고 길이를 가져 옵니다 .


[ dup iota swap '[ _ gcd nip 1 = ] map sum ]6 바이트를 절약합니다 (요소에 대해서는별로 경험하지 않았습니다).
bkul

@bkul 제안 해 주셔서 감사합니다! : D 불행하게도, t/fFactor에서 숫자와 (기호) 사이에는 호환성이 없으므로 , 그것을 구현하는 유일한 방법 [ dup iota swap '[ _ gcd nip 1 = 1 0 ? ] map sum ]은 현재 솔루션과 동일한 길이입니다.
고양이

아, 댕 타이핑이 다시 강렬합니다.
bkul

@bkul 글쎄, 나는 강력한 타이핑과 실제 요소 코드 TYPED:에 감사 합니다 : P
cat


2

레티 나, 36 29 바이트

Martin Ender 덕분에 7 바이트.

.+
$*
(?!(11+)\1*$(?<=^\1+)).

온라인으로 사용해보십시오!

설명

두 단계 (명령)가 있습니다.

첫 단계

.+
$*

입력을 많은 수로 변환하는 간단한 정규식 대체입니다.

예를 들어, 5변환 될 것이다11111 .

두 번째 단계

(?!(11+)\1*$(?<=^\1+)).

이 정규 표현식은 조건을 만족하는 위치 (입력과 함께 공동 프라임)를 일치시킨 다음 일치 횟수를 반환합니다.


Lookbehind는 lookahead 내부가 아닌 한 역 추적하지 않습니까?
Leaky Nun

둘러보기는 일반적으로 역 추적되지 않습니다.
Martin Ender 2016 년

그렇다면 정규 표현식이 모든 제수를 어떻게 테스트 했습니까?
Leaky Nun

1
그래서 그들은 만큼 당신이 그들을 떠나지 않는 한 철수. 엔진이 둘러보기 내에있는 한 해당 둘러보기를 일치시킬 수있는 모든 것을 시도합니다 (또는 부정적인 둘러보기의 경우 실패). lookaround이 통과되면하지만, 엔진이 경우 아무 것도 (그 다음 또한 물건을 역 추적하기 시작하지 않는 한 실패 후 철수 그것으로하지 않습니다 전면 어쨌든 lookaround과 재평가 모든 것에있다).
Martin Ender 2016 년

2

공통 리스프, 58 바이트

(defun o(x)(loop for i from 1 to x if (=(gcd x i)1)sum 1))

이것은 주어진 n까지 1을 카운트하고 gcd = 1 인 경우 합계를 증가시키는 간단한 루프입니다. t는 실제 부울 값이므로 함수 이름 o를 사용합니다. 가장 짧지는 않지만 매우 간단합니다.


CL에는 익명의 기능이 없습니까?
고양이

2

MATLAB / 옥타브, 21 바이트

@(n)sum(gcd(n,1:n)<2)

ans정수 n를 유일한 입력으로 호출 할 수 있는 익명의 함수 를 작성합니다.ans(n)

온라인 데모





1

자바 스크립트 (ES6), 67 바이트

f=n=>[...Array(n)].reduce(r=>r+=g(n,++i)<2,i=0,g=(a,b)=>b?g(b,a%b):a)


1

APL, 7 바이트

+/1=⊢∨⍳

이것은 오른쪽에 정수를 갖는 모나 딕 함수열입니다. 여기서 접근 방식은 명백한 방법입니다. sum ( +/) 입력의 GCD 횟수와 1에서 입력까지의 숫자 ( ⊢∨⍳)는 1 ( 1=) 과 같습니다 .

여기 사용해보십시오


1

하스켈, 31 30 바이트

\n->sum[1|x<-[1..n],gcd n x<2]

@Damien 덕분에 1 바이트가 절약되었습니다.

gcd = 1 인 값을 선택하고 각각을 1에 매핑 한 다음 합계를 가져옵니다.


당신은 대체 할 수 있습니다 ==1에 의해<2
데미안

1

배치, 151 (145) 144 바이트

@echo off
set t=
for /l %%i in (1,1,%1)do call:g %1 %%i
echo %t%
exit/b
:g
set/ag=%1%%%2
if not %g%==0 call:g %2 %g%
if %2%==1 set/at+=1

편집 : 불필요한 공간을 제거하여 4 바이트를 절약했습니다. 을 사용하여 1 바이트를 저장했습니다 +=. 어쨌든 그것을 해석 할 것이므로 1 바이트를 삭제 t했습니다 . @ EʀɪᴋᴛʜᴇGᴏʟғᴇʀ 덕분에 1 바이트를 절약했습니다.+=0

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.