python

Python: Calculating pi using random numbers

During my undergraduate degree I wrote a program in fortran 95 to calculate pi using random numbers. My aim is to rewrite it efficiently in python. I know its a terrible way to calculate pi, and there are much better ways to do it but its fun!

First I’ll explain the maths so you can visualise what’s going on. As we should know _pi_ is the ratio of circle’s radius to its circumference, which is conveniently the same as the ratio of a circle’s area to the square of its radius (wiki…)

So what we are going to be doing is picking lots of random coordinates in an x-y grid and calculating if they are within the circle or the square.
python-pi-random-numbers-1
We will assign the radius to be 1, because that makes it easy to work with. By default a random number in python ( random() ) will return a floating point number between 0 and 1. To test if a point is within a circle we simply use Pythagoras.

So if the sqrt(a**2+b**2)<=1 then the point lies inside the circle’s radius. In the diagram above we see that point A lies within the circle, and point B lies outside the circle.

We can really don’t need to use the whole circle as it has symmetry, so we can just take a quartre, which makes the generating of random numbers easier as you only need to use a random number for x and y between 0 and 1, rather than -1 and 1. It will look like the diagram below.

python-pi-random-numbers-2

Now for a confusing bit of maths. We are calculating the ratio of the area of a circle to the area of a square.

# Area of circle
A=pi*r**2
# where r = 1
A = pi
# Area of square
A = l ** 2
# in this case (see diagram) our square's length is twice the radius
l=2*r
A=(1+1)**2 = 4

#Therefore our ratio will be pi : 4.
# Which means we must multiply our result by four to get pi.

Final version (efficient for using)

from random import *
from math import sqrt
inside=0
n=1000
for i in range(0,n):
	x=random()
	y=random()
	if sqrt(x*x+y*y)<=1:
		inside+=1
pi=4*inside/n
print pi

Below we can see the values it creates

n	calc	error
1	4.00000000	0.73686317
10	3.60000000	0.45840735
100	3.24000000	0.09840735
1000	3.06400000	-0.07759265
10000	3.16160000	0.02000735
100000	3.14140000	-0.00019265
1000000	3.14293600	0.00134335
10000000	3.14117920	-0.00041345

pi-random-number-error

So we can see that the program quickly solves pi to about two decimal places, but it is a terribly inefficient method and will struggle to get much more accuracy than this.

Resources to check out:
This blog post – Solves pi via taylor series expansion
Super pi – Program that calculate pi often used for benchmarking

Read More

Python: palindrome checking function

I created a reasonable palindrome checking function in python.

Method 1

def ispalindrome(num):
	n=str(num)
	while len(n)>1:
		print n
		if n[0]!=n[-1]:
			return 0
		n=n[1:-1]
	return 1

I thought that it would be faster avoiding a string conversion, and to somehow use the modulus (modulo) function. However when I came to write it, I found it quite difficult to code, and I’m sure there must be a better way.

Method 2

def ispalindrome2(num):
	l=1
	while num/10**l>=1.0:
		l+=1
	r=0
	d=[]
	for i in range(1,l+1):
		p=num%10**i-r
		r+=p
		p=p/10**(i-1)
		d.append(p)
	
	for i in range(0,l/2):
		if d[i]!=d[-i-1]:
			return 0
	return 1

Doing the speed tests show that Method 1 is over 5.2 times faster than Method 2.

Method 1
0.355437994003 Seconds elapsed
Method 2
1.85815691948 Seconds elapsed

Update: Mike of mikemeat sent me his method using slices (Method 3) and I adapted it slight (Method 4), then shortly after I realised it could be even more efficient by not needing to differentiate between even and odd strings (Method 5).

Method 3

def ispalindrome3(x):
    z = str(x)
    if len(z)%2 == 0 and z[:len(z)/2]==z[-len(z)/2:][::-1]: 
       return 1
    if len(z)%2 != 0 and z[:(len(z)- 1)/2]==z[(-len(z) + 1)/2:][::-1]: 
       return 1
    else:
	return 0

Method 4

def ispalindrome4(x):
	z = str(x)
	if z[:len( z)/2]==z[len( z)/2+len( z)%2:][::-1]:
		return 1    
	return 0

Method 5

def ispalindrome5(x):
	z = str(x)
	l=len(z)/2
	if z[:l]==z[-l:][::-1]:
		return 1    
	return 0
Method 1
0.357168912888 Seconds elapsed
Method 2
1.83943104744 Seconds elapsed
Method 3
0.179126977921 Seconds elapsed
Method 4
0.179482936859 Seconds elapsed
Method 5
0.149376153946 Seconds elapsed

Read More

Python: sum of digits in a string

I have a function I wrote for a project euler that calculates the sum of the digits in a number. This is my first attempt which simply converts each letter to an integer and sums them.

Method 1:

def digitsum(x):
	total=0
	for letter in str(x):
		total+=int(letter)
	return total

I thought that this could be improved using ord, which converts a letter into its decimal ascii number. Numbers ‘0’, ‘1’, ‘2’ … ‘9’ correspond to the ascii values of 48 – 57 and then took the moduli of this with 48 to give the integer value. I later realised that this was completely nonsensical and should have just subtracted 48, but I decided to include it for the purposes of the speed test.

Method 2:

def digitsum2(x):
	total=0
	for letter in str(x):
		total+=ord(letter)%48
	return total 

Method 3:

def digitsum3(x):
	total=0
	for letter in str(x):
		total+=ord(letter)-48
	return total 

Speed Test:
The test uses a long number and one million repetitions for each method.

from time import time

# .. functions go here

# Nice long number to sum
x=981234153134415646571899783156122451653

tic = time()
for i in range(0,1000000):
	digitsum(x)
print time() - tic, 'Seconds elapsed'

tic = time()
for i in range(0,1000000):
	digitsum2(x)
print time() - tic, 'Seconds elapsed'

tic = time()
for i in range(0,1000000):
	digitsum3(x)
print time() - tic, 'Seconds elapsed'

Results:

#Method 1
29.3496568203 Seconds elapsed
#Method 2
12.185685873 Seconds elapsed
#Method 3
9.59367895126 Seconds elapsed

So we can see that the first method is much slower, avoiding the integer conversion by using ord speeds it up the function by ~60% and that using subtraction rather than modulus (a division based operation) saves a further ~20% on top of this.

Read More

Python: crossword solver + dictionary file

This is a quick and dirty crossword solver that I wrote in python:

word=raw_input('Crossword Solver \nuse * as a wildcard: ')
f=open('dic.txt', 'r')
for line in f:
	line=line.strip()
        if len(line)==len(word):
		good=1
		pos=0
		for letter in word:
			if not letter=='*':
				if not letter==line[pos]:
					good=0
			pos+=1
		if good==1:
			print line
f.close()

Example usage:

Crossword Solver
use * as a wildcard: *arn*val
carnival

The dictionary file I used is 608.2Kb with 80,368 english words and avaliable here

Read More

Python: diskspace

I wanted a simple function to use in a program I am writing to ensure that the disk isn’t getting full, after a quick search I found a blog post on thinkhole.org with a great solution:

# os module required
import os

# retrieves information for the harddrive where root is mounted
# in windows replace this with "C:\" or the relevant drive letter
disk = os.statvfs("/")

# Information is recieved in numbers of blocks free
# so we need to multiply by the block size to get the space free in bytes
capacity = disk.f_bsize * disk.f_blocks
available = disk.f_bsize * disk.f_bavail
used = disk.f_bsize * (disk.f_blocks - disk.f_bavail) 

# print information in bytes
print used, available, capacity

# print information in Kilobytes
print used/1024, available/1024, capacity/1024

# print information in Megabytes
print used/1.048576e6, available/1.048576e6, capacity/1.048576e6

# print information in Gigabytes
print used/1.073741824e9, available/1.073741824e9, capacity/1.073741824e9

You can argue about if they should be KiB or KB if you want, but i take them as 1024 bytes in a kilobyte

Read More

Python: Checking if a number is prime

I’ve been doing a lot of problem solving on Project Euler recently. If your not aware of Project Euler (PE) it is a website with lots of maths / programming based puzzles to solve. Many of the problems involve using or checking prime numbers, in many cases a sieve method would be applicable (see: Sieve of Eratosthenes for a clear explanation / animation).

However sometimes this is not necessary if you only require one prime number, or if memory limitations mean a sieve would be inconceivable. The following is the code I wrote to check if a number is prime or not in python. It tests upwards checking if the number is perfectly divisble, and as it does this it lowers the maximum number need to reach to stop as we know that if a number is not divisible by 2 then it will not be uniquely divisible (a repatition of a divislbe may exist) by anything greater than N/2

def isprime(number):
	if number<=1:
		return 0
	check=2
	maxneeded=number
	while check<maxneeded+1:
		maxneeded=number/check
		if number%check==0:
			return 0
		check+=1
	return 1

I hope that this made sense, and is useful to someone. If anyone has any more efficient methods I would be happy to hear from you.

Check out my profile to see which problems I’ve completed. If you’ve completed any I haven’t please get in contact and give me some tips.

Update:
Mike sent a suggestion that I could speed up the program by ignoring all factors of 2, it could also propbably be sped up by looking at 3,4,5 .. etc until certain point.

def isprime(number):
	if number<=1 or number%2==0:
		return 0
	check=3
	maxneeded=number
	while check<maxneeded+1:
		maxneeded=number/check
		if number%check==0:
			return 0
		check+=2
	return 1

So lets test the speed difference by doing 1,000 checks of the number 982,451,653 (known to be prime from this usefulsite)

Original Code: 9.99917411804 Seconds elapsed
Improved Code: 5.2977039814 Seconds elapsed

That’s approximately a factor of two speed increase, but this makes me think that a combination of the sieve method with this one may lead to an even further increase.

Read More