Rasyonel sayıların bitsel XOR'u


19

Giriş

0 ile 1 arasındaki her rasyonel sayı, sonunda periyodik bir bit dizisi olarak temsil edilebilir. Örneğin, 11/40 ikili gösterimi

0.010 0011 0011 0011 ...

nerede 0011parçası süresiz tekrarlar. Bu temsili bulmanın bir yolu şudur. İle başlayın r = 11/40 , daha sonra art arda değeri zaman 1'in üstünde gittiğinde kayıt bunu iki katına ve fraksiyonel katılmak r tekrarlar, size bir döngü girmiş biliyorum.

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.

İkili dizeden 11 / 40'a geri dönmek için formülü kullanabilirsiniz.

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

burada prefixilk parçası 010, suffixtekrar bir parçasıdır 0011ve inttamsayıya ikili bir dizi dönüştürür.

Bu tür iki gösterim verildiğinde, bunlar üzerinde bitsel XOR işlemini gerçekleştirebiliriz. Ortaya çıkan dizi de periyodik olacaktır, bu nedenle rasyonel bir sayıyı temsil eder.

Bazı rasyonel sayılar için iki ikili gösterim vardır.

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

Aralarındaki seçim, bitsel XOR'un sonucunu etkileyebilir. Bu durumlarda, sonsuz sayıda 0'a sahip olan eski temsili kullanıyoruz.

Görev

Girişleriniz yarı açık aralıkta iki rasyonel sayıdır [0,1). Çıktınız, rasyonel bir sayı olarak ifade edilen, girdilere uygulanan bitsel XOR işleminin sonucu olacaktır. Girişlerin hiçbiri olmasa da, çıkışın 1 olabileceğini unutmayın.

Girdi ve çıktının kesin formatları esnektir, ancak her bir rasyonel sayı, pay ve payda olmak üzere iki tamsayı ile temsil edilmelidir ( istenirse 0ve 1istendiği takdirde temsil edilebilen 0 ve 1 hariç ). Girdilerin en düşük terimlerle ifade edildiğini varsayabilirsiniz. Çıktı en düşük terimlerle ifade edilmelidir . Yerleşik bir rasyonel sayı türü, bu kısıtlamaları karşıladığı sürece kabul edilebilir bir biçimdir. Diliniz tarafından dayatılan tam sayılardaki sınırları göz ardı edebilirsiniz, ancak algoritmanız teorik olarak tüm rasyonel sayılar için çalışmalıdır.

En düşük bayt sayısı kazanır. Standart kuralları geçerlidir.

Misal

11/40 ve 3/7 girişlerini göz önünde bulundurun. Temsillerini üst üste yazıyoruz, tekrarlayan parçaları boru ile sınırlıyoruz |. Daha sonra eşit uzunlukta tekrar eden parçaları çıkarırız ve onlara ve onlardan önceki kısımlara bitsel XOR uygularız.

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

Elde edilen rasyonel sayı 89/520'dir.

Test senaryoları

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

Desteklememiz gereken maksimum süre nedir?
Neil

@Neil Böyle bir maksimumun var olduğunu düşündüren nedir?
orlp

3
Not: Bazı sayılar iki ikili genişlemeye sahiptir, yani nihai sürenin bir uzunluğa sahip olduğu sayılar. Yukarıdaki problem tanımında000..., bu durumlardasona eren temsili seçmemiz gerekir(algoritmayı birlikte kullanırsak elde ettiğimiz de budurr). Örneğin,5/8, 1/3alacağımızdurumda23/24genişlemeyi seçtiğimiz0.101000...için5/8. Bunun yerine seçerseniz0.10011111...olarak5/8, XOR hale geldikten sonra sonuç19/24, bu nedenle bu yanlış. İlgili Vikipedi: 0.999 ...
Jeppe Stig Nielsen

3
@JeppeStigNielsen Lanet olsun ... Bu, normal XOR'un aksine tutmadığı anlamına gelir (a ^ b) ^ b == a. Örn (19/24 ^ 1/3) ^ 1/3 != 19/24. Bu bana bu konuda biraz heyecan kaybettirdi :(
orlp

Yanıtlar:


3

Python 3, 193164 bayt

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'ün fractions.Fractiontürü olarak girdi alır ve çıktı verir.

Eğer değiştirirseniz eğlenceli yanı, (kolayca bu kullanarak üreten fonksiyonlarını gösterebiliriz) (a<.5)^(b<.5)için ((a>=.5)and(b>=.5))binaryde olsun yukarıdaki VE iki rasyonel sayı arasında. Bunu ara nd(a, b). O zaman var a + b - 2*nd(a, b) = x(a, b)!


Gerçekten, benim hatam. Özür! (cevaba eklenen tio bağlantısının harika olacağını unutmayın)
Bay Xcoder

1

JavaScript, 141 bayt

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

Son test durumu (tamsayı taşması) için çalışmaz. İçin 4 sayı girin p/q xor r/s, iki sayı içeren bir dizi çıkarın. Testcase için 0, 0giriş yapmalısınız 0, 1, 0, 1.

Nasıl:

(Burada açıklanan tüm sayılar ikili biçimdedir.)

  1. En küçük numarayı bulmak b, b = 10 ^ p - 10 ^ q (p, q are integers, p > q); and b = 0 (mod q); and b = 0 (mod s);
  2. Let x = p * b / q, y = r * b / q; Dönüştürme p / q, r / siçin x / bve y / b;
  3. Let o = 10 ^ (p - q) - 1; bölme x, yiçin [x % o, x / o], [y % o, y / o]; her bölüm için xor olsun [x % o xor y % o, x / o xor y / o]ve geri katılın (x % o xor y % o) + (x / o xor y / o) * o; Bağış yapın a;
  4. Eğer a = 0cevap 0(veya 0 / 1) ise; Aksi takdirde u = gcd(a, b); cevap (a/u)ve (b/u).

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.