Sharkovskii의 이상한 순서 4 배, 8 배 등

소개

이 과제에서 우리는 양의 정수의 특정 순서를 다룰 것입니다. 순서는 다음과 같습니다.

   3,    5,    7,    9,    11, ...
 2*3,  2*5,  2*7,  2*9,  2*11, ...
 4*3,  4*5,  4*7,  4*9,  4*11, ...
 8*3,  8*5,  8*7,  8*9,  8*11, ...
16*3, 16*5, 16*7, 16*9, 16*11, ...
 ...
... 64, 32, 16, 8, 4, 2, 1

먼저 1보다 큰 모든 홀수를 오름차순으로 나열합니다. 모든 경우 : 다음 우리는 1보다 큰 정수 홀수 개의 시간 후, 4 배, 8 배 등 나열 K 우리 나열 2 유전율 승순 1 배 이상 홀수 정수를 더. 마지막으로, 우리는 2의 거듭 제곱을 내림차순으로 나열하고 1로 끝납니다. 모든 양의 정수는이 “목록”에서 정확히 한 번 발생합니다.

더 명확하게, 두 개의 양의 정수 A = n · 2 pB = m · 2 q를 고려하십시오 . 여기서 n, m ≥ 1 은 홀수이고 p, q ≥ 0 입니다. 그리고 A는 앞에 오는 B 다음 조건 중 하나가 보유하고있는 경우, 순서에 :

  • n> 1 , m> 1p <q
  • 1 <n <mp = q
  • n> m = 1
  • n = m = 1 이고 p> q

이 순서 는 동적 시스템의주기적인 점에 관한 Sharkovskii의 정리 로 알려진 놀라운 수학적 결과에 나타납니다 . 여기에 대해서는 자세히 설명하지 않겠습니다.

작업

이 과제의 임무는 위의 순서를 계산하는 것입니다. 입력 값은 양의 정수 AB 두 개 이며 같을 수 있습니다. 순서대로 AB 보다 앞에 오면 출력값이 참 값이고 , 그렇지 않으면 거짓 값입니다. A = B 인 경우 출력은 진실해야합니다. 일관된 한 AB 를 어느 순서 로나 취할 수 있습니다 .

정수 오버플로에 대해 걱정할 필요는 없지만 이론적으로 알고리즘은 임의로 큰 입력에 작동해야합니다.

테스트 사례

진실한 사례

3 11
9 6
48 112
49 112
158 158
36 24
14 28
144 32
32 32
32 8
3 1
1 1

거짓 인스턴스

1 2
1 5
11 5
20 25
2 8
256 255
256 257
72 52
2176 1216
2176 2496


답변

파이썬 2, 87 71 바이트

k=lambda n:[n&~-n<1,(n&-n)*cmp(n&~-n,1),n/(n&-n)]
lambda a,b:k(a)<=k(b)

이것은 아마도 어떤 규모의 상도 얻지 못할 것이지만,이 답변은 사전 식으로 정렬 될 때 올바른 순서를 초래하는 정수에서 3 개의 표현식을 사용하여 3 개의 튜플을 구성하여 작동합니다.

읽을 수있는 용어로 튜플은 A = n · 2 p입니다 .

[n == 0, p * (1 - 2*(n == 0)), n]

답변

자바 스크립트 (ES6), 53 49 바이트

f=(a,b)=>b<2||a>1&&(a&b&1?a<=b:a&1|~b&f(a/2,b/2))

설명:

  • b가 1이면 a는 b보다 앞에 오거나 같습니다
  • 그렇지 않으면 a가 1이면 a가 b보다 우선하지 않습니다.
  • 그렇지 않으면 a와 b가 모두 홀수이면 정기적 인 부등식 검사를 사용하십시오.
  • 그렇지 않으면 a가 홀수이면 b보다 앞에옵니다
  • 그렇지 않으면 b가 홀수이면 a가 b보다 우선하지 않습니다.
  • 그렇지 않으면 a와 b를 2로 나누고 다시 시도하십시오.

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


답변

파이썬 2, 50 바이트

lambda*l:cmp(*[([-n][n&n-1:],n&-n,n)for n in l])<1

각 숫자는 정렬 순서가 원하는 순서 인 트리플에 매핑됩니다.

  • 기본 값은이며 [-n][n&n-1:], 마지막에 2의 거듭 제곱을 처리합니다. 의 거듭 제곱 일 n&n-1때 비트 단위 “and” 는 정확히 0 n입니다 2. 그렇다면 목록을 얻 [-n]거나 그렇지 않으면 빈 목록을 얻습니다 []. 이렇게하면 주문이 끝날 때 2의 모든 거듭 제곱이 내림차순으로 정렬됩니다.
  • 2 차 값은 2 n&-n의 거듭 제곱을 추출합니다 n.
  • 최종 값 n순위는 더 큰 수를 위해 2의 거듭 제곱입니다.

해당 튜플은 전달되어 cmp비교인지 확인 <=0합니다. 파이썬 3은 (n&n-1<1)/n트리플의 첫 번째 값에 대해 float 나누기 를 사용하여 바이트를 저장 하지만 부족 cmp합니다.


답변

자바 스크립트 (ES6), 70 64 바이트

아마도 더 많은 골프를 쳤을 수도 있지만 첫 번째 시도는 다음과 같습니다.

x=>y=>(a=x&-x,x/=a,b=y&-y,y/=b,y<2?x>1|b<=a:x>1&(b>a|b==a&y>=x))

카레 구문으로 입력을 (x)(y)받습니다. 0/를 반환 1합니다.

테스트 사례

let f =

x=>y=>(a=x&-x,x/=a,b=y&-y,y/=b,y<2?x>1|b<=a:x>1&(b>a|b==a&y>=x))

console.log('Testing truthy instances ...');
console.log(f(3)(11));
console.log(f(9)(6));
console.log(f(48)(112));
console.log(f(49)(112));
console.log(f(158)(158));
console.log(f(36)(24));
console.log(f(14)(28));
console.log(f(144)(32));
console.log(f(32)(32));
console.log(f(32)(8));
console.log(f(3)(1));
console.log(f(1)(1));

console.log('Testing falsy instances ...');
console.log(f(1)(2));
console.log(f(1)(5));
console.log(f(11)(5));
console.log(f(20)(25));
console.log(f(2)(8));
console.log(f(256)(255));
console.log(f(256)(257));
console.log(f(72)(52));
console.log(f(2176)(1216));
console.log(f(2176)(2496));

답변

펄 6 , 89 84 바이트

->\a,\b{my \u=*>max a,b;a==first a|b,flat [1,2,4...u].&{(3*$_,5*$_...u for $_),.reverse}}

{my \u=*>@_.max;@_[0]==first @_.any,flat [1,2,4...u].&{.map(*X*(3,5...u)),.reverse}}

( 온라인으로 시도하십시오. )

정확히 짧지는 않지만 실제로 순서 순서를 생성하는 솔루션 (각 하위 시퀀스의 안전한 상한까지)을 작성하고 어떤 입력이 먼저 나타나는지 확인하는 것이 흥미로울 것이라고 생각했습니다.

예를 들면 다음과 같습니다.

  • 입력 2, 3을 위해 다음 을 생성합니다.

    3 5
    6
    12
    4 2 1

    … 그리고 3이전 에 나타나는 것을 관찰하십시오 2.

  • 입력 9, 6을 위해 다음 을 생성합니다.

    3 5 7 9 11
    6 10
    12
    24
    48
    16 8 4 2 1

    … 그리고 9이전 에 나타나는 것을 관찰하십시오 6.

더 똑똑하고 시퀀스를 훨씬 적게 생성 할 수 있지만 더 많은 바이트가 필요합니다.


답변

파이썬 2, 54 바이트

f=lambda a,b:b<2or[f(a/2,b/2),a>1,0,1<a<=b][a%2+b%2*2]

Neil과 유사한 재귀 솔루션.


답변

Mathematica, 65 바이트

OrderedQ[{1,#}&/@#//.{a_,b_/;EvenQ@b}->{2a,b/2}/.{a_,1}->{∞,-a}]&

이름이없는 함수는 양의 정수 목록을 가져 와서 목록이 TrueSharkovskii 순서로 오름차순을 형성하는 경우 리턴 합니다 False. (특히 입력 목록에는 두 가지 요소 만있을 필요는 없습니다. 추가 기능은 무료로 제공됩니다.)

알고리즘의 핵심은 함수입니다.이 함수 {1,#}&/@#//.{a_,b_/;EvenQ@b}->{2a,b/2}는 2의 인수를 반복적으로 이동 m*2^k하여 m홀수 형식의 정수를 정렬 된 쌍 으로 변환합니다 {2^k,m}(입력 목록의 모든 요소에 적용). OrderedQ정렬 된 쌍의 결과 목록이 이미 정렬되어 있는지 여부를 결정합니다. 기본적으로 이는 첫 번째 요소에 따라 순서가 증가한 다음 두 번째 요소에 의해 순서가 증가 함을 의미합니다.

2의 거듭 제곱은 다른 규칙을 따르는 것을 제외하고는 정확히 우리가 원하는 것입니다. 그래서과에 확인하기 전에 OrderingQ, 우리는 마지막 규칙 적용 /.{a_,1}->{∞,-a}, 변환 (예를 들어) {64,1}로를 {∞,-64}; 주문의 올바른 자리에 2의 거듭 제곱을 넣습니다.