Pi Rakamlar


13

Amacınız pi (,) 'nin ardışık, özdeş basamaklarının kesinlikle artan sırasını çıkarmaktır. Dizideki her terim öncekinden bir basamak daha uzun olmalıdır. Yani 3(pi'nin 0 basamağı) ilk kez bir basamak çalışması meydana gelir (uzunluk 1). Bir sonraki gerçekleşir 33(pi'nin 24 ve 25 basamakları). Tabii ki, bu dizi pi basamaklarının baz 10'da olmasını gerektirir .

Şimdiye kadar bilinenler ve ilk altısı ilk 800 basamakta gerçekleşir:

3
33
111
9999
99999
999999
3333333
44444444
777777777
6666666666
... (not in first 2 billion digits)

Birbirini takip eden dokuzun hepsinin aynı çalışmada birlikte gerçekleştiğine dikkat edin, bu yüzden bir sonraki daha büyük koşunun ardışık olarak 1000 ardışık olması durumunda 0, bu dizinin birden çok terimini dolduracaktır .

Programımla ilgili başka terim bulamadım. İlk 50000 veya daha fazla basamakta daha fazla terim olmadığını biliyorum. Programım 500000 basamakla çok uzun sürüyordu, bu yüzden vazgeçtim.

Referans uygulaması

Yapabilirsin:

  • Diziyi sonsuza kadar çıkar
  • Bir tamsayı alın nve ndizideki ilk sayıları bulun
  • Bir tamsayı alın nve npi'nin ilk basamaklarında bulunan dizideki sayıları bulun .

Kodunuzun hangisini yapacağınızı belirttiğinizden emin olun. Sayı nsıfır veya bir dizinlenmiş olabilir.

Bu mathoverflow sorusundan ilham alındı .


1
İlgili - 9'ların koşusu birçok cevap için baş ağrısına neden oldu: P
Mego

Çıktıyı boş diziyle başlatabilir misiniz?
LegionMammal978

2
Ayrıca, dizinin bir sonraki terimi 10 ^ -710100 ile 10 ^ -710106 arasındaki rakamlarda 3333333 olarak görünür. N = 8 değeri ilk 5.000.000 basamakta görünmez.
LegionMammal978

4
İki terim daha: 10 ^ -22931745 ile 10 ^ -22931752 arası rakamlarda 44444444 ve 10 ^ -24658601 ile 10 ^ -24658609 arası rakamlarda 777777777. N = 10 değeri ilk 100 000 000 basamakta görünmez.
LegionMammal978

1
Bir terim daha: 6666666666, 10 ^ -386980412'de. 11. terim ilk 2.000.000.000 basamağında görünmez.
primo

Yanıtlar:


5

Mathematica, 85 bayt

FromDigits/@DeleteDuplicatesBy[Join@@Subsets/@Split@RealDigits[Pi,10,#][[1]],Length]&

Anonim işlev. Alır N girdi olarak ve ilk olarak dizinin elemanları döner N tt basamak. Çıktı şeklindedir {0, 3, 33, 111, ...}.


4

Python 2, 110 bayt

n=input()
x=p=7*n|1
while~-p:x=p/2*x/p+2*10**n;p-=2
l=m=0
for c in`x`:
 l=l*(p==c)+1;p=c
 if l>m:m=l;print p*l

Kontrol edilecek maksimum basamak sayısı stdin'den alınmıştır. 10.000 basamak PyPy 5.3 ile yaklaşık 2 saniyede bitiyor.

Örnek Kullanımı

$ echo 10000 | pypy pi-runs.py
3
33
111
9999
99999
999999

Kullanışlı bir şey

from sys import argv
from gmpy2 import mpz

def pibs(a, b):
  if a == b:
    if a == 0:
      return (1, 1, 1123)
    p = a*(a*(32*a-48)+22)-3
    q = a*a*a*24893568
    t = 21460*a+1123
    return (p, -q, p*t)
  m = (a+b) >> 1
  p1, q1, t1 = pibs(a, m)
  p2, q2, t2 = pibs(m+1, b)
  return (p1*p2, q1*q2, q2*t1 + p1*t2)

if __name__ == '__main__':
  from sys import argv
  digits = int(argv[1])

  pi_terms = mpz(digits*0.16975227728583067)
  p, q, t = pibs(0, pi_terms)

  z = mpz(10)**digits
  pi = 3528*q*z/t

  l=m=0
  x=0
  for c in str(pi):
   l=l*(p==c)+1;p=c
   if l>m:m=l;print x,p*l
   x+=1

Bunun için Chudnovsky'den Ramanujan 39'a geçtim. Chudnovsky, 100 milyon basamaktan kısa bir süre sonra sistemimde bellek kalmadı, ancak Ramanujan sadece 38 dakika içinde 400 milyona ulaştı. Bence bu, en azından sınırlı kaynaklara sahip bir sistemde, terimlerin yavaş büyüme oranının kazanmasıydı.

Örnek Kullanımı

$ python pi-ramanujan39-runs.py 400000000
0 3
25 33
155 111
765 9999
766 99999
767 999999
710106 3333333
22931752 44444444
24658609 777777777
386980421 6666666666

Daha Hızlı Sınırsız Jeneratörler

Sorun tanımında verilen referans uygulaması ilginçtir. Pi Basamakları için doğrudan Kağıt Bağlanmamış Spigot Algoritmaları'ndan alınan sınırsız bir jeneratör kullanır . Yazara göre, sağlanan uygulamalar "kasıtlı olarak belirsiz", bu yüzden kasıtlı gizleme olmadan yazar tarafından listelenen her üç algoritmanın da yeni uygulamalarını yapmaya karar verdim. Ayrıca Ramanujan # 39'a dayanan bir dördüncü ekledim .

try:
  from gmpy2 import mpz
except:
  mpz = long

def g1_ref():
  # Leibniz/Euler, reference
  q, r, t = mpz(1), mpz(0), mpz(1)
  i, j = 1, 3
  while True:
    n = (q+r)/t
    if n*t > 4*q+r-t:
      yield n
      q, r = 10*q, 10*(r-n*t)
    q, r, t = q*i, (2*q+r)*j, t*j
    i += 1; j += 2

def g1_md():
  # Leibniz/Euler, multi-digit
  q, r, t = mpz(1), mpz(0), mpz(1)
  i, j = 1, 3
  z = mpz(10)**10
  while True:
    n = (q+r)/t
    if n*t > 4*q+r-t:
      for d in digits(n, i>34 and 10 or 1): yield d
      q, r = z*q, z*(r-n*t)
    u, v, x = 1, 0, 1
    for k in range(33):
      u, v, x = u*i, (2*u+v)*j, x*j
      i += 1; j += 2
    q, r, t = q*u, q*v+r*x, t*x

def g2_md():
  # Lambert, multi-digit
  q, r, s, t = mpz(0), mpz(4), mpz(1), mpz(0)
  i, j, k = 1, 1, 1
  z = mpz(10)**49
  while True:
    n = (q+r)/(s+t)
    if n == q/s:
      for d in digits(n, i>65 and 49 or 1): yield d
      q, r = z*(q-n*s), z*(r-n*t)
    u, v, w, x = 1, 0, 0, 1
    for l in range(64):
      u, v, w, x = u*j+v, u*k, w*j+x, w*k
      i += 1; j += 2; k += j
    q, r, s, t = q*u+r*w, q*v+r*x, s*u+t*w, s*v+t*x

def g3_ref():
  # Gosper, reference
  q, r, t = mpz(1), mpz(180), mpz(60)
  i = 2
  while True:
    u, y = i*(i*27+27)+6, (q+r)/t
    yield y
    q, r, t, i = 10*q*i*(2*i-1), 10*u*(q*(5*i-2)+r-y*t), t*u, i+1

def g3_md():
  # Gosper, multi-digit
  q, r, t = mpz(1), mpz(0), mpz(1)
  i, j = 1, 60
  z = mpz(10)**50
  while True:
    n = (q+r)/t
    if n*t > 6*i*q+r-t:
      for d in digits(n, i>38 and 50 or 1): yield d
      q, r = z*q, z*(r-n*t)
    u, v, x = 1, 0, 1
    for k in range(37):
      u, v, x = u*i*(2*i-1), j*(u*(5*i-2)+v), x*j
      i += 1; j += 54*i
    q, r, t = q*u, q*v+r*x, t*x

def g4_md():
  # Ramanujan 39, multi-digit
  q, r, s ,t = mpz(0), mpz(3528), mpz(1), mpz(0)
  i = 1
  z = mpz(10)**3511
  while True:
    n = (q+r)/(s+t)
    if n == (22583*i*q+r)/(22583*i*s+t):
      for d in digits(n, i>597 and 3511 or 1): yield d
      q, r = z*(q-n*s), z*(r-n*t)
    u, v, x = mpz(1), mpz(0), mpz(1)
    for k in range(596):
      c, d, f = i*(i*(i*32-48)+22)-3, 21460*i-20337, -i*i*i*24893568
      u, v, x = u*c, (u*d+v)*f, x*f
      i += 1
    q, r, s, t = q*u, q*v+r*x, s*u, s*v+t*x

def digits(x, n):
  o = []
  for k in range(n):
    x, r = divmod(x, 10)
    o.append(r)
  return reversed(o)

notlar

Yukarıda 6 uygulama vardır: yazar tarafından sağlanan iki referans uygulaması (belirtilen _ref) ve toplu olarak terimleri hesaplayan ve aynı anda birden fazla basamak oluşturan dört uygulama ( _md). Tüm uygulamalar 100.000 basamağa kadar onaylanmıştır. Parti boyutlarını seçerken, zaman içinde hassasiyeti yavaş yavaş kaybeden değerleri seçtim. Örneğin, g1_mdtoplu iş başına 33 basamaklı 10 basamak oluşturur. Ancak, bu sadece ~ 9.93 doğru basamak üretir. Hassasiyet bittiğinde, kontrol koşulu başarısız olur ve fazladan bir parti çalıştırılmasını tetikler. Bu, zaman içinde yavaş yavaş ekstra ekstra, gereksiz hassasiyetten daha performanslı görünüyor.

  • g1 (Leibniz / Euler) Temsil eden
    fazladan bir değişken jtutulur 2*i+1. Yazar aynı şeyi referans uygulamasında da yapar. Hesaplama no anki değerlerini kullandığı için ayrı ayrı, çok daha basit (ve daha az belirsiz) 'dir q, rve tyerine gelecek daha.
  • g2 (Lambert)
    Çek n == q/skuşkusuz oldukça gevşek. Yani okumalı n == (q*(k+2*j+4)+r)/(s*(k+2*j+4)+t), nerede jolduğunu 2*i-1ve kbir i*i. Yüksek yinelemelerde rve tterimleri giderek daha az önemli hale gelir. Olduğu gibi, ilk 100.000 basamak için iyidir, bu yüzden muhtemelen herkes için iyidir. Yazar hiçbir referans uygulaması sağlamaz.
  • g3 (Gosper)
    Yazar n, sonraki yinelemelerde değişmeyeceğini kontrol etmenin gereksiz olduğunu ve sadece algoritmayı yavaşlatmaya hizmet ettiğini tahmin ediyor. Muhtemelen doğru olsa da, jeneratör şu anda ürettiğinden ~% 13 daha doğru rakamlar tutuyor, bu da biraz israf gibi görünüyor. Check-in işlemini tekrar ekledim ve 50 basamaklı doğru olana kadar bekleyin, hepsini bir kerede üretin, performansta gözle görülür bir kazanç sağlayın.
  • g4 (Ramanujan 39)
    olarak hesaplanan

    Maalesef snedeniyle ilk (3528 ÷) bileşimine, sıfır dışarı vermez, ama g3 çok daha hızlı hala bu. Yakınsama her terim için ~ 5.89 hane, bir seferde 3511 hane oluşturulur. Bu biraz fazlaysa, 46 yineleme başına 271 basamak oluşturmak da iyi bir seçimdir.

zamanlamalar

Sadece karşılaştırma amacıyla sistemime alındı. Zamanlar saniye olarak listelenir. Bir zamanlama 10 dakikadan uzun sürerse, başka test yapmadım.

            |  g1_ref |  g1_md  |  g2_md  |  g3_ref |  g3_md  |  g4_md 
------------+---------+---------+---------+---------+---------+--------
    10,000  |  1.645  |  0.229  |  0.093  |  0.312  |  0.062  |  0.062 
    20,000  |  6.859  |  0.937  |  0.234  |  1.140  |  0.250  |  0.109 
    50,000  |  55.62  |  5.546  |  1.437  |  9.703  |  1.468  |  0.234 
   100,000  |  247.9  |  24.42  |  5.812  |  39.32  |  5.765  |  0.593 
   200,000  |  2,158  |  158.7  |  25.73  |  174.5  |  33.62  |  2.156 
   500,000  |    -    |  1,270  |  215.5  |  3,173  |  874.8  |  13.51 
 1,000,000  |    -    |    -    |  1,019  |    -    |    -    |  58.02 

Yavaş bir yakınsama hızına rağmen , g2sonunda geçmesi ilginçtir g3. Bunun, işlenenlerin uzun vadede kazanarak önemli ölçüde daha yavaş bir oranda büyümesinden kaynaklandığından şüpheleniyorum. En hızlı uygulama g4_md, g3_ref500.000 basamak üzerindeki uygulamadan yaklaşık 235 kat daha hızlıdır . Bununla birlikte, bu şekilde akış rakamlarının hala önemli bir yükü var. Tüm basamakları doğrudan Ramanujan 39 ( python kaynağı ) kullanarak hesaplamak yaklaşık 10 kat daha hızlıdır.

Neden Chudnovsky olmasın?

Chudnovsky algoritması, tam olarak nasıl çalışılacağından emin olamadığım tam hassas bir kare kök gerektirir - hiç olmadığı varsayılır. Ramanujan 39 bu konuda biraz özeldir. Bununla birlikte, yöntem y-cruncher tarafından kullanılanlar gibi Machin benzeri formüllere elverişli görünebilir, bu yüzden keşfetmeye değer bir yol olabilir.


TIL Ideone Pypy'yi destekliyor. Peki 2. program hız için mi oluşturuldu?
mbomb007

@ mbomb007 "İkinci program hız için mi oluşturuldu?" Bu. Bence meydan okuma en hızlı kod kadar ilginç olurdu .
primo

Aynı. İkisini de düşündüm. İnsanların farklı bir etiket altında yeniden gönderme hakkında nasıl hissettiklerini belirtin.
OEIS'e

3

Haskell, 231 bayt

import Data.List
g(q,r,t,k,n,l)|4*q+r-t<n*t=n:g(10*q,10*(r-n*t),t,k,div(10*(3*q+r))t-10*n,l)|0<1=g(q*k,(2*q+r)*l,t*l,k+1,div(q*(7*k+2)+r*l)(t*l),l+2)
p=nubBy(\x y->length x==length y).concatMap inits.group$g(1,0,1,1,3,3) 

Bu, Jeremy Gibler'in Pi Basamakları için Sınırsız Tıkaç Algoritmalarını kullanır, Jeremy Gibbons, 2004 p. Teknik olarak, sonsuz çıkış dizilerini desteklemelidir, ancak bu biraz zaman alabilir (ve belleğinizle sınırlıdır).


3

Python 2, 298 bayt

Pi oluşturma kodunun OP uygulamasından alındığını unutmayın.

def p():
 q,r,t,j=1,180,60,2
 while 1:
  u,y=3*(3*j+1)*(3*j+2),(q*(27*j-12)+5*r)//(5*t)
  yield y
  q,r,t,j=10*q*j*(2*j-1),10*u*(q*(5*j-2)+r-y*t),t*u,j+1
p=p()
c=r=0
d=[0]
while 1:
 t=p.next()
 if t==d[len(d)-1]:d.append(t)
 else:d=[t]
 if len(d)>r:r=len(d);print"".join([`int(x)`for x in d])
 c+=1

Python'da ilk golf girişimim. Diziyi sonsuza dek çıkarır.


πBurada nasıl hesapladığınızı açıklar mısınız? Elbette pi hesaplıyorsunuz değil mi?
R. Kap

Şu anda test yapamıyorum, ama πorada sonsuza kadar hesaplamıyor musunuz?
Yytsi

@TuukkaX durduğu için görünmüyor yield, ancak
python'da

Downgoat doğrudur - bir jeneratör işlevi kullanır .
Mego

1
Tüm kodu yazdım, pbölüm dışında uygulamanıza
bakmadım

3

Python 3.5, 278 263 bayt:

import decimal,re;decimal.getcontext().prec=int(input());D=decimal.Decimal;a=p=1;b,t=1/D(2).sqrt(),1/D(4)
for i in[1]*50:z=(a+b)/2;b=(a*b).sqrt();t-=p*(a-z)**2;a=z;p*=2;pi=(z*2)**2/(4*t);i=0;C=lambda r:re.search(r'(\d)\1{%s}'%r,str(pi))
while C(i):print(C(i));i+=1

Bu n, ilk nhanelere giriş olarak alınır πve daha sonra bu ilk nhanelere dizinin üyelerini verir . Şimdi, bu, Python'un kayan nokta sınırlamalarının ötesine geçmek için Python'un yerleşik ondalık modülünü kullanır ve daha sonra hassasiyeti veya epsilon'u kullanıcı girişlerine ayarlar. Daha sonra, hesaplamak için π, bu etkili Gausse-Legendre algoritmasını kullanarak 50 iterasyondan geçer , çünkü algoritma her seferinde doğru basamak sayısını iki katına çıkarır ve bu nedenle 50 iterasyonda basamaklara ulaşabilir 2^50veya 1,125,899,906,842,624düzeltebiliriz. Son olarak, hesaplamalar yapıldıktan sonra, whilebulmak ve yazdırmak için bir döngüde dize biçimlendirmeli normal bir ifade kullanırre döngü boyunca önceki yinelemeden 1 basamak daha uzun tüm sürekli, yinelenen basamaklar için nesneleri (ki umarım iyidir) eşleştirin.

Bu algoritmayı (on milyon) basamağı başarıyla ve doğru bir şekilde hesaplamak πiçin kullanabildim 10,000,000, bu işlemin tamamlanması yaklaşık 4 saat 12 dakika sürdü. Son çıktı aşağıdaki gibidir:

<_sre.SRE_Match object; span=(0, 1), match='3'>
<_sre.SRE_Match object; span=(25, 27), match='33'>
<_sre.SRE_Match object; span=(154, 157), match='111'>
<_sre.SRE_Match object; span=(763, 767), match='9999'>
<_sre.SRE_Match object; span=(763, 768), match='99999'>
<_sre.SRE_Match object; span=(763, 769), match='999999'>
<_sre.SRE_Match object; span=(710101, 710108), match='3333333'> 

Yani, dizideki 8. sayının ilk 10 milyon basamakta bile gerçekleşmediğini güvenle söyleyebilirim! πrastgele bir sayı ...

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.