소수 표현 기간


16

단일 양의 정수 n 을 취하고 1 / n 의 소수 표현주기를 리턴 하는 함수를 작성하십시오 .

테스트 사례 :

1 -> 1               # 1/1 = 1.0000...... = 1._0
2 -> 1               # 1/2 = 0.5000...... = 0.5_0
3 -> 1               # 1/3 = 0.3333...... = 0._3
7 -> 6               # 1/7 = 0.14285714.. = 0._142857
13 -> 6
14 -> 6
123 -> 5
345 -> 22
654 -> 108
12345 -> 822
67890 -> 120

이것은 입니다. 기간을 직접 반환하는 내장 또는 라이브러리는 허용되지 않습니다. 합리적인 시간 (최대 몇 분) 내에 최대 100000 이상의 숫자가 작동해야합니다.


문제는 "적어도 100000까지의 숫자는 합리적인 시간 내에 작동해야한다"고 말하지만 프로그램은 이보다 큰 숫자에 대한 올바른 답 을 제공 해야 합니까? 아니면 최대 100000까지만 정확한 알고리즘을 사용할 수 있습니까?
FireFly

1
@FireFly 알고리즘은 정답을 제공해야합니다.
Howard

2
1이 1을 반환하는 이유는 무엇입니까? 나는 0을 생각 할까?
Timtech

@Timtech1.00000000000000000000000000000000000
Cruncher

@Cruncher 오 감사합니다.
Timtech

답변:


11

APL, 19 자 / 바이트 *

{(↑⍳⍨1∘↓)⌽⍵|10x*⍳⍵}

Nars2000 . 이전 버전은 일부 숫자에서 잘못되었습니다. 맞습니다. 최대 50까지 모든 숫자를 수동으로 확인했습니다.

다시 한번, 신용은 Ben Reich 에게 갑니다.10^i (mod x)

분해도

{                     ⍳⍵}   generate all naturals up to the argument ⍵
                 10x*       raise 10 to each of them, with unlimited precision
              ⍵|            compute the respective remainders mod ⍵
            ⌽               reverse the list
 (  ⍳⍨    )                 (fork) find the position of the first occurrence
  ↑                         of the fist element of the list
       1∘↓                  in the remainder of the list

      {(↑⍳⍨1∘↓)⌽⍵|10x*⍳⍵}¨1 2 3 7 13 14 123 345 654 12345 67890
1 1 1 6 6 6 5 22 108 822 120

* : APL 기호를 상위 128 바이트 값에 매핑하는 자체 (레거시) 단일 바이트 문자 집합으로
APL을 작성할 수 있습니다. 따라서 스코어링을 위해 ASCII 문자와 APL 기호 만 사용하는 N 문자 프로그램은 N 바이트 길이로 간주 될 수 있습니다.


예를 들어 input에 대한 정답을 얻을 수 없습니다 20. 확인 부탁드립니다.
Howard

나는 당신이 게시 한 예를 따랐습니다. 귀하의 예에서 1/2 = 0.5-> 1이므로 자연스럽게 1/20 = 0.05-> 2입니다.
Tobia

1/20 = 0.05_0_이므로 정답은 1입니다.
Howard

내가 참조. 조금만 줘요. 대답을 수정하겠습니다.
Tobia

4왜냐하면 그것은 잘못된 답변을 줄 것입니다 10 != 100 (mod 4).
피터 테일러

7

골프 스크립트 ( 42 27)

{:x)1\[{.10*x%}*]-1%(?)}:P;

벤치 마크 시간 : 5 초 벤치마킹 코드 :

'"The time is #{Time.now#1
}"'~ puts
[1 2 3 7 13 14 123 345 654 12345 67890 99991]{[P]p}%
'"The time is #{Time.now#2
}"'~ puts

시대를 바라 보는 핵심 아이디어에 대해 Ben Reich에게 감사드립니다 10^i (mod x).

설명

주기 p는 충분히 큰 값 i을 갖도록 가장 작은 양의 정수로 정의됩니다 frac(10^i * 1/x) = frac(10^(i+p) * 1/x). 우리는이를 약간 단순화 할 수 있습니다 frac(10^i / x) = frac(10^(i+p) / x). 이제, frac(a / x) = frac(b / x)IFF a == b (mod x), 우리는 그와 같은 모든 충분히 큰 가장 작은 양의 정수를 찾고 있도록 i: 10^i == 10^(i+p) (mod x).

가정 해 봅시다 10^i == 10^(i+p) (mod x). 그런 다음 10^(i+1) == 10 * 10^i == 10 * 10^(i+p) == 10^(i+p+1) (mod x); 반복을 받으면 깨질 수없는주기에 있습니다.

x별개의 가치 만 (mod x)있기 때문에 비둘기 구멍 원리에 따라 첫 번째 x + 1값 에서 반복을 얻어야합니다 10^i (mod x).

위의 코드 x + 210^i (mod x)* 값 을 계산하는 것입니다 . 그런 다음 마지막 항목은 반복되는 것으로 보장되며 목록을 되돌리고 검색하여 가장 최근 항목을 찾을 수 있습니다. 또한, 나는 하나의 검색 만하고 있기 때문에 이것은 의사 선형 시간입니다.

* 여분의 것은 특별한 경우를 처리하는 것 입니다 . x = 1축소하지 않기 때문에 in을 10^0 (mod x)찾고 있기 때문 0입니다 [1].


대박! 더 나은 솔루션이므로 내 답변을 삭제했습니다! –
Ben Reich

7

골프 스크립트-26 바이트

{:i.)+.,{;10*i%.}%i>|,}:f;

편집 : 1소수점 표현의 길이가 아닌 소수점이 종료되면 출력으로 업데이트되었습니다 .

상당히 효율적인 버전입니다. 값 67890 은 약 10 초, 99991은 약 20 초 동안 실행됩니다. 반복되는 범위가 두 배가되었으므로 전반이 무시되기 때문에 이전보다 약간 느립니다 (대략 절반 정도 빠름).

대안, 또한 26 바이트

{:i.)+.n*{*i%.}%i>)^^,}:f;

이것은 문자열을 반복하여 작동합니다 "\n"*(2*i+1). 여기서 i값은 함수에 전달됩니다. 블록마다에 전달 된 값의 서수 값 "\n"이다 (10) .

)^^작업 주위의 비트입니다. 이 때 uncons 문자열에서 문자를 위에서 언급 한 바와 같이, 결과는 제거 된 문자의 순서 값이다. 그러나 그 값을 다시 추가 하면 문자가 아닌 해당 숫자 의 문자열 표현 이 추가됩니다 -상당히 비대칭적인 행동이며 제 생각에는 디자인 결함이 있습니다. 실제로 그렇게하고 싶다면 먼저 문자열을 지정하는 데 1 바이트가 필요합니다.

최종 값의 추가 사본이 이미 스택에 있으므로 최종 값을 다시 제거 )하고 문자열로 xor 값을 제거한 다음 다시 xor 값을 제거하여 첫 번째 xor에 의해 추가되거나 제거 된 문자가 복원됩니다. int op string문자열 표현이 아닌 문자로 처리 된 경우 )^^로 대체 될 수 있습니다 |.

문자열 (골프 스크립트에서 int 배열로 저장 됨)에는 각 문자 mod 256 의 값이 표시 되지만 각 문자 값 자체는이 범위를 벗어날 수 있습니다. 고유성 (설정된 작업을 통해) 또는 포함도 (를 통해 ?) 를 테스트 할 때 표시 값이 아닌 비교되는 실제 값입니다.

현재 Golfscript 인터프리터 의 패치 파일 :

61c61
<       to_gs
---
>       Gstring.new([self])

위의 동작 중 하나에 만 영향을 미치며 string op int그 반대의 경우도 마찬가지 op입니다
+-|&^. 의 동작을 포함하여 다른 모든 사항은 영향을받지 않습니다 Gint`.

그러면 다음 24 바이트 솔루션이 유효 해집니다.

{:i.)+.n*{*i%.}%i>|,}:f;

그리고 이것은 또한 다른 많은 추악한 해결 방법을 수정합니다 .


파이썬-48 바이트

f=lambda n:len(set(10**-~i%n for i in range(n)))

가장 효율적인 솔루션은 아니지만 100000 미만의 값에 적합합니다 .

FWIW, 핵심 요소는 십진수로 순환 숫자 생성에 대한 솔루션과 동일합니다 .

동일한 코드의보다 효율적인 버전 ( 70 바이트 ) :

 def f(n):
  a=[];i=10%n
  while i not in a:a+=i,;i=i*10%n
  return len(a)

99991 값 은 1 초 미만입니다.


@PeterTaylor or배열을 빈 문자열에 넣습니다. 설정 작업이므로 모든 복제본이 미리 제거됩니다.
primo

그러나 빈 줄은 어디에서 왔습니까? 함수가 자체적으로 포함되어야한다면 여분의 바이트를 소비하고 만들어야한다고 생각합니다 .|.
피터 테일러

1
@PeterTaylor가 수정되었습니다 .
primo

1
동작을 변경하면 많은 프로그램 string int +이 중단 됩니다. 해당 유형 쌍에서 다른 op가 얼마나 자주 사용되는지 잘 모르겠습니다.
피터 테일러

@PeterTaylor 동의합니다. 그러나 고려 : 문자로 변환 지능 : []+''+''+. 문자열을 문자로 추가]를 INT, : []+++. Apend은 문자열로, 문자열 표현으로, 값 int : +`+. 현재 구현 int''+에서는와 동의어입니다. int`배열로 강제 변환 해야하는 세부 사항을 고려한 다음 아스키 문자를 원하면 문자열로 강제 변환하는 것을 고려하면 낭비되는 것처럼 보입니다.
primo

3

골프 스크립트, 48 47 46

두 글자를 자르는 @PeterTaylor에게 감사드립니다.

{2{1$1$%!{.@\/\d}*}:d~;5d;9{2$%}{10*9+}/+,}:f;

J를 사용해 보았지만 모든 종류의 이상한 결과가 계속 나왔습니다.

온라인 테스트

이것은 기본적으로 숫자에서 2와 5를 나눕니다 (2와 5는 10의 주요 요소이며 그 역수는 종료하고 알고리즘을 채 웁니다). 그 결과 숫자가 10 ^ n-1을 나누도록 가장 낮은 정수 n이 기간.


3
함수에 대한 첫 번째 호출이 어느 것인지 알면 정의를 인라인 할 수 있습니다. {...}:d;...d당신 대신에 1 개의 문자를 저장하십시오...{...}:d~
Peter Taylor

@PeterTaylor 감사합니다, 그렇게 생각하지 않았다
변동성

1
f스택에 남기지 말라고 Ben에게 의견을 말하면 , 당신도 그렇게하고 있음을 알았습니다. ;다른 언어와의 공정한 비교를 위해 함수를 표시하려면 실제로를 추가해야 합니다.
Peter Taylor

2
또 다른 미세 최적화 : int array ,)\;로 단축 할 수 있습니다 int array +,.
피터 테일러

2

펄, 52 자

sub f{($p,%r)=1;1until$r{$p=$p*10%$_[0]}++;~~keys%r}

이것은 직접적인 접근 방식의 복잡하지 않은 구현입니다. (다행히도 직접 접근 방식도 매우 효율적입니다. 모듈로 산술 덕분에 수학은 입력 값의 10 배 이상을 처리 할 필요가 없습니다.)

도전 과제가 함수를 지정했기 때문에 나는 완전한 프로그램을 위해 귀찮게하지 않을 변수를 (재) 초기화해야한다고 느꼈습니다. 마찬가지로 ~~함수가 스칼라 컨텍스트에서 호출 될 것이라고 확신 할 수있는 경우 마지막 명령문에서 불필요합니다.


20잘못된 결과가 나오는 입력을 시도하십시오 .
Howard

2

클로저, 102, 117, 115, 106

형식화되지 않은 :

(defn r([n](r{}(iterate #(mod(* % 10)n)10)0))([a[f & s]i](if(a f)(- i(a f))(recur(assoc a f i)s(inc i)))))

형식화 :

(defn r
  ([n] (r {} (iterate #(mod (* % 10) n) 10) 0))
  ([a [f & s] i]
    (if (a f)
      (- i (a f))
      (recur
        (assoc a f i)
        s
        (inc i)))))

실행 시간은 기간에 따라 다릅니다. 샘플 값은 컴퓨터에서 거의 즉각적으로 나타납니다.

기본적으로 긴 분할의 각 단계 후 빼기 결과를 계산합니다. 어떤 시점에서 그 숫자가 이전에 계산 된 것과 동일하면 사이클이 감지됩니다.


코드는 input으로 중단됩니다 20. 확인 부탁드립니다.
Howard

위의 해결책에 결함이 있습니다. 내가 고칠 수 있는지 봅시다.
RedDeckWins

20에 대한 예상 결과는 무엇입니까?
RedDeckWins

정답은 1입니다.
Howard

좋은 알고리즘이되어야합니다. 첫 번째 알고리즘은 많은 입력 (예 : 12 및 20)에서 실패합니다.
RedDeckWins

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