generate random weigted string file in python - python

i'm trying to generate a string from characters of ['A','B','C','D','E'] with length of 3900, and every character should have probability of:
{'A':0.1,
'B':0.3,
'C':0.3,
'D':0.1,
'E':0.2 }
in this string
i wrote the following code:
from random import random
from bisect import bisect
def weighted_choice(choices):
values, weights = zip(*choices)
total = 0
cum_weights = []
for w in weights:
total += w
cum_weights.append(total)
x = random() * total
i = bisect(cum_weights, x)
return values[i]
string_ = ''
for i in range(0,3900):
string_ = string_ + weighted_choice([("A",10), ("B",30), ("C",30),("D",10),("E",20)])
with open("rand_file","w") as f:
f.write(string_)
but it doesn't generate the string(file) based on the probabilities. it generates with probabilities like this:
C 0.2500264583
B 0.2499284457
E 0.1666428313
D 0.0833782424
A 0.0833758065
probability cause the for loop runs separately every time, without considering previous results.
any help please to solve this problem ?

If you just use the list ['A','B','B','B','C','C','C','D','E','E'] and choose an item from it at random, you can get rid off all that weighting stuff in your code totally, and the weighting will be built in.
You can see that in the following example (yes, I don't doubt it could be written better but it's only meant to be a proof-of-concept, not production-ready, pure-as-snow-white code):
from random import random, seed
def choice(lst):
return lst[int(random() * len(lst))];
seed()
(a, b, c, d, e, t) = (0, 0, 0, 0, 0, 0)
for i in range(1000):
x = choice('ABBBCCCDEE')
if (x == 'A'): a += 1
if (x == 'B'): b += 1
if (x == 'C'): c += 1
if (x == 'D'): d += 1
if (x == 'E'): e += 1
t += 1
print ("a =", a, "which is", a * 100 / t, "%")
print ("b =", b, "which is", b * 100 / t, "%")
print ("c =", c, "which is", c * 100 / t, "%")
print ("d =", d, "which is", d * 100 / t, "%")
print ("e =", e, "which is", e * 100 / t, "%")
with the output matching (roughly) the desired distribution:
a = 101 which is 10.1 %
b = 297 which is 29.7 %
c = 299 which is 29.9 %
d = 102 which is 10.2 %
e = 201 which is 20.1 %
Now that's obviously going to be annoying if your distribution is 99.9% A and 0.1% B (it'll be a rather long string passed to choice) but this should be adequate for the distribution you have.

You can generate all letters according to the weighting, then randomly shuffle them and finally join them. Something like:
from random import shuffle
N = 3900 # the string length
doc = {'A':0.1, 'B':0.3, 'C':0.3, 'D':0.1, 'E':0.2 } #weights
letters = []
for key in doc.keys():
m = int(doc[key] * N) #generate correct number of letter
letters.append(list(key * m))
letters = [item for sublist in letters for item in sublist] # flatten the list
shuffle(letters) # shuffle all letters randomly
result = ''.join(letters) # join all letter to make one string
print(len(result))
# 3900

this is actually the same as paxdiablo's solution, except a little more general (for your simple example, his solution is better. +1):
import random
choice = [("A",10), ("B",30), ("C",30),("D",10),("E",20)]
choose_from = ''.join(x * letter for letter, x in choice)
print(choose_from)
# AAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDDetc...
print(random.choice(choose_from))

Related

How to take numbers from a .txt list and save the result in another .txt?

This script has a formula where at the beginning the numbers x1 and x2 in the code are set, and
I need to change the code so that the value x1 is taken from the list
pre-prepared text document
For example, from a document: 'List.txt'
That is, it turns out I need to enter:
with open ("List.txt '", "r") as f:
into place the value x1 = 6 in the code. But how to systematize it? Just not very rich in knowledge of Python.
List of numbers:
1
4
2
15
6
8
13
3
12
5
10
7
14
9
11
Code: (Powered by Python 2.7)
import sys
a=0
b=7
p=37
x1=6
x2=8
if (len(sys.argv)>1):
x1=int(sys.argv[1])
if (len(sys.argv)>2):
x2=int(sys.argv[2])
if (len(sys.argv)>3):
p=int(sys.argv[3])
if (len(sys.argv)>4):
a=int(sys.argv[4])
if (len(sys.argv)>5):
b=int(sys.argv[5])
def modular_sqrt(a, p):
""" Find a quadratic residue (mod p) of 'a'. p
must be an odd prime.
Solve the congruence of the form:
x^2 = a (mod p)
And returns x. Note that p - x is also a root.
0 is returned is no square root exists for
these a and p.
The Tonelli-Shanks algorithm is used (except
for some simple cases in which the solution
is known from an identity). This algorithm
runs in polynomial time (unless the
generalized Riemann hypothesis is false).
"""
# Simple cases
#
if legendre_symbol(a, p) != 1:
return 0
elif a == 0:
return 0
elif p == 2:
return p
elif p % 4 == 3:
return pow(a, (p + 1) / 4, p)
# Partition p-1 to s * 2^e for an odd s (i.e.
# reduce all the powers of 2 from p-1)
#
s = p - 1
e = 0
while s % 2 == 0:
s /= 2
e += 1
# Find some 'n' with a legendre symbol n|p = -1.
# Shouldn't take long.
#
n = 2
while legendre_symbol(n, p) != -1:
n += 1
x = pow(a, (s + 1) / 2, p)
b = pow(a, s, p)
g = pow(n, s, p)
r = e
while True:
t = b
m = 0
for m in xrange(r):
if t == 1:
break
t = pow(t, 2, p)
if m == 0:
return x
gs = pow(g, 2 ** (r - m - 1), p)
g = (gs * gs) % p
x = (x * gs) % p
b = (b * g) % p
r = m
def legendre_symbol(a, p):
""" Compute the Legendre symbol a|p using
Euler's criterion. p is a prime, a is
relatively prime to p (if p divides
a, then a|p = 0)
Returns 1 if a has a square root modulo
p, -1 otherwise.
"""
ls = pow(a, (p - 1) / 2, p)
return -1 if ls == p - 1 else ls
def egcd(a, b):
if a == 0:
return (b, 0, 1)
else:
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def modinv(a, m):
g, x, y = egcd(a, m)
if g != 1:
print ("x")
else:
return x % m
print "a=",a
print "b=",b
print "p=",p
print "x-point=",x1
print "x-point=",x2
z=(x1**3 + a*x1 +b) % p
y1=modular_sqrt(z, p)
z=(x2**3 + a*x2 +b) % p
y2=modular_sqrt(z, p)
print "\nP1\t(%d,%d)" % (x1,y1)
print "P2\t(%d,%d)" % (x2,y2)
s=((-y2)-y1)* modinv(x2-x1,p)
x3=(s**2-x2-x1) % p
y3=((s*(x2-x3)+y2)) % p
result = "Q\t(%d,%d)" % (x3,y3)
f = open('Result01.txt', 'w')
f.write(result)
f.close()
Earlier, I saw scripts where numbers are taken from one text document, perform a function, and the result is saved in another text document.
Try using the pandas library to read, process and write your numbers.
import pandas as pd # import pandas module and call it pd for short
x2 = 6
df = pd.read_csv('input_file.txt') # read the data from a text file into a dataframe
df['x1 times x2'] = df['x1'] * x2 # create new column in your dataframe with result of your function
df.to_csv('output_file.txt', index=False) # output result of your calculations (dropping the dataframe index column)
Although you're hard coding the values of x1, x2, in your code, they can be redefined, as you're doing here:
if (len(sys.argv)>1):
x1=int(sys.argv[1])
if (len(sys.argv)>2):
x2=int(sys.argv[2])
So if you call your script from command line, like C:\Users\test.py x1value x2value you can redefine x1 and x2. If you really want a text file to contain your x1 and x2, just use the following snippet somewhere at the top
import json
with open("input.json","r",encoding="utf-8") as stream:
parsed = json.load(stream)
x1,x2 = parsed["x1"],parsed["x2"]
Contents of "input.json":
{"x1":1,"x2"=2}
With only python without extra dependencies, your can read List.txt as follow
with open("List.txt","r") as f:
arrX1 = list(map(int,f.readlines()))
print (arrX1)
The above reads all the lines in f and converts/maps them to integers. The list function then gives you an array you can loop through to generate x2 and write to the Result.txt file.
The above prints
[1, 4, 2, 15, 6, 8, 13, 5, 3, 10, 7, 14, 9, 11]
So for your code replace all lines from 125 downward with
# Read numbers from file and put them in an array
with open("List.txt","r") as f:
arrX1 = list(map(int,f.readlines()))
f.close()
# Open the result file to write to
f = open('Result01.txt', 'w')
# Now get x1 for each item in the list of numbers from the file
# then do the calculations
# and write the result
for x1 in arrX1:
z=(x1**3 + a*x1 +b) % p
y1=modular_sqrt(z, p)
z=(x2**3 + a*x2 +b) % p
y2=modular_sqrt(z, p)
print "\nP1\t(%d,%d)" % (x1,y1)
print "P2\t(%d,%d)" % (x2,y2)
s=((-y2)-y1)* modinv(x2-x1,p)
x3=(s**2-x2-x1) % p
y3=((s*(x2-x3)+y2)) % p
result = "Q\t(%d,%d)" % (x3,y3)
f.write(result)
f.close()

Brute Force password generator for md5? [duplicate]

I would like to make a alphabetical list for an application similar to an excel worksheet.
A user would input number of cells and I would like to generate list.
For example a user needs 54 cells. Then I would generate
'a','b','c',...,'z','aa','ab','ac',...,'az', 'ba','bb'
I can generate the list from [ref]
from string import ascii_lowercase
L = list(ascii_lowercase)
How do i stitch it together?
A similar question for PHP has been asked here. Does some one have the python equivalent?
Use itertools.product.
from string import ascii_lowercase
import itertools
def iter_all_strings():
for size in itertools.count(1):
for s in itertools.product(ascii_lowercase, repeat=size):
yield "".join(s)
for s in iter_all_strings():
print(s)
if s == 'bb':
break
Result:
a
b
c
d
e
...
y
z
aa
ab
ac
...
ay
az
ba
bb
This has the added benefit of going well beyond two-letter combinations. If you need a million strings, it will happily give you three and four and five letter strings.
Bonus style tip: if you don't like having an explicit break inside the bottom loop, you can use islice to make the loop terminate on its own:
for s in itertools.islice(iter_all_strings(), 54):
print s
You can use a list comprehension.
from string import ascii_lowercase
L = list(ascii_lowercase) + [letter1+letter2 for letter1 in ascii_lowercase for letter2 in ascii_lowercase]
Following #Kevin 's answer :
from string import ascii_lowercase
import itertools
# define the generator itself
def iter_all_strings():
size = 1
while True:
for s in itertools.product(ascii_lowercase, repeat=size):
yield "".join(s)
size +=1
The code below enables one to generate strings, that can be used to generate unique labels for example.
# define the generator handler
gen = iter_all_strings()
def label_gen():
for s in gen:
return s
# call it whenever needed
print label_gen()
print label_gen()
print label_gen()
I've ended up doing my own.
I think it can create any number of letters.
def AA(n, s):
r = n % 26
r = r if r > 0 else 26
n = (n - r) / 26
s = chr(64 + r) + s
if n > 26:
s = AA(n, s)
elif n > 0:
s = chr(64 + n) + s
return s
n = quantity | r = remaining (26 letters A-Z) | s = string
To print the list :
def uprint(nc):
for x in range(1, nc + 1):
print AA(x,'').lower()
Used VBA before convert to python :
Function AA(n, s)
r = n Mod 26
r = IIf(r > 0, r, 26)
n = (n - r) / 26
s = Chr(64 + r) & s
If n > 26 Then
s = AA(n, s)
ElseIf n > 0 Then
s = Chr(64 + n) & s
End If
AA = s
End Function
Using neo's insight on a while loop.
For a given iterable with chars in ascending order. 'abcd...'.
n is the Nth position of the representation starting with 1 as the first position.
def char_label(n, chars):
indexes = []
while n:
residual = n % len(chars)
if residual == 0:
residual = len(chars)
indexes.append(residual)
n = (n - residual)
n = n // len(chars)
indexes.reverse()
label = ''
for i in indexes:
label += chars[i-1]
return label
Later you can print a list of the range n of the 'labels' you need using a for loop:
my_chrs = 'abc'
n = 15
for i in range(1, n+1):
print(char_label(i, my_chrs))
or build a list comprehension etc...
Print the set of xl cell range of lowercase and uppercase charterers
Upper_case:
from string import ascii_uppercase
import itertools
def iter_range_strings(start_colu):
for size in itertools.count(1):
for string in itertools.product(ascii_uppercase, repeat=size):
yield "".join(string)
input_colume_range = ['A', 'B']
input_row_range= [1,2]
for row in iter_range_strings(input_colume_range[0]):
for colum in range(int(input_row_range[0]), int(input_row_range[1]+1)):
print(str(row)+ str(colum))
if row == input_colume_range[1]:
break
Result:
A1
A2
B1
B2
In two lines (plus an import):
from string import ascii_uppercase as ABC
count = 100
ABC+=' '
[(ABC[x[0]] + ABC[x[1]]).strip() for i in range(count) if (x:= divmod(i-26, 26))]
Wrap it in a function/lambda if you need to reuse.
code:
alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
for i in range(len(alphabet)):
for a in range(len(alphabet)):
print(alphabet[i] + alphabet[a])
result:
aa
ab
ac
ad
ae
af
ag
ah
ai
aj
ak
al
am
...

How to make a continuous alphabetic list python (from a-z then from aa, ab, ac etc)

I would like to make a alphabetical list for an application similar to an excel worksheet.
A user would input number of cells and I would like to generate list.
For example a user needs 54 cells. Then I would generate
'a','b','c',...,'z','aa','ab','ac',...,'az', 'ba','bb'
I can generate the list from [ref]
from string import ascii_lowercase
L = list(ascii_lowercase)
How do i stitch it together?
A similar question for PHP has been asked here. Does some one have the python equivalent?
Use itertools.product.
from string import ascii_lowercase
import itertools
def iter_all_strings():
for size in itertools.count(1):
for s in itertools.product(ascii_lowercase, repeat=size):
yield "".join(s)
for s in iter_all_strings():
print(s)
if s == 'bb':
break
Result:
a
b
c
d
e
...
y
z
aa
ab
ac
...
ay
az
ba
bb
This has the added benefit of going well beyond two-letter combinations. If you need a million strings, it will happily give you three and four and five letter strings.
Bonus style tip: if you don't like having an explicit break inside the bottom loop, you can use islice to make the loop terminate on its own:
for s in itertools.islice(iter_all_strings(), 54):
print s
You can use a list comprehension.
from string import ascii_lowercase
L = list(ascii_lowercase) + [letter1+letter2 for letter1 in ascii_lowercase for letter2 in ascii_lowercase]
Following #Kevin 's answer :
from string import ascii_lowercase
import itertools
# define the generator itself
def iter_all_strings():
size = 1
while True:
for s in itertools.product(ascii_lowercase, repeat=size):
yield "".join(s)
size +=1
The code below enables one to generate strings, that can be used to generate unique labels for example.
# define the generator handler
gen = iter_all_strings()
def label_gen():
for s in gen:
return s
# call it whenever needed
print label_gen()
print label_gen()
print label_gen()
I've ended up doing my own.
I think it can create any number of letters.
def AA(n, s):
r = n % 26
r = r if r > 0 else 26
n = (n - r) / 26
s = chr(64 + r) + s
if n > 26:
s = AA(n, s)
elif n > 0:
s = chr(64 + n) + s
return s
n = quantity | r = remaining (26 letters A-Z) | s = string
To print the list :
def uprint(nc):
for x in range(1, nc + 1):
print AA(x,'').lower()
Used VBA before convert to python :
Function AA(n, s)
r = n Mod 26
r = IIf(r > 0, r, 26)
n = (n - r) / 26
s = Chr(64 + r) & s
If n > 26 Then
s = AA(n, s)
ElseIf n > 0 Then
s = Chr(64 + n) & s
End If
AA = s
End Function
Using neo's insight on a while loop.
For a given iterable with chars in ascending order. 'abcd...'.
n is the Nth position of the representation starting with 1 as the first position.
def char_label(n, chars):
indexes = []
while n:
residual = n % len(chars)
if residual == 0:
residual = len(chars)
indexes.append(residual)
n = (n - residual)
n = n // len(chars)
indexes.reverse()
label = ''
for i in indexes:
label += chars[i-1]
return label
Later you can print a list of the range n of the 'labels' you need using a for loop:
my_chrs = 'abc'
n = 15
for i in range(1, n+1):
print(char_label(i, my_chrs))
or build a list comprehension etc...
Print the set of xl cell range of lowercase and uppercase charterers
Upper_case:
from string import ascii_uppercase
import itertools
def iter_range_strings(start_colu):
for size in itertools.count(1):
for string in itertools.product(ascii_uppercase, repeat=size):
yield "".join(string)
input_colume_range = ['A', 'B']
input_row_range= [1,2]
for row in iter_range_strings(input_colume_range[0]):
for colum in range(int(input_row_range[0]), int(input_row_range[1]+1)):
print(str(row)+ str(colum))
if row == input_colume_range[1]:
break
Result:
A1
A2
B1
B2
In two lines (plus an import):
from string import ascii_uppercase as ABC
count = 100
ABC+=' '
[(ABC[x[0]] + ABC[x[1]]).strip() for i in range(count) if (x:= divmod(i-26, 26))]
Wrap it in a function/lambda if you need to reuse.
code:
alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]
for i in range(len(alphabet)):
for a in range(len(alphabet)):
print(alphabet[i] + alphabet[a])
result:
aa
ab
ac
ad
ae
af
ag
ah
ai
aj
ak
al
am
...

What's wrong with my Extended Euclidean Algorithm (python)?

My algorithm to find the HCF of two numbers, with displayed justification in the form r = a*aqr + b*bqr, is only partially working, even though I'm pretty sure that I have entered all the correct formulae - basically, it can and will find the HCF, but I am also trying to provide a demonstration of Bezout's Lemma, so I need to display the aforementioned displayed justification. The program:
# twonumbers.py
inp = 0
a = 0
b = 0
mul = 0
s = 1
r = 1
q = 0
res = 0
aqc = 1
bqc = 0
aqd = 0
bqd = 1
aqr = 0
bqr = 0
res = 0
temp = 0
fin_hcf = 0
fin_lcd = 0
seq = []
inp = input('Please enter the first number, "a":\n')
a = inp
inp = input('Please enter the second number, "b":\n')
b = inp
mul = a * b # Will come in handy later!
if a < b:
print 'As you have entered the first number as smaller than the second, the program will swap a and b before proceeding.'
temp = a
a = b
b = temp
else:
print 'As the inputted value a is larger than or equal to b, the program has not swapped the values a and b.'
print 'Thank you. The program will now compute the HCF and simultaneously demonstrate Bezout\'s Lemma.'
print `a`+' = ('+`aqc`+' x '+`a`+') + ('+`bqc`+' x '+`b`+').'
print `b`+' = ('+`aqd`+' x '+`a`+') + ('+`bqd`+' x '+`b`+').'
seq.append(a)
seq.append(b)
c = a
d = b
while r != 0:
if s != 1:
c = seq[s-1]
d = seq[s]
res = divmod(c,d)
q = res[0]
r = res[1]
aqr = aqc - (q * aqd)#These two lines are the main part of the justification
bqr = bqc - (q * aqd)#-/
print `r`+' = ('+`aqr`+' x '+`a`+') + ('+`bqr`+' x '+`b`+').'
aqd = aqr
bqd = bqr
aqc = aqd
bqc = bqd
s = s + 1
seq.append(r)
fin_hcf = seq[-2] # Finally, the HCF.
fin_lcd = mul / fin_hcf
print 'Using Euclid\'s Algorithm, we have now found the HCF of '+`a`+' and '+`b`+': it is '+`fin_hcf`+'.'
print 'We can now also find the LCD (LCM) of '+`a`+' and '+`b`+' using the following method:'
print `a`+' x '+`b`+' = '+`mul`+';'
print `mul`+' / '+`fin_hcf`+' (the HCF) = '+`fin_lcd`+'.'
print 'So, to conclude, the HCF of '+`a`+' and '+`b`+' is '+`fin_hcf`+' and the LCD (LCM) of '+`a`+' and '+`b`+' is '+`fin_lcd`+'.'
I would greatly appreciate it if you could help me to find out what is going wrong with this.
Hmm, your program is rather verbose and hence hard to read. For example, you don't need to initialise lots of those variables in the first few lines. And there is no need to assign to the inp variable and then copy that into a and then b. And you don't use the seq list or the s variable at all.
Anyway that's not the problem. There are two bugs. I think that if you had compared the printed intermediate answers to a hand-worked example you should have found the problems.
The first problem is that you have a typo in the second line here:
aqr = aqc - (q * aqd)#These two lines are the main part of the justification
bqr = bqc - (q * aqd)#-/
in the second line, aqd should be bqd
The second problem is that in this bit of code
aqd = aqr
bqd = bqr
aqc = aqd
bqc = bqd
you make aqd be aqr and then aqc be aqd. So aqc and aqd end up the same. Whereas you actually want the assignments in the other order:
aqc = aqd
bqc = bqd
aqd = aqr
bqd = bqr
Then the code works. But I would prefer to see it written more like this which is I think a lot clearer. I have left out the prints but I'm sure you can add them back:
a = input('Please enter the first number, "a":\n')
b = input('Please enter the second number, "b":\n')
if a < b:
a,b = b,a
r1,r2 = a,b
s1,s2 = 1,0
t1,t2 = 0,1
while r2 > 0:
q,r = divmod(r1,r2)
r1,r2 = r2,r
s1,s2 = s2,s1 - q * s2
t1,t2 = t2,t1 - q * t2
print r1,s1,t1
Finally, it might be worth looking at a recursive version which expresses the structure of the solution even more clearly, I think.
Hope this helps.
Here is a simple version of Bezout's identity; given a and b, it returns x, y, and g = gcd(a, b):
function bezout(a, b)
if b == 0
return 1, 0, a
else
q, r := divide(a, b)
x, y, g := bezout(b, r)
return y, x - q * y, g
The divide function returns both the quotient and remainder.
The python program that does what you want (please note that extended Euclid algorithm gives only one pair of Bezout coefficients) might be:
import sys
def egcd(a, b):
if a == 0:
return (b, 0, 1)
g, y, x = egcd(b % a, a)
return (g, x - (b // a) * y, y)
def main():
if len(sys.argv) != 3:
's program caluclates LCF, LCM and Bezout identity of two integers
usage %s a b''' % (sys.argv[0], sys.argv[0])
sys.exit(1)
a = int(sys.argv[1])
b = int(sys.argv[2])
g, x, y = egcd(a, b)
print 'HCF =', g
print 'LCM =', a*b/g
print 'Bezout identity: %i * (%i) + %i * (%i) = %i' % (a, x, b, y, g)
main()

1000 digits of pi in Python

I have been thinking about this issue and I can't figure it out. Perhaps you can assist me. The problem is my code isn't working to output 1000 digits of pi in the Python coding language.
Here's my code:
def make_pi():
q, r, t, k, m, x = 1, 0, 1, 1, 3, 3
while True:
if 4 * q + r - t < m * t:
yield m
q, r, t, k, m, x = (10*q, 10*(r-m*t), t, k, (10*(3*q+r))//t - 10*m, x)
else:
q, r, t, k, m, x = (q*k, (2*q+r)*x, t*x, k+1, (q*(7*k+2)+r*x)//(t*x), x+2)
digits = make_pi()
pi_list = []
my_array = []
for i in range(1000):
my_array.append(str("hello, I'm an element in an array \n" ))
big_string = "".join(my_array)
print "here is a big string:\n %s" % big_string
I know this code can be fixed to work, but I'm not sure what to fix... The print statement saying here is a big string and the my_array.append(str("hello, im an element in an array \n)) is just a filler for now. I know how all the code is used to work, but like I said before, I can't get it to shoot out that code.
If you don't want to implement your own algorithm, you can use mpmath.
try:
# import version included with old SymPy
from sympy.mpmath import mp
except ImportError:
# import newer version
from mpmath import mp
mp.dps = 1000 # set number of digits
print(mp.pi) # print pi to a thousand places
Reference
Update: Code supports older and newer installations of SymPy (see comment).*
Run this
def make_pi():
q, r, t, k, m, x = 1, 0, 1, 1, 3, 3
for j in range(1000):
if 4 * q + r - t < m * t:
yield m
q, r, t, k, m, x = 10*q, 10*(r-m*t), t, k, (10*(3*q+r))//t - 10*m, x
else:
q, r, t, k, m, x = q*k, (2*q+r)*x, t*x, k+1, (q*(7*k+2)+r*x)//(t*x), x+2
my_array = []
for i in make_pi():
my_array.append(str(i))
my_array = my_array[:1] + ['.'] + my_array[1:]
big_string = "".join(my_array)
print "here is a big string:\n %s" % big_string
And read about yield operator from here:
What does the "yield" keyword do?
Here is the answer:
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337
The accepted answer is incorrect, as noted in comments.
The OP's code appears to be based on an implementation of Spigot's algorithm copied from here.
To fix the code per the OP's question (although I renamed the variables and functions to match what they were in the original source), one solution might be:
#!/usr/bin/env python
DIGITS = 1000
def pi_digits(x):
"""Generate x digits of Pi."""
q,r,t,k,n,l = 1,0,1,1,3,3
while x >= 0:
if 4*q+r-t < x*t:
yield n
x -= 1
q,r,t,k,n,l = 10*q, 10*(r-n*t), t, k, (10*(3*q + r))/t-10*n, l
else:
q,r,t,k,n,l = q*k, (2*q+r)*l, t*l, k+1, (q*(7*k+2)+r*l)/(t*l), l+2
digits = [str(n) for n in list(pi_digits(DIGITS))]
print("%s.%s\n" % (digits.pop(0), "".join(digits)))
Also, here is a much faster* implementation, also apparently based on Spigot's algorithm:
#!/usr/bin/env python
DIGITS = 1000
def pi_digits(x):
"""Generate x digits of Pi."""
k,a,b,a1,b1 = 2,4,1,12,4
while x > 0:
p,q,k = k * k, 2 * k + 1, k + 1
a,b,a1,b1 = a1, b1, p*a + q*a1, p*b + q*b1
d,d1 = a/b, a1/b1
while d == d1 and x > 0:
yield int(d)
x -= 1
a,a1 = 10*(a % b), 10*(a1 % b1)
d,d1 = a/b, a1/b1
digits = [str(n) for n in list(pi_digits(DIGITS))]
print("%s.%s\n" % (digits.pop(0), "".join(digits)))
I tested both a few times against this online Pi digit generator.
All credit to this Gist by deeplook.
* Based on testing 10,000 digits, where I got about 7 seconds compared to about 1 second.
For up to 1 million digits of pi use math_pi (note: I am the author of the module)
Install with pip:
pip install math-pi
In Python:
>>> import math_pi
>>> print(math_pi.pi(b=1000))
3.1415926535...
From Fabrice Bellard site: Pi Computation algorithm. Sorry for such a straightforward implementation. 1000 is fast enough (0.1s for me), but 10000 isn't such fast - 71s :-(
import time
from decimal import Decimal, getcontext
def compute(n):
getcontext().prec = n
res = Decimal(0)
for i in range(n):
a = Decimal(1)/(16**i)
b = Decimal(4)/(8*i+1)
c = Decimal(2)/(8*i+4)
d = Decimal(1)/(8*i+5)
e = Decimal(1)/(8*i+6)
r = a*(b-c-d-e)
res += r
return res
if __name__ == "__main__":
t1 = time.time()
res = compute(1000)
dt = time.time()-t1
print(res)
print(dt)
I was solved with bellow formula 5-6 years ago.
Machin-like formula
Wikipedia: https://en.wikipedia.org/wiki/Machin-like_formula
Sorry for the code quality. Variable names can be meaningless.
#-*- coding: utf-8 -*-
# Author: Fatih Mert Doğancan
# Date: 02.12.2014
def arccot(x, u):
sum = ussu = u // x
n = 3
sign = -1
while 1:
ussu = ussu // (x*x)
term = ussu // n
if not term:
break
sum += sign * term
sign = -sign
n += 2
return sum
def pi(basamak):
u = 10**(basamak+10)
pi = 4 * (4*arccot(5,u) - arccot(239,u))
return pi // 10**10
if __name__ == "__main__":
print pi(1000) # 1000
I'm not familiar with your algorithm. Is it an implementation of BBP?
In any case, your make_pi is a generator. Try using it in a for loop:
for digit in make_pi():
print digit
Note that this loop is infinite: make_pi() never throws StopIteration
Here you can check whether your program outputs correct 1000 digits:
http://spoj.com/CONSTANT
Of course you can use diff or tc as well but you'd have to copy these 1000 digits from somewhere and there you just submit your program and check whether the score is bigger than 999.
You can try to print even more digits there and thus get more points. Perhaps you'd enjoy it.
Does this do what you want?
i = 0;
pi_str = ""
for x in make_pi():
pi_str += str(x)
i += 1
if i == 1001:
break
print "pi= %s.%s" % (pi_str[0],pi_str[1:])
Here is a different way I found here --> Python pi calculation? to approximate python based on the Chudnovsky brothers formula for generating Pi which I have sightly modified for my program.
def pifunction():
numberofdigits = int(input("please enter the number of digits of pi that you want to generate"))
getcontext().prec = numberofdigits
def calc(n):
t = Decimal(0)
pi = Decimal(0)
deno = Decimal(0)
k = 0
for k in range(n):
t = (Decimal(-1)**k)*(math.factorial(Decimal(6)*k))*(13591409+545140134*k)
deno = math.factorial(3*k)*(math.factorial(k)**Decimal(3))*(640320**(3*k))
pi += Decimal(t)/Decimal(deno)
pi = pi * Decimal(12)/Decimal(640320**Decimal(1.5))
pi = 1/pi
return str(pi)
print(calc(1))
I hope this helps as you can generate any number of digits of pi that you wish to generate.
wallis formula can get to 3.141592661439964 but a more efficient way is needed to solve this problem.
https://www.youtube.com/watch?v=EZSiQv_G9HM
and now my code
x, y, summing = 2, 3, 4
for count in range (0,100000000):
summing *= (x/y)
x += 2
summing *= (x/y)
y += 2
print (summing)

Categories

Resources