최소 잔여 시퀀스 생성


21

모든 숫자는 무한히 긴 나머지 시퀀스를 사용하여 표현할 수 있습니다. 우리가 숫자 7을하고, 수행하는 경우 예를 들어 7mod2, 다음 7mod3, 다음 7mod4, 등등, 우리가 얻을 1,1,3,2,1,0,7,7,7,7,.....

그러나 모든 하위 수와 구별하기 위해 여전히 사용할 수 있는 가장 짧은 나머지 하위 시퀀스 가 필요합니다 . [1,1,3]이전의 모든 하위 시퀀스가 ​​다음으로 시작하지 않기 때문에 7을 다시 사용 하는 것이 가장 짧은 하위 시퀀스입니다 [1,1,3].

0: 0,0,0,0...
1: 1,1,1,1...
2: 0,2,2,2...
3: 1,0,3,3...
4: 0,1,0,4...
5: 1,2,1,0...
6: 0,0,2,1...

참고 [1,1] 하지 않습니다 또한 그러나 1을 나타내는 데 사용할 수 있기 때문에 작업은 정상적으로 출력, 7 나타내는 [1]하나의 입력과 함께.

입출력

입력은 음이 아닌 정수입니다. 위에 정의 된대로 최소 길이 시퀀스의 시퀀스 또는 목록을 출력해야합니다.

테스트 사례 :

0: 0
1: 1
2: 0,2
3: 1,0
4: 0,1
5: 1,2
6: 0,0,2
7: 1,1,3
8: 0,2,0
9: 1,0,1
10: 0,1,2
11: 1,2,3
12: 0,0,0,2
30: 0,0,2,0
42: 0,0,2,2
59: 1,2,3,4
60: 0,0,0,0,0,4
257: 1,2,1,2,5,5
566: 0,2,2,1,2,6,6
1000: 0,1,0,0,4,6,0,1
9998: 0,2,2,3,2,2,6,8,8,10
9999: 1,0,3,4,3,3,7,0,9,0

관심있는 경우를 위해 처음 10,000 개의 시퀀스 가 있습니다 (행 번호가 1 씩 꺼짐).

이것은 이므로 원하는 언어로 가능한 한 짧게 만드십시오. 빠른 답변에 대한 가짜 보너스 포인트!



@nimi 우리는 채팅에서 그것에 대해 이야기했으며, 시퀀스는 적어도 1 요소 길이가되어야한다고 결정했습니다.
Nathan Merrill

1
나는 당신이 나머지를 소수로 제한하지 않았다는 것에 약간 놀랐습니다.
Neil

출력이 목록에 반환되면 괜찮습니까?
R. Kap

@neil, 나는 또한 그것을 고려했지만 나머지는 복합 숫자와 다르기 때문에 나는 그것을 유지하기로 결정했습니다.
Nathan Merrill

답변:


5

Mathematica, 60 53 바이트

#~Mod~FirstCase[2~Range~#&/@Range[#+2],x_/;LCM@@x>#]&

다소 빠릅니다 (~ 0.1 초 만에 10000을 처리하지만 100000 동안 메모리가 부족할 수 있습니다).

코드에서 오류가 발생하지만 결과는 올바르게 계산됩니다.

설명

채팅에서 필요한 제수는 항상 {1, 2, ..., n}최소 공배수가 입력을 초과하는 가장 짧은 목록으로 결정될 수 있음을 발견했습니다 . LCM이 입력 값보다 작은 경우 입력에서 LCM을 빼면 모든 제수가 변경되지 않으므로 표현이 고유하지 않습니다. 그러나 LCM보다 작은 모든 입력의 경우 나머지가 고유합니다. 그렇지 않으면 동일한 나머지를 가진 두 숫자의 차이는 모든 제수의 작은 배수가됩니다.

코드에 관해서는 ... 평소와 같이 골프 용 Mathematica의 읽기 순서는 약간 재미 있습니다.

Range[#+2]

이것은 우리에게 [1, 2, 3, ..., n+2]입력 목록 을 얻는다 n. 는 +2이 올바르게 작동하는지 확인하는 것입니다 01.

2~Range~#&/@...

이 목록 위에 지도 2~Range~#(구문 설탕 Range[2,#])를 입력하면

{{}, {2}, {2,3}, ..., {2,3,...,n+2}}

이들은 후보 제수 목록입니다 (물론 일반적으로 우리가 필요로하는 것보다 훨씬 더 많습니다). 이제 우리는 LCM이 입력을 초과하는 첫 번째 것을 찾습니다.

FirstCase[...,x_/;LCM@@x>#]

더 많은 구문 : x_목록과 일치하는 패턴입니다 x. 는 /;그 패턴에 조건을 첨부합니다. 이 조건은 LCM@@x>#어디에 @@ 적용 목록, 즉로 기능을 LCM@@{1,2,3}수단 LCM[1,2,3].

마지막으로, 우리는 모든 나머지를 얻는다 . 즉, 인수 중 하나가리스트 인 경우 (또는 둘 다 같은 길이의리스트 인 경우 Mod) Listable, 즉 사실을 이용 하여리스트를 자동으로 맵핑한다 :

#~Mod~...

5

젤리 , 14 바이트

‘Ræl\>iṠ2»2r⁸%

이것은 선형 합동 시스템의 솔루션 (있는 경우)이 모듈러스의 LCM에 고유 한 모듈로라는 사실을 사용합니다. 온라인으로 사용해보십시오! 또는 모든 테스트 사례를 확인하십시오 .

작동 원리

‘Ræl\>iṠ2»2r⁸%  Main link. Argument: n

‘               Increment; yield n+1.
 R              Range; yield [1, ..., n+1].
  æl\           Cumulatively reduce by LCM.
                This yields [LCM(1), ..., LCM(1, ..., n+1)].
     >          Compare all LCMs with n.
      iṠ        Find the first index of sign(n).
                This yields the first m such that LCM(2, ..., m) > n if n > 0, and
                0 if n == 0.
        2»      Take the maximum of the previous result and 2, mapping 0 to 2.
          2r    Yield the range from 2 up to and including the maximum.
            ⁸%  Compute n modulo each integer in that range.

5

MATL , 24 바이트

이 답변의 이전 버전에서 오류를 지적 한 @nimi에게 감사드립니다 (현재 수정되었습니다)

Q:qtQ!\t0Z)tb=YpsSP2):Q)

두 가지 가장 큰 테스트 사례에 대한 온라인 컴파일러의 메모리가 부족합니다 (그러나 4GB RAM이있는 컴퓨터에서는 작동합니다).

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

설명

이것은 정의를 간단하게 적용합니다. 입력 n그것을 포함하는 2 차원 배열을 계산 mod(p,q)하여 p0n그리고 q1에이 n+1. 각각 p은 열이고 각각 q은 행입니다. 예를 들어, 입력 n=7으로이 배열은

0 0 0 0 0 0 0 0
0 1 0 1 0 1 0 1
0 1 2 0 1 2 0 1
0 1 2 3 0 1 2 3
0 1 2 3 4 0 1 2
0 1 2 3 4 5 0 1
0 1 2 3 4 5 6 0
0 1 2 3 4 5 6 7

이제의 나머지를 포함하는 마지막 n열은이 배열의 각 열과 비교하여 요소 별입니다. 이 결과

1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1
0 1 0 0 1 0 0 1
0 0 0 1 0 0 0 1
0 0 1 0 0 0 0 1
0 1 0 0 0 0 0 1
1 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1

여기서 1평등을 나타냅니다. 마지막 열은 분명히 그 자체와 동일하므로 모든 열을 포함합니다. 마지막 열 이외 의 초기수가 가장 많은 열을 찾아 해당 열의 초기 열 수를 기록해야합니다 m. (이 경우 m=3첫 번째 열이 포함 된 두 번째 열 입니다). 이를 위해 각 열의 누적 곱을 계산합니다.

1 1 1 1 1 1 1 1
0 1 0 1 0 1 0 1
0 1 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1
0 0 0 0 0 0 0 1

각 열의 합

1 3 1 2 1 2 1 8

그리고 점점 증가하지 않고 두 번째 값인을 가져옵니다 3. 이것은 m우리가 선택해야 할 나머지 수를 나타내는 원하는 것 입니다.

Q:q    % take input n implicitly. Generare row array [0 1 ... n]
tQ!    % duplicate. Transform into column array [1; 2; ...; n-1]
\      % modulo, element-wise with broadcast. Gives the 2D array
t0Z)   % duplicate. Take last column
tb     % duplicate, bubble up
=      % test for equality, element-wise with broadcast
Yp     % cumumative product of each column
s      % sum of each column. This gives the number of initial coincidences
SP2)   % sort in decreasing order and take second value: m
:Q     % generate range [2 3 ... m+1]
)      % apply as index into array of remainders of n. Implicitly display

4

젤리 , 13 11 바이트

r¬µ%€R‘$ḟ/Ṫ

이것은 속도 브라우니 포인트를 얻지 못합니다 ... 온라인으로보십시오! 또는 더 작은 테스트 사례를 확인하십시오 .

작동 원리

r¬µ%€R‘$ḟ/Ṫ  Main link. Argument: n

r¬           Range from n to (not n).
             This yields [n, ..., 0] if n > 0 and [0, 1] otherwise.

  µ          Begin a new, monadic chain. Argument: A (range)

       $     Combine the previous two links into a monadic chain:
     R         Range; turn each k in A into [1, ..., k] or [] if k == 0.
      ‘        Increment to map k to [2, ..., k+1].
   %€        Take each k in A modulo all the integers in the 2D list to the right.
        ḟ/   Reduce by filter-not; sequentially remove all remainder sequences of
             n-1, ..., (not n) from the remainder sequences of n.
          Ṫ  Tail; take the last remainder sequence.
             This gives the shortest sequence for descending A and the longest one
             (i.e., [0]) for ascending A.

왜 두 가지 답변을 포함 했습니까 ???
Outgolfer Erik

두 가지 완전히 다른 접근 방식이기 때문입니다. 이 크기는 3 바이트 짧지 만 다른 하나는 실제로 모든 테스트 사례를 계산하기에 충분히 빠릅니다.
Dennis

내가 당신이라면, 나는 그것을하지 않았을 것입니다 ... 그것이 위로 / 아래로 투표하는 경우를 제외하고.
아웃 골퍼 Erik

언어 / 접근법에 따라 답변이 다릅니다. 그것은 나의 첫 번째 메타 질문이었습니다.
Dennis

3

Python 3.5, 117 95 78 바이트

import sympy
r=lambda n,m=2,M=1,*l:M>n and l or r(n,m+1,sympy.lcm(m,M),*l,n%m)

Python 3.5 및 sympy ( python3 -m pip install --user sympy)가 필요합니다 . Python 3.5 *l에서 기본 인수로 트릭을 허용한다는 것을 알려주는 @Dennis의 의견입니다.


SymPy 0.7.5을 사용하면 줄일 수 있습니다 M>n and ll*(M>n).
Dennis

3

파이썬 2, 73 70 69 65 바이트

i=l=1
n=input()
while l<=n|1:
 i+=1;a=l;print n%i
 while l%i:l+=a

전체 프로그램. @Dennis는 0 처리 방식을 개선하여 4 바이트를 절약했습니다.


3

하스켈, 66 60 51 50 바이트

f i=mod i<$>[2..2+sum[1|l<-scanl1 lcm[2..i],l<=i]]

사용 예 : f 42-> [0,0,2,2]. @Martin Büttner의 답변에 설명 된 알고리즘 입니다.

꽤 빠르기 때문에 이전 버전을 참조로 유지합니다.

하스켈, 51 바이트

f i=mod i<$>[[2..x]|x<-[2..],foldl1 lcm[2..x]>i]!!0

f (10^100)5 살짜리 노트북 에서는 0.03 초가 걸립니다 .

편집 : @xnor는 저장할 바이트를 찾았습니다. 감사!


lcm이 너무 높아질 때까지 인덱스를 계산하여 바이트 저장 :h i=mod i<$>[2..2+sum[1|l<-scanl1 lcm[2..i],l<=i]]
xnor

2

Pyth, 51 바이트 66 바이트

IqQZ[Z).q)IqQ1[1))IqQ2,0 1))FdhhQJu/*GHiGHtUd1I>JQVQ aY%QhN)<tYd.q

사용해보십시오!

훨씬 빠른 속도의 39 바이트 버전 (0-2에서는 작동하지 않음) :

FdhhQJu/*GHiGHtUd1I>JQVtd aY%QhN)<tYd.q

10 10 3 과 같이 터무니없이 많은 수의 경우 작동하는 것 같습니다

참고 :이 답변은 0, 1 및 2에서 작동하지 않습니다 .


2

자바 스크립트 (ES6), 81 77 바이트

f=(n,r=[n%2],l=i=2,g=(j,k)=>j?g(k%j,j):k)=>l>n?r:f(n,[...r,n%++i],i/g(i,l)*l)

이것은 LCM이 원래 숫자를 초과 할 때까지 재귀 적으로 답을 만듭니다. 물론 GCD도 재귀 적으로 계산됩니다.

편집 : @ user81655 덕분에 4 바이트가 절약되었습니다.


@ user81655 방금 처리 된 것입니다 ...
Neil

2

루비, 52 바이트

->n{m=t=1;a=[];(a<<n%m)until n<t=t.lcm(m+=1);a<<n%m}

이 솔루션 m은 시퀀스를 독특하게 만드는 나머지 인 2부터 시작하여 가능한 모든 것을 확인합니다 . 마지막을 m고유 하게 만드는 것은 나머지 자체가 아니지만 해당 m범위 (2..m)의 최소 ​​공배수 (LCM)가보다 큰 가장 작은 범위의 마지막 멤버입니다 n. 이 고유 번호를 결정하기 위해 중국 잉여 정리로 인해 n나머지의 번호이고, 그 나머지의 LCM보다 커야합니다 n(있는 경우 선택 n에서 (1..n), 선택하는 경우 n에서 a..b의 LCM은보다 클 필요가 b-a)

참고 : 이전의 단락 은 고유하게하기 위해 마지막 요소를 받았기 a<<n%m때문에 코드 끝에 넣었 습니다 .until n<t=t.lcm(m+=1)a

골프 제안이 있으시면 의견이나 PPCG 채팅 에 알려주십시오 .

풀기 :

def remainder_sequence(num)
  # starting with 1, as the statements in the until loop immediately increments divisor
  divisor = 1
  # starts with 1 instead of 2, as the statements in the until loop
  # immediately change product to a new lcm
  product = 1
  remainders = []

  # this increments divisor first then checks the lcm of product and divisor
  # before checking if num is less than this lcm
  until num < (product = product.lcm(divisor = divisor + 1))
    remainders << num % divisor
  end

  # until always short circuits before the last element is entered
  # so this enters the last element and returns
  return remainders << num % divisor
end


1

파이썬 3.5 194 181 169 152 149 146 바이트 :

( 2 바이트에 @ Sherlock9 덕분에! )

def r(o,c=0):
 y=[[j%i for i in range(2,100)]for j in range(o+1)]
 while 1:
  c+=1;z=y[-1][:c]
  if z not in[f[:c]for f in y[:-1]]:break
 print(z)

완벽하게 작동하며 매우 빠릅니다. 최소한의 나머지 100000출력 시퀀스를 계산하는 [0, 1, 0, 0, 4, 5, 0, 1, 0, 10, 4, 4]데 약 3 초 밖에 걸리지 않았습니다. 심지어 입력 1000000(1 백만), 출력 의 시퀀스를 계산할 수 있었고 [0, 1, 0, 0, 4, 1, 0, 1, 0, 1, 4, 1, 8, 10, 0, 9]약 60 초가 걸렸습니다.

설명

기본적으로이 기능은 먼저 목록을 작성한다 무엇을, y모두 함께 j mod i어디 j범위의 모든 정수 0=>7(7 포함하여)와 i범위의 모든 정수입니다 0=>100. 그런 다음 프로그램은 무한 while루프 로 들어가서 () 의 첫 번째에서 두 번째- 마지막 하위 목록 에있는 각 하위 목록의 동일한 수의 내용 을 list 의 마지막 하위 목록 y( y[:-1:])에있는 동일한 수의 항목 y[-1]과 비교합니다 y. 하위 목록 y[-1]다른 하위 목록 과 다른 경우 루프가 중단되고 올바른 최소 나머지 시퀀스가 ​​반환됩니다.

예를 들어 입력이 3이면 y다음과 같습니다.

[[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], [0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], [1, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3]]

그런 다음 while 루프에 들어가면 list의 각 서브리스트를 sublist y[:-1:]의 동일한 수의 항목과 비교합니다 y[-1]. 예를 들어 먼저 [[0],[1],[0]]와를 비교 [1]합니다. 마지막 하위 목록이의 나머지 부분에 있기 때문에 y, 그것은 계속하고 비교하는 것 [[0,0],[0,1],[0,2]]하고 [1,0]. [1,0]이제는 y 특정 순서 의 나머지 부분에 있지 않기 때문에 최소 미리 알림 순서이므로 [1,0]올바르게 반환됩니다.


바이트를 절약하는 y[:c:]것은 다음과 같습니다y[:c]
Sherlock9

0

C89, 105 바이트

g(a,b){return b?g(b,a%b):a;}main(n,m,M){scanf("%d",&n);for(m=M=1;(M=++m*M/g(m,M))<=n;)printf("%d ",n%m);}

를 사용하여 (경고와 함께) 컴파일하십시오 gcc -std=c89. stdin에서 단일 숫자를 가져 와서 stdout에서 공백으로 구분 된 나머지 시퀀스를 출력합니다.


1
n = 0 일 때 아무 것도 인쇄하지 않습니다
xsot

0

C, 89 바이트

a,i=2;main(l,n){for(n=atoi(gets(n))?:!puts(n);n/l;printf("%d ",n%i++))for(a=l;l%i;l+=a);}

gcc로 컴파일하십시오. 온라인으로 시도하십시오 : n = 59 , n = 0 .

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