introduzione
Ogni numero razionale compreso tra 0 e 1 può essere rappresentato come una sequenza di bit eventualmente periodica. Ad esempio, la rappresentazione binaria di 11/40 è
0.010 0011 0011 0011 ...
dove la 0011parte si ripete indefinitamente. Un modo per trovare questa rappresentazione è il seguente. Inizia con r = 11/40 , quindi raddoppia ripetutamente e prendi la parte frazionaria, registrando quando supera 1. Quando il valore di r si ripete, sai di essere entrato in un ciclo.
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.
Per tornare dalla stringa binaria a 11/40, è possibile utilizzare la formula
(int(prefix) + int(suffix)/(2^len(suffix) - 1)) / 2^len(prefix)
dove prefixè la parte iniziale 010, suffixè la parte ripetuta 0011e intconverte una stringa binaria in numero intero.
Date due di queste rappresentazioni, possiamo eseguire l'operazione XOR bit a bit su di esse. Anche la sequenza risultante sarà periodica, quindi rappresenta un numero razionale.
Per alcuni numeri razionali, ci sono due rappresentazioni binarie.
1/4 = 0.010000000...
= 0.001111111...
La scelta tra loro può influenzare il risultato dell'XOR bit a bit. In questi casi, usiamo la rappresentazione precedente, che ha infinitamente molti 0.
L'obiettivo
I tuoi input sono due numeri razionali nell'intervallo semi-aperto [0,1). L'output deve essere il risultato dell'operazione XOR bit a bit applicata agli input, espressa come un numero razionale. Si noti che l'uscita può essere 1, anche se nessuno degli ingressi lo è.
I formati esatti di input e output sono flessibili, ma ogni numero razionale dovrebbe essere rappresentato da due numeri interi, il numeratore e il denominatore (ad eccezione di 0 e 1, che possono essere rappresentati come 0e 1se desiderato). Si può presumere che gli input siano espressi in termini più bassi. L'output deve essere espresso nei termini più bassi. Un tipo di numero razionale incorporato è un formato accettabile, purché soddisfi queste restrizioni. Puoi ignorare qualsiasi limite sugli interi imposti dal tuo linguaggio, ma il tuo algoritmo dovrebbe teoricamente funzionare per tutti i numeri razionali.
Vince il conteggio dei byte più basso. Si applicano le regole standard del code-golf .
Esempio
Considera gli ingressi 11/40 e 3/7. Scriviamo le loro rappresentazioni una sopra l'altra, delimitando le parti ripetute con le pipe |. Quindi estraiamo parti ripetute di uguale lunghezza e applichiamo XOR bit a bit a esse e alle parti prima di esse.
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 ...
Il numero razionale risultante è 89/520.
Casi test
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...in questi casi (che è anche ciò che otteniamo se usiamo l'algoritmo conr). Ad esempio, nel caso5/8, 1/3otteniamo23/24perché scegliamo l'espansione0.101000...per5/8. Se scegliamo invece0.10011111...come5/8, il risultato dopo XOR diventa19/24, quindi questo è sbagliato. Correlato a Wikipedia: 0.999 ...
(a ^ b) ^ b == anon regge. Es (19/24 ^ 1/3) ^ 1/3 != 19/24. Questo mi ha fatto perdere un po 'di eccitazione per questo :(