Bitwise XOR của các số hữu tỷ


19

Giới thiệu

Mỗi số hữu tỷ từ 0 đến 1 có thể được biểu diễn dưới dạng một chuỗi bit định kỳ cuối cùng. Ví dụ: biểu diễn nhị phân của 11/40 là

0.010 0011 0011 0011 ...

trong đó 0011phần lặp lại vô thời hạn. Một cách để tìm đại diện này là sau đây. Bắt đầu với r = 11/40 , sau đó lặp lại gấp đôi và lấy phần phân số, ghi lại khi nó vượt lên trên 1. Khi giá trị của r lặp lại, bạn biết bạn đã nhập một vòng lặp.

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.

Để lấy từ chuỗi nhị phân trở về 11/40, bạn có thể sử dụng công thức

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

trong đó prefixlà phần ban đầu 010, suffixlà phần lặp lại 0011intchuyển đổi một chuỗi nhị phân thành số nguyên.

Đưa ra hai biểu diễn như vậy, chúng ta có thể thực hiện thao tác XOR bitwise trên chúng. Trình tự kết quả cũng sẽ là định kỳ, vì vậy nó đại diện cho một số hữu tỷ.

Đối với một số số hữu tỷ, có hai biểu diễn nhị phân.

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

Sự lựa chọn giữa chúng có thể ảnh hưởng đến kết quả của XOR bitwise. Trong những trường hợp này, chúng tôi sử dụng đại diện trước đây, có vô số 0.

Nhiệm vụ

Đầu vào của bạn là hai số hữu tỷ trong khoảng thời gian nửa mở [0,1). Đầu ra của bạn sẽ là kết quả của hoạt động XOR bitwise được áp dụng cho các đầu vào, được biểu thị dưới dạng số hữu tỷ. Lưu ý rằng đầu ra có thể là 1, mặc dù cả hai đầu vào đều không.

Các định dạng chính xác của đầu vào và đầu ra là linh hoạt, nhưng mỗi số hữu tỷ phải được biểu thị bằng hai số nguyên, tử số và mẫu số (ngoại trừ 0 và 1, có thể được biểu diễn theo 01nếu muốn). Bạn có thể giả định rằng các đầu vào được thể hiện bằng các thuật ngữ thấp nhất. Đầu ra phải được thể hiện bằng các thuật ngữ thấp nhất. Một loại số hợp lý tích hợp là một định dạng có thể chấp nhận, miễn là nó thỏa mãn những hạn chế này. Bạn có thể bỏ qua mọi giới hạn về số nguyên do ngôn ngữ của bạn áp đặt, nhưng về mặt lý thuyết, thuật toán của bạn sẽ hoạt động với tất cả các số hữu tỷ.

Số byte thấp nhất sẽ thắng. tiêu chuẩnLuật áp dụng.

Thí dụ

Hãy xem xét các đầu vào 11/40 và 3/7. Chúng tôi viết các đại diện của họ chồng lên nhau, phân định các phần lặp lại bằng đường ống |. Sau đó, chúng tôi trích xuất các phần lặp lại có độ dài bằng nhau và áp dụng XOR bitwise cho chúng và các phần trước chúng.

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 ...

Số hữu tỷ kết quả là 89/520.

Các trường hợp thử nghiệm

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

Khoảng thời gian tối đa chúng ta cần hỗ trợ là bao nhiêu?
Neil

@Neil Điều gì khiến bạn nghĩ rằng tồn tại tối đa như vậy?
orlp

3
Lưu ý: Một số số có hai lần mở rộng nhị phân, cụ thể là những số trong đó khoảng thời gian cuối cùng có độ dài một. Điều này tiềm ẩn trong định nghĩa vấn đề ở trên rằng chúng ta phải chọn biểu diễn kết thúc trong000...trường hợp này (cũng là những gì chúng ta nhận được nếu sử dụng thuật toán vớir). Ví dụ: trong trường hợp5/8, 1/3chúng tôi nhận được23/24vì chúng tôi chọn mở rộng0.101000...cho5/8. Nếu chúng ta chọn thay vì0.10011111...như5/8, kết quả sau khi XOR trở thành19/24, vì vậy đây là sai. Liên quan đến Wikipedia: 0.999 ...
Jeppe Stig Nielsen

3
@JeppeStigNielsen Chết tiệt ... Điều này có nghĩa là không giống như XOR thông thường (a ^ b) ^ b == akhông giữ. Ví dụ (19/24 ^ 1/3) ^ 1/3 != 19/24. Điều đó khiến tôi mất khá nhiều hứng thú về điều này :(
orlp

Câu trả lời:


3

Python 3, 193 164 byte

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

Lấy đầu vào là fractions.Fractionkiểu của Python 3 và cũng xuất ra nó.

Fun thực tế (bạn có thể dễ dàng hiển thị này sử dụng các hàm tạo), nếu bạn thay đổi (a<.5)^(b<.5)để ((a>=.5)and(b>=.5))trên bạn sẽ có được nhị phân VÀ giữa hai số hữu tỉ. Gọi này nd(a, b). Vậy thì chúng ta có a + b - 2*nd(a, b) = x(a, b)!


Thật vậy, sai lầm của tôi. Xin lỗi! (lưu ý rằng một liên kết đến tio có trong câu trả lời sẽ rất tuyệt)
Ông Xcoder

1

JavaScript, 141 byte

(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))

Không làm việc cho trường hợp thử nghiệm cuối cùng (tràn số nguyên). Nhập 4 số cho p/q xor r/s, xuất một mảng có hai số. Đối với testcase 0, 0, bạn nên nhập0, 1, 0, 1 .

Làm sao:

(Tất cả các số được mô tả ở đây là ở dạng nhị phân.)

  1. tìm số nhỏ nhất b, trong đó b = 10 ^ p - 10 ^ q (p, q are integers, p > q); and b = 0 (mod q); and b = 0 (mod s);
  2. Hãy x = p * b / q, y = r * b / q; Chuyển đổi p / q, r / ssang x / by / b;
  3. Hãy để o = 10 ^ (p - q) - 1; chia x, yđể [x % o, x / o], [y % o, y / o]; nhận xor cho mỗi phần [x % o xor y % o, x / o xor y / o], và tham gia trở lại (x % o xor y % o) + (x / o xor y / o) * o; Tặng nó như a;
  4. Nếu a = 0, câu trả lời là 0(hoặc 0 / 1); Nếu không hãy để u = gcd(a, b); Câu trả lời là (a/u)(b/u).

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.