Tüm rasyonel sayıların bir listesini çıkar


13

Tüm matematikte, her zaman sağduyunun ötesine geçen birkaç teorem olacaktır. Bunlardan biri, farklı boyutlarda sonsuzluğun olmasıdır. Bir başka ilginç gerçek, farklı büyüklükte görünen birçok sonsuzluğun aslında aynı boyutta olduğu fikri. Rasyonel sayılar kadar tamsayılar kadar eşit sayılar vardır.

Bu sorunun genel konsepti, sonsuzluğun tuhaf gerçekliğiyle yüzleşmektir. Bu zorlukta, programınız aşağıdakileri içeren bir liste çıkarır:

  • Herhangi bir zamanda, her zaman tam sayıda giriş yapın
  • Sonunda (yeterince uzun süre çalıştırılmak üzere bırakılırsa) herhangi bir (sıfır olmayan) rasyonel sayıyı tam olarak tüm listede bir kez içerir
  • Sınırsız sayıda boş yuva içeriyor (listedeki gereksiz yere 0'a ayarlanmış girişler)
  • % 100 sınırına yaklaşan boş yuva oranına sahip olmak
  • Her pozitif tamsayı N için, ardışık N boş yuvaya sahip sonsuz sayıda yere sahip olun

Meydan okuma

Zorluğunuz, aşağıdaki kurallarla özel bir liste çıkaracak olan mümkün olan en kısa programı yazmaktır:

  1. Bir kare numarası olmayan bir dizine sahip tüm girdiler sıfır olarak ayarlanmalıdır. Böylece, ilk giriş sıfırdan, ikinci ve üçüncü sıfırdan, dördüncü sıfırdan vb. Olacaktır.
  2. Tüm rasyonel sayılar, basitleştirilmiş yanlış bir kesir (4/5 veya 144/13 gibi) şeklinde olacaktır. İstisna, sadece sıfır olacaktır 0.
  3. Programınız yeterince uzun ve yeterli belleğe sahipse, tüm (pozitif ve negatif) rasyonel sayılar sonunda listede görünmelidir. Herhangi bir özel rasyonel sayı için, gereken süre keyfi olarak büyük, fakat her zaman sınırlı olan bir süre olabilir.
  4. Sonsuz bir süre için çalıştırılırsa, sıfır olmayan rasyonel sayı hiçbir zaman iki kez görünmemelidir.

Kural 3, sınırsız sayıda farklı olası yasal çıktı olduğu için bazı değişikliklere izin vermektedir.

Çıktı bir çizgi akışı olacaktır. Her satır 5: 2/3, ilk sayının giriş numarası olduğu genel formda olacak , ardından rasyonel sayı olacaktır. 1: 0Bunun her zaman ilk çıktı satırı olacağını unutmayın .

Çıktı snippet'i örneği:

1: 1/1
2: 0
3: 0
4: 2/1
5: 0
6: 0
7: 0
8: 0
9: -2/1
10: 0
etc...

Kurallar, Düzenlemeler ve Notlar

Bu kod golf. Standart kod golf kuralları geçerlidir. Ayrıca, çıktıda izin verilen varyasyon nedeniyle, en azından listenizin olası tüm rasyonel sayıları tam olarak bir kez içereceğine ve çözümünüzün doğru olduğuna neden inandığınızı göstermeniz gerekir.

DÜZENLEME: Asal sayılar meydan okumadan uzaklaştığından, kare sayılara değiştiriyorum. Bu aynı amaca ulaşır ve çözümleri kısaltır.


1
Kural 1'in amacı nedir? İnsanların ilkelliği test etmek ve gerekçeleri sıralamak için karşılıklı olarak iki ayrı program golf oynamasını mı istiyorsunuz?
Peter Taylor

Tamsayıların çok küçük bir bölümünün hala tüm rasyonel sayılar kümesiyle aynı kardinaliteye sahip olduğunu gösterir ve aynı zamanda boş yuvaların yüzdesinin% 100'e yaklaşmasına (ancak asla ulaşmamasına) izin verir.
PhiNotPi

Programın ayrıca sabit bir bellekte çalışması gerektiğini varsayıyorum, yani makinenin her zaman daha fazla tahsis edebileceğini varsayamaz mıyım? Ayrıca, sınırlı bir aralığı olduğunu bildiğinizde, liste endeksi için bir C int kullanmak kurallara aykırı mıdır? (Kesin sınır uygulamaya göre değişse de.) Bir çeşit bignum gerekli mi?
breadbox

1
@PhiNotPi, bunu yapmanın çok daha basit yolları var ve bu sorunun daha ilginç kısmından dikkat dağıtıyor.
Peter Taylor

1
1: 0Bunun her zaman ilk çıktı satırı olacağını unutmayın . - Bu, örneğinizle çelişiyor ve benim için de bir anlam ifade etmiyor.
Wrzlprmft

Yanıtlar:


6

Haskell, 184 karakter

main=putStr.unlines$zip[1..](s>>=g)>>=h
s=(1,1):(s>>=f)
f(a,b)=[(a,a+b),(a+b,b)]
g x@(a,b)=[x,(-a,b)]
h(i,(a,b))=(i^2)%(u a++'/':u b):map(%"0")[i^2+1..i*(i+2)]
i%s=u i++": "++s
u=show

Bu, Calkin-Wilf Ağacı'nın ilk genişlik geçişini yapar ve tüm pozitif rasyonel sayıları tam olarak bir kez azaltılmış biçimde verir. Daha sonra sıfır olmayan rasyonel sayıları ve kare girişler arasında sıfırlı pedleri kapsayacak şekilde pozitif ve negatif arasında değişir.

Çıktı (kısalık için sıfır satırlar hariç):

1: 1/1
4: -1/1
9: 1/2
16: -1/2
25: 2/1
36: -2/1
49: 1/3
64: -1/3
81: 3/2
100: -3/2
...

5

Adaçayı, 103 113 128

Adaçayı rasyonelleri kolaylıkla listeleyebilir! Program gereksinimlerine uyacak şekilde biçimlendirme, her zaman olduğu gibi her şeyi mahveder.

for i,q in enumerate(QQ):
 for j in[(i-1)^2+1..i*i]:print'%d:'%j,[0,'%d/%d'%(q.numer(),q.denom())][j==i*i]

Adaçayı boylarınaQQ göre numaralandırır : GCD azalmasından sonra pay ve payda maksimum mutlak değeri.


Skoru 124'e düşürerek, aşağıdaki gibi sadece bir kez ortadan kaldırabilir x.next()ve kullanabilirsiniz . Bu bir yorumda düzgün görüntülenmiyor, ancak ne demek istediğimi görebildiğini düşünüyorum. printx=enumerate(QQ) for i,q in x: for j in[(i-1)^2+1..i*i]: print'%d: '%j,'%d/%d'%(q.numer(),q.denom())if j.is_square()else 0
res

BTW, ilk 4 olumlu unsurdan sonra Sage'nin numaralandırmasının diğer cevaplardakiyle aynı olmadığını fark ettim. Calkin-Wilf formülleri, bir rasyonel paydasının bir sonraki rasyonelin payı olduğu bir dizi verir; örneğin (..., 1/3, 3/2, 2/3, ...), Sage'lerle karşılaştırıldığında (..., 1/3, 3/1, 2/3, ...). Nasıl hesaplandığını görmek için Sage'nin numaralandırması için herhangi bir belge bulamıyorum.
res

@ res, teşekkürler! Basılı ifadeleri birleştirmek istedim ama [x..y] gösterimini kullanmayı unuttum. Burada başka bir Sage kullanıcısı görmek harika!
boothby

4

Python, 162

f=lambda n:f(n/2)if n%2 else f(n/2)+f(n/2-1)if n else 1
n=i=1
while 1:
 print'%d:'%i,
 if i-n*n:s=0
 else: n+=1;s='%d/%d'%((-1)**n*f(n/2-1),f(n/2))
 print s
 i+=1

Bu Calkin & Wilf tarafından Rationals Recounting içinde verilen özyineleme kullanır .


2

Haskell, 55 bayt

mapM_ print$join$iterate(>>=(\x->[x+1,1/(1+1/x)]))[1%1]

çıktılar

1 % 1
2 % 1
1 % 2
3 % 1
2 % 3
3 % 2
1 % 3
4 % 1
...

% 1 1, Calkin-Wilf ağacının köküdür; yineleme her düğümün her iki alt öğesini de ekler; birleştirme seviyeleri tek bir listede daraltır.

Uygun ithalat, 0 ve negatifleri eklerseniz 120 karakter:

import Data.Ratio
import Control.Monad
main=mapM_ print$0:(join(iterate(>>=(\x->[x+1,1/(1+1/x)]))[1%1])>>=(\x->[-x,x]))

çıktılar

0 % 1
(-1) % 1
1 % 1
(-2) % 1
2 % 1
(-1) % 2
1 % 2
(-3) % 1
3 % 1
(-2) % 3
2 % 3
(-3) % 2
3 % 2
(-1) % 3
1 % 3
(-4) % 1
4 % 1
...

boş yuva çıktı? bu kötü bir tadı var :( beni "tüm olumlu rasyonların listesi" nde yakaladın


mapM_ print$fix((1%1:).(>>= \x->[x+1,1/(x+1)]))47 karakterdir. dan haskellwiki . herhangi bir ithalat olmadan, haskell.org 'un "denemek" REPL (iyi, mapM_ printparçası olmadan ...) olduğu gibi çalışır
Will Ness

1

PHP 105 bayt

Not: Düzgün çalışması için bu kod iso-8859-1 (ansi) olarak kaydedilmelidir. Tüm girdileri varsayılan olarak utf8'e (ideone gibi) kodlayan çevrimiçi tercümanlar yanlış çıktı üretir.

<?for($f=µ;$i++<$j*$j||++$j%2||(--$$f?$$f--:$f^=C);)echo"$i: ",$i==$j*$j?$j%2?$x=++$ö.~Ð.++$µ:"-$x":0,~õ;

Georg Cantor'un numaralandırmasını kullanarak (+/- değerleri için biraz değiştirildi).

Yukarıdaki kodu çalıştırmak için sorun yaşıyorsanız (büyük olasılıkla aşırı miktarda BİLDİRİM mesajı nedeniyle), bunun yerine bunu kullanın (107 bayt):

<?for($f=µ;$i++<$j*$j||++$j%2||(--$$f?$$f--:$f^=C);)echo"$i: ",$i==$j*$j?$j%2?$x=++$ö.'/'.++$µ:"-$x":0,'
';

1
Bu kod ile çalışma zamanı hataları alıyorum (bazı garip karakterler içeriyor gibi görünüyor; örneğin, "$ ö. ~ Ð.").
res

İdeone'de bu çözümün işe yaradığını gösterebilir misiniz? Ben de hata alıyorum
mellamokb 14:02

IdICE çok fazla sayıda BİLDİRİM mesajı oluşturulduğunda hata veriyor gibi görünüyor : ~ Ð ('/' değerine eşit) ve ~ õ ("\ n" değerine eşit) her yinelemede bir BİLDİRİM oluşturur. Tabii ki, BİLDİRİMLERİNİZ varsa, bu bir sorun değildir. İkisi de değiştirilmiş bir macun (107 Bayt): ideone.com/lFUbl
primo

Ben sadece Ideone PHP yorumlayıcı yanlış çıktı oluşturduğunu fark ettim. Kodu yerel olarak çalıştırırsanız, kodun doğru olduğunu görürsünüz. Veya Anarchy Golf'ün performans denetleyicisi gibi geçerli bir PHP yorumlayıcısıyla test edebilirsiniz: golf.shinh.org/checker.html (bir dosyaya kaydedin ve yükleyin)
primo

Düzeltilmiş kodunuzu ANSI kodlaması olan bir dosyaya kaydettiğimde Anarchy Golf yorumlayıcısında çalışır. Ancak, şimdi farklı bir sorun var: listede "sıfır olmayan hiçbir rasyonel sayının iki kez görünmemesi" gerekliliğini ihlal ediyor . Aslında, kod her rasyonelleri sonsuz kez listeliyor gibi görünüyor; örneğin 1/1, 2/2, 3/3, ... vb aynı şekilde için 1/2, 2/4, 3/6, ..., hepsi aynı rasyonel ve
res

0

Oktav, 168 bayt

a=b=p=1;do for i=(p-1)^2+1:p^2-1 printf("%d: 0\n",i)end
printf("%d: %d/%d\n",p^2,a,b)
a=-a;if a>0do if b==1 b=a+1;a=1;else a++;b--;end until 1==gcd(a,b)end
p++;until 0

Çözüm çok sofistike değil, sadece rasyonel sayıların "halısının" basit bir çapraz geçişidir ve basitleştirilebilen tüm kesirler atılır. Pozitif bir sayıdan sonra , her zaman a/btersi -a/b, sıradaki bir sonrakinden önce yazdırılır.

Tüm pozitif rasyonların çapraz geçişi

Tüm pozitif basit kesirler yazdırılacak ve bunların ters imzalı kesirleri yazdırılacağı ve iki farklı basit kesirin aynı değere sahip olması asla mümkün olmadığından, sıfır olmayan her rasyonel sayı tam olarak bir kez yazdırılacaktır.

Degolfed:

a=b=p=1
do
    for i=(p-1)^2+1:p^2-1
        printf("%d: 0\n",i)         # p=2,3,4: 1..3,5..8,10..15
    end
    printf("%d: %d/%d\n", p^2,a,b); # p=2,3,4: 4,9,16
    a=-a;
    if a>0                          # the rule is: after a/b, a>0 output -a/b
        do
            if b==1 b=a+1;a=1; else a++;b--; end
        until 1==gcd(a,b)
    end
    p++;
until 0
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.