Wprowadzenie
Każda liczba wymierna od 0 do 1 może być reprezentowana jako ewentualnie okresowa sekwencja bitów. Na przykład binarna reprezentacja 11/40 to
0.010 0011 0011 0011 ...
gdzie 0011
część powtarza się w nieskończoność. Jednym ze sposobów znalezienia tej reprezentacji jest: Zacznij od r = 11/40 , a następnie kilkakrotnie podwoj go i weź ułamek, rejestrując, gdy przekroczy on 1. Gdy wartość r się powtarza, wiesz, że wszedłeś w pętlę.
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.
Aby wrócić z ciągu binarnego z powrotem do 11/40, możesz użyć formuły
(int(prefix) + int(suffix)/(2^len(suffix) - 1)) / 2^len(prefix)
gdzie prefix
jest częścią początkową 010
, suffix
jest częścią powtarzającą się 0011
i int
konwertuje ciąg binarny na liczbę całkowitą.
Biorąc pod uwagę dwie takie reprezentacje, możemy wykonać na nich bitową operację XOR. Wynikowa sekwencja będzie również okresowa, więc reprezentuje liczbę wymierną.
Dla niektórych liczb wymiernych istnieją dwie reprezentacje binarne.
1/4 = 0.010000000...
= 0.001111111...
Wybór między nimi może wpływać na wynik bitowego XOR. W takich przypadkach używamy poprzedniej reprezentacji, która ma nieskończenie wiele zer.
Zadanie
Twoje dane wejściowe to dwie liczby wymierne w przedziale półotwartym [0,1). Twój wynik powinien być wynikiem bitowej operacji XOR zastosowanej do danych wejściowych, wyrażonej jako liczba wymierna. Zauważ, że wyjście może wynosić 1, mimo że żadne z wejść nie jest.
Dokładne formaty wejściowe i wyjściowe są elastyczne, a każda liczba wymierna powinna być reprezentowana przez dwie liczby całkowite, licznika i mianownika (z wyjątkiem wartości 0 i 1, który może być przedstawiony jak 0
i 1
w razie potrzeby). Możesz założyć, że dane wejściowe są wyrażone w najniższych kategoriach. Wynik musi być wyrażony w najniższych kategoriach. Wbudowany typ liczby wymiernej jest dopuszczalnym formatem, o ile spełnia te ograniczenia. Możesz zignorować wszelkie ograniczenia liczb całkowitych narzucone przez twój język, ale twój algorytm powinien teoretycznie działać dla wszystkich liczb wymiernych.
Wygrywa najniższa liczba bajtów. Obowiązują standardowe zasady gry w golfa .
Przykład
Rozważ wejścia 11/40 i 3/7. Piszemy ich reprezentacje jedna nad drugą, ograniczając powtarzające się części za pomocą potoków |
. Następnie wyodrębniamy powtarzające się części o równej długości i nakładamy bitową XOR na nich i na części przed nimi.
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 ...
Wynikowa liczba wymierna to 89/520.
Przypadki testowe
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
000...
w tych przypadkach (i to również uzyskujemy, jeśli użyjemy algorytmu zr
). Na przykład w przypadku,5/8, 1/3
gdy otrzymujemy,23/24
ponieważ wybieramy rozszerzenie0.101000...
dla5/8
. Jeśli zamiast tego wybierzemy0.10011111...
jako5/8
, wynik po XOR staje się19/24
, więc jest to źle. Związane z Wikipedią: 0.999 ...
(a ^ b) ^ b == a
nie działa. Np (19/24 ^ 1/3) ^ 1/3 != 19/24
. To sprawiło, że straciłem sporo podekscytowania z tego powodu :(