Обчислюючи усічені цифри суми повноважень pi


12

За умови додатного цілого n вивести суму перших n десяткових цифр дробової частини π n .

Приклад вводу та виходів:

1 → 1
2 → 14
3 → 6
4 → 13
5 → 24
50 → 211
500 → 2305
5000 → 22852

Вбудовані функції, що обчислюють цифри π або оцінюють серію потужності або тривалі дроби, не дозволяються. Застосовуються стандартні лазівки . Введення / вихід може бути у зручному форматі (stdin, stdout, функція вводу / виводу тощо).

Виграє найкоротший код у байтах .


Чи заборонені й інші триггерні функції, які можна використовувати для обчислення пі, але не обов'язково безпосередньо, як арктангент чи уявні логарифми? Крім того, чи існує верхня межа n, після якої вона може провалюватися?
FryAmTheEggman

@FryAmTheEggman Якщо ці триггерні функції можуть обчислювати довільні цифри pi, тоді так вони заборонені. Ваша програма повинна теоретично працювати для будь-якої російської мови , але це прощається, якщо час виконання або пам'ять стане занадто високою.
orlp

Відповіді:


4

Пітон - 191 байт

t=i=1L;k=n=input();f=2000*20**n;A=range(n+1)
for k in range(2,n):A=[(A[j-1]+A[j+1])*j>>1for j in range(n-k+1)];f*=k
while k:k=(1-~i*n%4)*f/A[1]/i**n;t+=k;i+=2
print sum(map(int,`t`[-n-4:-4]))

~ В 4 рази швидша версія - 206 байт

t=i=1L;k=n=input();f=2000*20**n;A=[0,1]+[0]*n
for k in range(1,n):
 f*=k
 for j in range(-~n/2-k+1):A[j]=j*A[j-1]+A[j+1]*(j+2-n%2)
while k:k=(1-~i*n%4)*f/A[1]/i**n;t+=k;i+=2
print sum(map(int,`t`[-n-4:-4]))

Введення взято з stdin. Вихід для n = 5000 займає приблизно 14 секунд з другим сценарієм (або 60-х з першим).


Використання зразка:

$ echo 1 | python pi-trunc.py
1

$ echo 2 | python pi-trunc.py
14

$ echo 3 | python pi-trunc.py
6

$ echo 4 | python pi-trunc.py
13

$ echo 5 | python pi-trunc.py
24

$ echo 50 | python pi-trunc.py
211

$ echo 500 | python pi-trunc.py
2305

$ echo 5000 | python pi-trunc.py
22852

Використовувана формула така:

де A n - n- й змінний номер , який формально можна визначити як кількість чергуються перестановок на множині розміру n (див. також: A000111 ). Альтернативно, послідовність можна визначити як склад дотичних чисел і таємних чисел ( A 2n = S n , A 2n + 1 = T n ), про це пізніше.

Малий поправочний коефіцієнт c n швидко переходить до 1, оскільки n стає великим, і задається:

Для n = 1 це означає оцінку серії Лейбніца . Облікуючи π як 10 ½ , кількість необхідних термінів можна обчислити як:

який збігається (округляється) до 17 , хоча менші значення n вимагають значно більше.

Для обчислення A n існує кілька алгоритмів і навіть явна формула, але всі вони є квадратичними по n . Я спочатку кодував реалізацію алгоритму Зейделя , але це виявляється занадто повільним, щоб бути практичним. Кожна ітерація потребує збереження додаткового терміна, а умови збільшуються на величину дуже швидко («неправильний» вид O (n 2 ) ).

Перший сценарій використовує реалізацію алгоритму, який спочатку давали Кнут та Бакхолц :

Нехай T 1, k = 1 для всіх k = 1..n

Наступні значення Т задаються відношенням рецидивування:

T n + 1, k = 1/2 [ (k - 1) T n, k-1 + (k + 1) T n, k + 1 ]

Тоді A n задається T n, 1

(див. також: A185414 )

Хоча це прямо не вказано, цей алгоритм обчислює і дотичні числа, і таємні числа одночасно. Другий сценарій використовує варіацію цього алгоритму Брент та Циммерманна , яка обчислює або T, або S , залежно від паритету n . Поліпшення є квадратичним на n / 2 , отже, ~ 4-кратне підвищення швидкості.


1
Відмінне пояснення математики за вашою відповіддю.
Логічний лицар

3

Python 2, 246 байт

Я застосував аналогічний підхід до своєї відповіді при обчисленні π з квадратичною збіжністю . Останній рядок приймає N-ту силу pi і підсумовує цифри. Тест N = 5000 займає хвилину або близько того.

from decimal import*
d=Decimal
N=input()
getcontext().prec=2*N
j=d(1)
h=d(2)
f=h*h
g=j/h
a=j
b=j/h.sqrt()
t=j/f
p=j
for i in bin(N)[2:]:e=a;a,b=(a+b)/h,(a*b).sqrt();c=e-a;t-=c*c*p;p+=p
k=a+b
l=k*k/f/t
print sum(map(int,`l**N`.split('.')[1][:N]))

Деякі тести:

$ echo 1 | python soln.py
1
$ echo 3 | python soln.py
6
$ echo 5 | python soln.py
24
$ echo 500 | python soln.py
2305
$ echo 5000 | python soln.py
22852

Невикористаний код:

from decimal import *
d = Decimal

N = input()
getcontext().prec = 2 * N

# constants:
one = d(1)
two = d(2)
four = two*two
half = one/two

# initialise:
a = one
b = one / two.sqrt()
t = one / four
p = one

for i in bin(N)[2:] :
    temp = a;
    a, b = (a+b)/two, (a*b).sqrt();
    pterm = temp-a;
    t -= pterm*pterm * p;
    p += p

ab = a+b
pi = ab*ab / four / t
print sum(map(int, `pi ** N`.split('.')[1][:N]))

Рядок 8, ви можете звернутися a=jі p=jдо a=p=jIIRC. Може бути.
Ілля Бенедес

Дякую. Існує більше оптимізацій для гольфу для цього коду, але він не буде конкурентоспроможним без перезапису з використанням алгоритму без Десяткової.
Логічний лицар

1

Піта, 33

s<>j^u+/*GHhyHy^TyQr*TQ0ZQT_y*QQQ

На основі цієї відповіді isaacg . Можливо, можна було б пограти в гольф більше. Повільно.

s<>j            Digit sum of...
  ^                 
    u               Evaluate pi = 2 + 1/3*(2 + 2/5*(2 + 3/7*(2 + 4/9*(2 + ...))))
      +
        /
          *GH
          hyH
        y^TyQ       Except we generate a large integer containing 2n digits,
                    rather than a fraction.
      r*TQ0         Experimentally verified that 10*n iterations will give enough
                    precision for 2n digits (# digits correct grows faster than 2n).
      Z
    Q               To the nth power.
  T_y*QQQ         Get the last 2n^2 digits (all the fractional digits) and get the
                  first n fractional digits.

1
Ця відповідь справді потребує хоча б достатнього пояснення, щоб обґрунтувати, що вона обчислює достатню кількість цифр, щоб отримати правильну відповідь.
Пітер Тейлор

@PeterTaylor Я завтра додам пояснення, ось-ось лягаю спати.
orlp

Кожна ітерація створює один правильний біт (див. Додаток А ). Для 2n цифр потрібно вимагати ~ 6,64n ітерацій.
примо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.