Runs of Digits in Pi


13

เป้าหมายของคุณคือการส่งออกลำดับที่เพิ่มขึ้นอย่างต่อเนื่องของตัวเลขที่เหมือนกันของ pi (π) แต่ละคำในลำดับจะต้องมีความยาวมากกว่าหนึ่งหลัก ดังนั้น3(0th หลักของ pi) เป็นครั้งแรกที่มีการเรียกใช้ตัวเลข (ความยาว 1) สิ่งที่จะเกิดขึ้นถัดไปคือ33(ตัวเลข 24 และ 25 ของ pi) แน่นอนลำดับนี้ต้องใช้ตัวเลขของปี่ที่จะเป็นฐาน 10

คนที่รู้จักกันมานานและหกคนแรกทั้งหมดเกิดขึ้นภายใน 800 หลักแรก:

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

โปรดทราบว่าการเรียงลำดับเก้าทั้งหมดเกิดขึ้นพร้อมกันในการเรียกใช้เดียวกันดังนั้นหากการเรียกใช้ครั้งต่อไปที่ใหญ่ขึ้นคุณพบว่าเกิดขึ้น 1,000 ครั้งติดต่อกัน0สิ่งนี้จะเติมเต็มหลายเงื่อนไขของลำดับ

ฉันไม่พบคำศัพท์ใด ๆ เพิ่มเติมในโปรแกรมของฉัน ฉันรู้ว่าไม่มีคำศัพท์เพิ่มเติมในหลักแรก 50,00000 หรือมากกว่า โปรแกรมของฉันใช้เวลานานเกินไปด้วยจำนวน 500,000 หลักดังนั้นฉันจึงยอมแพ้

การดำเนินการอ้างอิง

คุณอาจ:

  • เอาต์พุตลำดับตลอดไป
  • ใช้จำนวนเต็มnและค้นหาnตัวเลขแรกในลำดับ
  • ใช้จำนวนเต็มnและค้นหาตัวเลขในลำดับที่มีอยู่ในnหลักแรกของ pi

ตรวจสอบให้แน่ใจว่าได้ระบุรหัสของคุณไว้ จำนวนnอาจเป็นศูนย์หรือหนึ่งดัชนี

แรงบันดาลใจจากคำถาม mathoverflowนี้


1
ที่เกี่ยวข้อง - ที่ทำงานของ 9s ทำให้ปวดหัวสำหรับคำตอบมากมาย: P
Mego

คุณได้รับอนุญาตให้เริ่มต้นเอาต์พุตด้วยลำดับที่ว่างเปล่าหรือไม่
LegionMammal978

2
นอกจากนี้คำต่อไปของลำดับปรากฏเป็น 3333333 ในหลัก 10 ^ -710100 ถึง 10 ^ -710106 ค่าสำหรับn = 8 ไม่ปรากฏในหลัก 5 000 000 หลัก
LegionMammal978

4
สองเทอมเพิ่มเติม: 44444444 ที่หลัก 10 ^ -22931745 ถึง 10 ^ -22931752 และ 777777777 ที่หลัก 10 ^ -24658601 ถึง 10 ^ -24658609 ค่าสำหรับn = 10 ไม่ปรากฏในหลักแรก 100,000 000
LegionMammal978

1
อีกหนึ่งเทอม: 6666666666 ที่ 10 ^ -386980412 คำที่ 11 ไม่ปรากฏใน 2 000 000 000 หลักแรก
โม่

คำตอบ:


5

Mathematica, 85 ไบต์

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

ฟังก์ชั่นไม่ระบุชื่อ รับnเป็นอินพุตและส่งคืนองค์ประกอบของลำดับในตัวเลขnแรกของπ {0, 3, 33, 111, ...}เอาท์พุทเป็นในรูปแบบของ


4

Python 2, 110 ไบต์

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

จำนวนหลักของการตรวจสอบสูงสุดนั้นมาจาก stdin 10,000 หลักเสร็จในเวลาประมาณ 2 วินาทีด้วย PyPy 5.3

ตัวอย่างการใช้งาน

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

สิ่งที่มีประโยชน์

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

ฉันได้เปลี่ยนจาก Chudnovsky เป็น Ramanujan 39 สำหรับเรื่องนี้ Chudnovsky มีหน่วยความจำไม่เพียงพอในระบบของฉันหลังจาก 100 ล้านหลัก แต่ Ramanujan ทำให้ไปถึง 400 ล้านในเวลาเพียง 38 นาที ฉันคิดว่านี่เป็นอีกกรณีหนึ่งที่มีอัตราการเติบโตที่ช้าลงของเงื่อนไขในท้ายที่สุดชนะอย่างน้อยในระบบที่มีทรัพยากร จำกัด

ตัวอย่างการใช้งาน

$ 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

เครื่องกำเนิดที่ไม่ จำกัด ได้เร็วกว่า

การใช้การอ้างอิงที่ระบุในคำอธิบายปัญหาน่าสนใจ โดยจะใช้เครื่องกำเนิดไฟฟ้ามากมายที่นำมาโดยตรงจากกระดาษUnbounded หัวจุกอัลกอริทึมสำหรับตัวเลขของพี่ การใช้งานที่ให้ไว้เป็น "จงใจปิดบัง" ดังนั้นฉันจึงตัดสินใจที่จะทำให้การใช้งานใหม่ของทั้งสามขั้นตอนวิธีการระบุไว้โดยผู้เขียนโดยไม่ต้องทำให้งงงวยโดยเจตนา ฉันได้เพิ่มนอกจากนี้ยังเป็นหนึ่งในสี่บนพื้นฐานของRamanujan #

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)

หมายเหตุ

ด้านบนคือการใช้งาน 6 รายการ: การใช้งานอ้างอิงสองรายการที่จัดทำโดยผู้แต่ง (เขียนแทน_ref) และสี่คำที่คำนวณเป็นแบตช์สร้างตัวเลขหลายหลักพร้อมกัน ( _md) การใช้งานทั้งหมดได้รับการยืนยันถึง 100,000 หลัก เมื่อเลือกขนาดแบทช์ฉันเลือกค่าที่ค่อยๆลดความแม่นยำลงตามเวลา ตัวอย่างเช่นg1_mdสร้าง 10 หลักต่อชุดพร้อม 33 ซ้ำ อย่างไรก็ตามสิ่งนี้จะสร้างตัวเลขที่ถูกต้อง ~ 9.93 เท่านั้น เมื่อความแม่นยำหมดสภาพการตรวจสอบจะล้มเหลวการทริกเกอร์ชุดพิเศษที่จะทำงาน สิ่งนี้ดูเหมือนว่าจะมีประสิทธิภาพมากกว่าความแม่นยำที่ช้าลงอย่างเห็นได้ชัดเมื่อเวลาผ่านไป

  • G1 (Leibniz / ออยเลอร์)
    ตัวแปรเสริมจะถูกเก็บไว้เป็นตัวแทนของj 2*i+1ผู้เขียนทำสิ่งเดียวกันในการนำไปใช้อ้างอิง การคำนวณnแยกกันอยู่ไกลง่าย (และปิดบังน้อยกว่า) เพราะใช้ค่าปัจจุบันของq, rและtมากกว่าถัดไป
  • g2 (แลมเบิร์ต)
    เช็คn == q/sเป็นที่ยอมรับค่อนข้างหย่อนยาน ที่ควรอ่านn == (q*(k+2*j+4)+r)/(s*(k+2*j+4)+t)ที่jเป็น2*i-1และเป็นk i*iที่การวนซ้ำที่สูงกว่าเงื่อนไขrและtข้อกำหนดมีความสำคัญลดลงเรื่อย ๆ อย่างที่มันเป็นดีสำหรับ 100,000 หลักแรกดังนั้นมันอาจจะดีสำหรับทุกคน ผู้เขียนไม่ได้ใช้การอ้างอิง
  • g3 (Gosper)
    ผู้เขียนคาดเดาว่ามันไม่จำเป็นที่จะตรวจสอบว่าnจะไม่เปลี่ยนแปลงในการทำซ้ำตามมาและมันทำหน้าที่เพียงเพื่อชะลออัลกอริทึม ในขณะที่อาจเป็นจริงเครื่องกำเนิดไฟฟ้าจะยึดตัวเลขที่ถูกต้องมากกว่า ~ 13% มากกว่าที่สร้างขึ้นในปัจจุบันซึ่งดูเหมือนจะค่อนข้างสิ้นเปลือง ฉันได้เพิ่มการตรวจสอบย้อนกลับและรอจนกว่าตัวเลข 50 หลักถูกต้องสร้างพวกเขาทั้งหมดในครั้งเดียวพร้อมประสิทธิภาพที่เพิ่มขึ้นอย่างเห็นได้ชัด
  • g4 (Ramanujan 39)
    คำนวณว่า

    น่าเสียดายsไม่เป็นศูนย์เนื่องจากองค์ประกอบเริ่มต้น (3528 ÷) แต่ก็ยังเร็วกว่า g3 อย่างมาก การบรรจบกันคือ ~ 5.89 หลักต่อเทอม 3511 หลักถูกสร้างขึ้นในแต่ละครั้ง ถ้ามันค่อนข้างมากการสร้าง 271 หลักต่อ 46 การทำซ้ำก็เป็นตัวเลือกที่ดีเช่นกัน

การกำหนดเวลา

ถ่ายในระบบของฉันเพื่อการเปรียบเทียบเท่านั้น เวลามีการระบุไว้ในไม่กี่วินาที หากเวลาใช้เวลานานกว่า 10 นาทีฉันจะไม่ทำการทดสอบเพิ่มเติมใด ๆ

            |  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 

เป็นที่น่าสนใจว่าg2ในที่สุดจะแซงg3แม้ว่าอัตราการลู่เข้าจะช้าลง ฉันสงสัยว่านี่เป็นเพราะตัวถูกดำเนินการเติบโตในอัตราที่ช้าลงอย่างมากชนะในระยะยาว การใส่ที่เร็วที่สุดg4_mdคือ 235x เร็วกว่าการg3_refใส่ที่ 500,000 เลขหลัก ที่กล่าวว่ายังคงมีค่าใช้จ่ายที่สำคัญในการสตรีมตัวเลขด้วยวิธีนี้ การคำนวณตัวเลขทั้งหมดโดยตรงโดยใช้ Ramanujan 39 ( แหล่งไพ ธ อน ) นั้นเร็วประมาณ 10 เท่า

ทำไมไม่ Chudnovsky

อัลกอริทึมของ Chudnovsky นั้นต้องการสแควร์รูทที่มีความแม่นยำเต็มรูปแบบซึ่งฉันก็ไม่แน่ใจว่าจะใช้งานได้จริงหรือไม่ Ramanujan 39 ค่อนข้างพิเศษในเรื่องนี้ อย่างไรก็ตามวิธีการนี้ดูเหมือนว่าอาจเอื้อต่อสูตรที่เหมือน Machin เช่นที่ใช้โดย y-cruncher เพื่อที่จะได้เป็นสถานที่ที่ควรค่าแก่การสำรวจ


TIL Ideone รองรับ Pypy ดังนั้นโปรแกรมที่ 2 จึงถูกสร้างขึ้นมาเพื่อความเร็ว
mbomb007

@ mbomb007 "โปรแกรมที่สองถูกสร้างขึ้นมาเพื่อความเร็วใช่หรือไม่"มันคือ. ผมคิดว่าความท้าทายที่จะได้รับอย่างเท่าเทียมกันเป็นที่น่าสนใจเป็นเร็วที่สุดรหัส
Primo

เหมือนกัน. ฉันถือว่าทั้งสอง Idk ความรู้สึกของผู้คนเกี่ยวกับการโพสต์ใหม่ภายใต้แท็กอื่น มันอาจจะมีประโยชน์มากกว่านี้ถ้าจะเพิ่มใน OEIS (ซึ่งไม่มีลำดับนี้)
mbomb007

3

Haskell, 231 ไบต์

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) 

นี้ใช้Unbounded หัวจุกอัลกอริทึมสำหรับตัวเลขของพี่โดยเจเรมีชะนีปี 2004 pผลที่ได้คือ ในทางเทคนิคมันควรสนับสนุนลำดับเอาต์พุตไม่สิ้นสุด แต่อาจใช้เวลาสักครู่ (และถูก จำกัด โดยหน่วยความจำของคุณ)


3

Python 2, 298 ไบต์

หมายเหตุรหัสสำหรับสร้าง pi นั้นนำมาจากการใช้งานของ OP

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 เอาต์พุตลำดับตลอดไป


คุณช่วยอธิบายวิธีคำนวณπที่นี่ได้มั้ย แน่นอนคุณคำนวณ pi ได้ไหม
R. Kap

ไม่สามารถทดสอบได้ในตอนนี้ แต่คุณไม่คำนวณπตลอดกาลใช่ไหม
Yytsi

@TuukkaX ไม่ปรากฏขึ้นเนื่องจากมันมีตัวyieldหยุดทำงาน แต่ฉันไม่เก่งเรื่องไพ
ธ อน

Downgoat ถูกต้อง - จะใช้ฟังก์ชั่นเครื่องกำเนิดไฟฟ้า
Mego

1
ฉันเขียนรหัสทั้งหมดฉันไม่ได้ดูการใช้งานของคุณยกเว้นpส่วน
acrolith

3

Python 3.5, 278 263 ไบต์:

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

สิ่งนี้ใช้nเป็นอินพุตสำหรับnตัวเลขแรกของπจากนั้นเอาท์พุทสมาชิกของลำดับในnหลักแรกเหล่านั้น ตอนนี้สิ่งนี้ใช้โมดูลทศนิยมในตัวของ Python เกินกว่าข้อ จำกัด ทศนิยมของ Python จากนั้นตั้งค่าความแม่นยำหรือ epsilon ให้กับผู้ใช้ที่ป้อนเข้ามา จากนั้นในการคำนวณπนี่ใช้การวนซ้ำ 50 ครั้งโดยใช้อัลกอริธึม Gausse-Legendre ที่มีประสิทธิภาพเนื่องจากอัลกอริทึมเห็นได้ชัดว่าเพิ่มจำนวนตัวเลขที่ถูกต้องสองเท่าในแต่ละครั้งดังนั้นใน 50 รอบเราสามารถขึ้น2^50หรือ1,125,899,906,842,624ตัวเลขที่ถูกต้อง ในที่สุดหลังจากการคำนวณเสร็จสิ้นจะใช้นิพจน์ทั่วไปที่มีการจัดรูปแบบสตริงในwhileลูปเพื่อค้นหาและพิมพ์re จับคู่ออบเจ็กต์ (ซึ่งฉันหวังว่าไม่เป็นไร) สำหรับตัวเลขต่อเนื่องทั้งหมดที่เกิดขึ้น 1 หลักที่ยาวกว่าในการวนซ้ำก่อนหน้าผ่านลูป

ฉันสามารถใช้อัลกอริธึมนี้ในการคำนวณตัวเลขπให้ได้ถึง10,000,000สิบล้านตัวซึ่งใช้เวลาประมาณ 4 ชั่วโมง 12 นาที ต่อไปนี้เป็นผลลัพธ์สุดท้าย:

<_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'> 

ดังนั้นฉันสามารถพูดได้อย่างมั่นใจว่าหมายเลขที่ 8 ในลำดับนั้นไม่ได้เกิดขึ้นภายใน 10 ล้านหลักแรก! πคือหมายเลขสุ่มหนึ่งตัว ...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.