유리수의 비트 별 XOR


19

소개

0과 1 사이의 모든 합리적인 숫자는 결국주기적인 비트 시퀀스로 표현 될 수 있습니다. 예를 들어 11/40의 이진 표현은

0.010 0011 0011 0011 ...

여기서 0011부분 무한 반복된다. 이 표현을 찾는 한 가지 방법은 다음과 같습니다. 시작 R = 40분의 11 , 다음 반복의 값 때 1 위가 될 때 기록을 두 배로 소수 부분을 R의 반복, 당신은 당신이 루프를 입력 알고있다.

1. r = 11/40
2. 2*r = 11/20 < 1   ->  next bit is 0, r = 11/20
3. 2*r = 11/10 >= 1  ->  next bit is 1, r = 2*r - 1 = 1/10
4. 2*r = 1/5 < 1     ->  next bit is 0, r = 1/5
5. 2*r = 2/5 < 1     ->  next bit is 0, r = 2/5
6. 2*r = 4/5 < 1     ->  next bit is 0, r = 4/5
7. 2*r = 8/5 >= 1    ->  next bit is 1, r = 2*r - 1 = 3/5
8. 2*r = 6/5 >= 1    ->  next bit is 1, r = 2*r - 1 = 1/5, same as in 4.
   The loop 5. -> 6. -> 7. -> 8. now repeats.

이진 문자열에서 11/40으로 돌아가려면 수식을 사용할 수 있습니다

(int(prefix) + int(suffix)/(2^len(suffix) - 1)) / 2^len(prefix)

여기서 prefix초기 부분은 010, suffix반복 부분 0011int정수 이진 스트링을 변환한다.

그러한 두 가지 표현이 주어지면 비트 XOR 연산을 수행 할 수 있습니다. 결과 시퀀스도 주기적이므로 합리적인 숫자를 나타냅니다.

일부 합리적인 숫자의 경우 두 가지 이진 표현이 있습니다.

1/4 = 0.010000000...
    = 0.001111111...

이들 사이의 선택은 비트 XOR의 결과에 영향을 줄 수 있습니다. 이 경우 무한히 많은 0을 가진 이전 표현을 사용합니다.

작업

입력 값은 반 개방 간격 [0,1)에서 두 개의 유리수입니다. 출력은 입력에 적용된 비트 XOR 연산의 결과이며 합리적인 숫자로 표시됩니다. 입력이 모두 없더라도 출력은 1이 될 수 있습니다.

입력 및 출력의 정확한 형식은 유연하지만 각 합리적인 숫자는 분자와 분모의 두 정수로 표시되어야합니다 (0과 1은 제외 0하고 1원하는 경우 표시 할 수 있음 ). 입력이 가장 낮은 용어로 표현되었다고 가정 할 수 있습니다. 출력 가장 낮은 용어로 표현 되어야합니다 . 내장 된 유리수 유형은 이러한 제한을 만족하는 한 허용되는 형식입니다. 언어에 의해 부과 된 정수의 경계는 무시할 수 있지만 이론적으로 모든 합리적인 숫자에 대해 알고리즘이 작동해야합니다.

가장 낮은 바이트 수가 이깁니다. 표준 규칙이 적용됩니다.

입력 11/40 및 3/7을 고려하십시오. 파이프로 반복되는 부분을 구분하여 표현을 다른 것 위에 씁니다 |. 그런 다음 동일한 길이의 반복 부분을 추출하고 비트 XOR을 그 부분과 그 앞 부분에 적용합니다.

11/40 = 0. 0 1 0|0 0 1 1|0 0 1 1|0 0 1 1|0 0 1 1|0 0 1 1|0 0 1 1|0 0 1 ...
3/7   = 0.|0 1 1|0 1 1|0 1 1|0 1 1|0 1 1|0 1 1|0 1 1|0 1 1|0 1 1|0 1 1|...
     -> 0. 0 0 1|0 1 0 1 1 1 1 0 1 0 0 0|0 1 0 1 1 1 1 0 1 0 0 0|0 1 0 ...

결과 합리적인 숫자는 89/520입니다.

테스트 사례

0 0 -> 0
1/2 1/2 -> 0
1/2 1/4 -> 3/4
1/3 2/3 -> 1
1/2 3/4 -> 1/4
5/8 1/3 -> 23/24
1/3 1/5 -> 2/5
15/16 3/19 -> 257/304
15/16 257/304 -> 3/19
3/7 11/40 -> 89/520
5/32 17/24 -> 59/96
16/29 16/39 -> 621001733121535520/696556744961512799

지원해야하는 최대 기간은 얼마입니까?

@Neil 그러한 최대 값이 존재한다고 생각하는 이유는 무엇입니까?
orlp

3
참고 : 일부 숫자는 2 개의 이진 확장, 즉 최종 기간의 길이가 1 인 숫자입니다. 위의 문제 정의에서 우리는000...이 경우에끝나는 표현을 선택해야한다는 것을 암시합니다(또한 알고리즘을와 함께 사용하면 얻을 수 있음r). 예를 들어에대한 확장을선택했기 때문에5/8, 1/3얻을 수23/24있습니다. 대신을선택하면XOR 이후의 결과가되므로 잘못되었습니다. 관련 위키 백과 : 0.999 ...0.101000...5/80.10011111...5/819/24
Jeppe의 Stig 닐슨

3
@JeppeStigNielsen 젠장 ... 이것은 일반적인 XOR과 달리 (a ^ b) ^ b == a보유하지 않는다는 것을 의미합니다 . 예 (19/24 ^ 1/3) ^ 1/3 != 19/24. 그로 인해 나는 이것에 대해 약간의 흥분을 잃었습니다. (
orlp

답변:


3

Python 3, 193 164 바이트

def x(a,b,z=0):
 l=[]
 while(a,b)not in l:l+=[(a,b)];z=2*z|(a<.5)^(b<.5);a=a*2%1;b=b*2%1
 p=l.index((a,b));P=len(l)-p
 return((z>>P)+z%2**P*a**0/~-2**(P or 1))/2**p

입력을 Python 3의 fractions.Fraction유형으로 가져 와서 출력합니다.

재미있는 사실 (생성 함수를 사용하여 쉽게 표시 할 수 있음), 위로 변경 (a<.5)^(b<.5)하면 ((a>=.5)and(b>=.5))2 개의 합리적인 숫자 사이에 이진 AND가 표시됩니다. 이것을 호출하십시오 nd(a, b). 그럼 우리는 a + b - 2*nd(a, b) = x(a, b)!


사실, 내 실수. 사과! (답변에 포함 된 티오에 대한 링크는 훌륭 할 것입니다)
Mr. Xcoder

1

자바 스크립트, 141 바이트

(p,q,r,s)=>(h=(v,u)=>v%u?h(u,v%u):[a/u,b/u])(b=(g=x=>x%q||x%s?g((x|x/2)+x%2):x)(1),a=(o=b/(b-(b&~-b)),x=p*b/q,y=r*b/s,(x%o^y%o)+(x/o^y/o)*o))

마지막 테스트 사례에서는 작동하지 않습니다 (정수 오버플로). 에 대해 4 개의 숫자를 입력 p/q xor r/s하고 두 개의 숫자로 구성된 배열을 출력합니다. 테스트 케이스의 0, 0경우 입력해야합니다 0, 1, 0, 1.

어떻게:

(여기에 설명 된 모든 숫자는 이진 형식입니다.)

  1. 가장 작은 번호를 찾을 수 b, b = 10 ^ p - 10 ^ q (p, q are integers, p > q); and b = 0 (mod q); and b = 0 (mod s);
  2. 하자 x = p * b / q, y = r * b / q; 변환 p / q, r / sx / by / b;
  3. 하자 o = 10 ^ (p - q) - 1; 분할 x, y[x % o, x / o], [y % o, y / o]; 각 부분에 대해 xor를 가져 [x % o xor y % o, x / o xor y / o]오고 다시 연결하십시오 (x % o xor y % o) + (x / o xor y / o) * o. 로 기부하십시오 a;
  4. 이면 a = 0답은 0(또는 0 / 1)입니다. 그렇지 않으면 u = gcd(a, b); 대답은 (a/u)하고 (b/u).

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