পাইথন 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
চেক করতে সর্বাধিক সংখ্যার সংখ্যা স্টিডিন থেকে নেওয়া হয়। পাইপি 5.3 এর সাথে প্রায় 2 সেকেন্ডে 10,000 অঙ্কগুলি শেষ হয়।
নমুনা ব্যবহার
$ 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-এ চলেছি। চুদনোভস্কি আমার সিস্টেমে ১০০ মিলিয়ন অঙ্কের অল্প সময়ের মধ্যেই স্মৃতি হারিয়ে ফেললেন, তবে রামানুজন মাত্র ৩৮ মিনিটের মধ্যে এটিকে প্রায় ৪০০ মিলিয়নে পৌঁছে দিয়েছিলেন। আমি মনে করি এটি অন্য ক্ষেত্রে শর্তগুলির ধীরে ধীরে বৃদ্ধি হার ছিল, অন্তত সীমিত সংস্থান সহ একটি সিস্টেমে।
নমুনা ব্যবহার
$ 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
দ্রুত আনবাউন্ডেড জেনারেটর
সমস্যার বর্ণনায় প্রদত্ত রেফারেন্স বাস্তবায়ন আকর্ষণীয়। এটি আনবাউন্ডেড জেনারেটর ব্যবহার করে, পাই এর অঙ্কগুলির জন্য সরাসরি কাগজ আনবাউন্ডেড স্পিগোট অ্যালগরিদম থেকে নেওয়া । লেখকের মতে, প্রদত্ত বাস্তবায়নগুলি "ইচ্ছাকৃতভাবে অস্পষ্ট", সুতরাং আমি ইচ্ছাকৃত অবহেলা ছাড়াই লেখকের তালিকাভুক্ত তিনটি অ্যালগরিদমের নতুন করে বাস্তবায়ন করার সিদ্ধান্ত নিয়েছি। রামানুজন # 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
33 টি পুনরাবৃত্তি সহ প্রতি ব্যাচে 10 টি সংখ্যা উত্পন্ন করে। তবে এটি কেবল ~ 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)
দুর্ভাগ্য
হিসাবে গণনা করা হয়, প্রাথমিক (3528 ÷) রচনার কারণে শূন্য হয় না, তবে এটি এখনও জি 3 এর তুলনায় উল্লেখযোগ্যভাবে দ্রুত। রূপান্তরটি প্রতি শব্দ প্রতি 89 5.89 ডিজিট, একবারে 3511 ডিজিট উত্পন্ন হয়। যদি এটি কিছুটা বেশি হয় তবে 46 টি পুনরাবৃত্তির জন্য 271 ডিজিট উত্পন্ন করাও একটি শালীন পছন্দ।
s
সময়
আমার সিস্টেমে নেওয়া হয়েছে, কেবল তুলনার উদ্দেশ্যে। টাইমস সেকেন্ডে তালিকাভুক্ত করা হয়। যদি সময় নির্ধারণের সময় 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
প্রায় g3_ref
500,000 সংখ্যার উপর চাপিয়ে দেওয়ার চেয়ে প্রায় 235x দ্রুত । এটি বলেছিল, এইভাবে স্ট্রিমিং অঙ্কগুলিতে এখনও একটি উল্লেখযোগ্য ওভারহেড রয়েছে। সরাসরি রামানুজন 39 ( পাইথন উত্স ) ব্যবহার করে সমস্ত অঙ্কের গণনা করা প্রায় 10x হিসাবে দ্রুত।
চুদনভস্কি কেন নয়?
চুদনভস্কি অ্যালগরিদমের একটি সম্পূর্ণ নির্ভুলতা বর্গমূল প্রয়োজন, যা আমি কীভাবে কাজ করব তা সৎভাবে নিশ্চিত নই - ধরে নিই এটি আদৌ হতে পারে। রামানুজন 39 এক্ষেত্রে কিছুটা বিশেষ। তবে, পদ্ধতিটি মনে হচ্ছে এটি মেশিনের মতো সূত্রগুলির জন্য উপযুক্ত হতে পারে যেমন ওয়াই-ক্র্যাঙ্কারগুলি ব্যবহার করে, যাতে এটি অন্বেষণের মতো উপায় হতে পারে।