Тиражі цифр у Пі


13

Ваша мета - вивести строго зростаючу послідовність послідовних однакових цифр pi (π). Кожен член у послідовності повинен бути на одну цифру довший, ніж попередній. Отже 3(0-та цифра pi) - це перший раз, коли відбувається пробіг цифр (довжина 1). Наступним, що відбудеться, є 33(цифри 24 та 25 пі). Звичайно, ця послідовність вимагає, щоб цифри pi були в базі 10 .

Ті, які були відомі досі , і перші шість знаходяться в межах перших 800 цифр:

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

Зауважте, що всі послідовні дев'ятки відбуваються разом, в одному циклі, тому якщо наступний більший запуск, який ви виявили, буде 1000 послідовних 0с, це заповнить декілька членів послідовності.

Я більше не знайшов термінів зі своєю програмою. Я знаю, що немає більше термінів протягом перших 50000 цифр або більше. Моя програма занадто довго займала 500000 цифр, тому я відмовився.

Довідкова реалізація

Ви можете:

  • Виведіть послідовність назавжди
  • Візьміть ціле число nі знайдіть перші nчисла в послідовності
  • Візьміть ціле число nі знайдіть числа в послідовності, що міститься в перших nцифрах pi.

Обов’язково вкажіть, який саме код виконує. Число nможе бути нульовим або одним індексованим.

Натхненний цим запитанням про перехід .


1
Пов’язане - що пробіг 9-х спричинив головні болі для багатьох відповідей: 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

Математика, 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

Для цього я перейшов з Чудновського на Рамануджан 39. Чудновському не вистачило пам’яті в моїй системі незабаром після 100 мільйонів цифр, але Рамануджан домігся до 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

Швидші без обмежених генераторів

Довідкова реалізація, наведена в описі проблеми, цікава. Він використовує необмежений генератор, узятий безпосередньо з паперових алгоритмів Безмежного шпигуна для цифр Pi . За словами автора, надані реалізації є "навмисно неясними", тому я вирішив зробити нові реалізації всіх трьох алгоритмів, перерахованих автором, без навмисного придушення. Я також додав четвертий на основі Рамануджана №39 .

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 (Лейбніц / Ейлер)
    Додаткову змінну 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 (Госпер)
    Автор гадає, що зайве перевіряти, що nне зміниться в наступних ітераціях, і що це служить лише для уповільнення роботи алгоритму. Хоча це, мабуть, правда, генератор тримається на ~ 13% правильніших цифр, ніж наразі, що здається дещо марнотратним. Я знову додав чек і чекаю, коли 50 цифр будуть правильними, генеруючи їх усі відразу, із помітним посиленням продуктивності.
  • g4 (Рамануджан 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втілення приблизно на 235 разів швидше, ніж наg3_ref на 500 000 цифр. Але це означає, що існує ще значна істотна витрата на передачу цифр таким чином. Розрахувати всі цифри безпосередньо за допомогою Ramanujan 39 ( джерело пітона ) приблизно 10 разів швидше.

Чому б не Чудновський?

Алгоритм Чудновського вимагає повноцінного квадратного кореня, я, чесно кажучи, не впевнений, як працювати - припускаючи, що це взагалі може бути. Рамануджан 39 дещо особливий у цьому плані. Однак метод здається, що він може сприяти формулам, подібним Махіну, таким як ті, які використовує y-cruncher, так що це може бути дорога, яку варто вивчити.


TIL Ideone підтримує Pypy. Тож 2-а програма побудована для швидкості?
mbomb007

@ mbomb007 "Отже, 2-а програма побудована для швидкості?" Це є. Я думаю, що виклик був би таким же цікавим, як і найшвидший код .
примо

Те саме. Я розглядав обоє. Зазначте, як люди ставляться до повторної публікації під іншим тегом. Це може бути кориснішим, якщо він буде доданий до 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) 

Для цього використовуються алгоритми Безмежних шпігунів для цифр Пі Джеремі Гіббонса, 2004. Результат такий p. Технічно він повинен підтримувати нескінченні вихідні послідовності, але це може зайняти деякий час (і обмежене вашою пам'яттю).


3

Python 2, 298 байт

Зауважте, код для створення пі взято з реалізації ОП.

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. Виводить послідовність назавжди.


Чи можете ви поясніть, як ви πтут розраховуєте ? Ви, звичайно, розраховуєте пі, правда?
Р. Кап

Зараз ви не можете перевірити, але хіба ви не πвічні розрахунки там?
Yytsi

@TuukkaX не виглядає так, що він має yieldзупинку, але я не дуже хороший в python
Downgoat

Пуховик правильний - він використовує функцію генератора .
Мего

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 ітерацій, використовуючи ефективний алгоритм Гаусса-Лежандра , оскільки алгоритм, мабуть, подвоює кількість правильних цифр щоразу, і, отже, за 50 ітерацій ми можемо отримати 2^50чи 1,125,899,906,842,624виправити цифри. Нарешті, після закінчення обчислень, він використовує регулярний вираз із форматуванням рядків у awhile циклі для пошуку та друку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'> 

Тож, я можу впевнено сказати, що восьме число у послідовності навіть не відбувається протягом перших 10 мільйонів цифр! πце одне випадкове число ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.