Обчислюючи усічені цифри суми повноважень 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.