Python
"What I can not create, I do not understand."
- Richard Feynman
My Core Strategist role with JP Morgan involves broadly large scale development on Python, wx and grid computing. Some misc code snippets doing random fun stuff below...
Rolls of Dice
Problem : Given n dice, find all combination of rolls that sum to x
Solution : def pairs(nd, s): return [e for e in [map(lambda x,y:y/x %
6 + 1, [(6**(i)) for i in range(0, nd)], v ) for v in [[r]*nd for r in range(
6**nd )] ] if sum(e) == s]
Examples :
>>> pairs(3, 6)
[[4, 1, 1], [3, 2, 1], [2, 3, 1], [1, 4, 1], [3, 1, 2], [2, 2, 2], [1, 3, 2], [2, 1, 3], [1, 2, 3], [1, 1, 4]]
>>> pairs(2, 8)
[[6, 2], [5, 3], [4, 4], [3, 5], [2, 6]]
Recursive Image Rotate
An surprising (though not the most practical) application of recursion to the rotation for images by 90 degrees. For a n x n image (where n is a power of 2), rotating it can be achieved by splitting it into 4 quadrants of equal size n/2 x n/2, moving them to their destination positions, and the recursively applying this rotation process to the 4 subimages of n/2 x n/2. The following picture provides a visualization of the process,
A step by step sample run of the above algorithm is shown in the image sequence below,
The following python code is a straight forward implementation of the above recursive algorithm. It only supports square images of n x n where n is a power of 2. However it's straightforward to extend to arbitrary sizes by extending the non-square image to the next smallest square size, rotating it, then clipping back the smaller rotated image.
import wx
import operator
import collections
import Image
origins = [ (0, 0), (1, 0), (1, 1), (0, 1) ]
offset = (10, 30)
stops = [ 2**(i*2) for i in range(1, 10) ]
f = lambda r : (r.x, r.y)
class BitmapButtonFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, -1, 'Recursive Bitmap Rotate', size=(300, 320))
self.panel = wx.Panel(self, -1)
self.pilImage= Image.open("logo.jpg")
self.boxFromRect = lambda r : (r.x, r.y, r.x + r.Width, r.y + r.Height)
self.button = wx.BitmapButton(self.panel, -1, self.wxBitmapFromPILImage(self.pilImage), pos=offset, style=wx.BORDER_NONE)
self.rects = [wx.Rect(0, 0, self.pilImage.size[0], self.pilImage.size[1])]
self.image_sequence = self.rotateImage()
m_close = wx.Button(self.panel, -1, "Step")
m_close.Bind(wx.EVT_BUTTON, self.OnStep)
def rotateImage(self):
if self.rects[0].Width > 1:
for r in self.rects:
rects = self.splitRect(r)
boxes = map(self.boxFromRect, rects)
subimages = [ self.pilImage.crop(b) for b in boxes ]
map( lambda x: x.load() , subimages )
d = collections.deque(subimages)
d.rotate()
for s, r in zip( d, rects ):
self.pilImage.paste(s, f( r.GetTopLeft() ) )
l = []
for r in self.rects:
l.extend( self.splitRect(r) )
self.rects = l
yield self.pilImage
for i in self.rotateImage(): yield self.pilImage
def wxBitmapFromPILImage(self, pilImage):
wimage = wx.EmptyImage(pilImage.size[0],pilImage.size[1])
wimage.SetData(pilImage.convert("RGB").tostring())
return wx.BitmapFromImage(wimage)
def updateUI(self):
img = self.image_sequence.next()
wx.BitmapButton(self.panel, -1, self.wxBitmapFromPILImage(img), pos=offset, style=wx.BORDER_NONE)
def OnStep(self, event):
self.updateUI()
def splitRect(self, rect):
nw = rect.Width >> 1
neworigins = [ map(operator.add, map(operator.mul, x, [nw] * 2), (rect.x, rect.y) ) for x in origins ]
return [ wx.Rect(x[0], x[1], nw, nw) for x in neworigins]
app = wx.PySimpleApp()
frame = BitmapButtonFrame()
frame.Show()
app.MainLoop()
|
Reconstruct Binary Tree from it's traversal sequences
Short python code for tree construction from it's preorder and postorder node sequences. We use the following sample tree for our example,
import pprint
pre = ['F', 'B', 'A', 'D', 'C', 'E', 'G', 'I', 'H']
post = ['A', 'C', 'E', 'D', 'B', 'H', 'I', 'G', 'F']
sample = {'F' : [
{ 'B' : [
{ 'A' : [] },
{ 'D' : [
{ 'C':[]},
{ 'E':[]}
]
}
]},
{ 'G' : [
{},
{ 'I': [
{ 'H':[] },
{}
]
}
]
}
]
}
def buildtree(pre, post):
if len(pre) == 0: return {}
elif len(pre) == 1: return { pre[0]:[] }
elif len(post) == 0: return { pre[0] : [buildtree( pre[1:],[]), {}] }
cur, lc, rc = pre[0], pre[1], post[-2]
ipostlc, iprerc = post.index(lc), pre.index(rc)
postleft, postright, preleft, preright = post[:ipostlc + 1], post[ipostlc + 1:-1], pre[1:iprerc], pre[iprerc:]
return { cur :[ buildtree(preleft, postleft),
buildtree(preright, postright) ] }
root = buildtree(pre, post)
pprint.pprint(root)
pprint.pprint(sample) |
Output :
{'F': [{'B': [{'A': []}, {'D': [{'C': []}, {'E': []}]}]},
{'G': [{}, {'I': [{'H': []}, {}]}]}]}
{'F': [{'B': [{'A': []}, {'D': [{'C': []}, {'E': []}]}]},
{'G': [{}, {'I': [{'H': []}, {}]}]}]}
How python makes it so easy!
import os
dir='/home/pix/code/webservice'
def print_tree( node, prefix = '', isLastNode = True, isInitialNode = True ):
own_prefix = '`- ' if isLastNode else '+- '
if prefix:
x, y = prefix[:-3], prefix[-3:]
if y == '+- ':
cur_prefix = x + '| ' + own_prefix
else:
cur_prefix = x + ' ' + own_prefix
else:
cur_prefix = own_prefix
if isInitialNode:
print cur_prefix + node
else:
print cur_prefix + node.rsplit('/', 1)[-1]
if os.path.isdir(node):
dirFiles = sorted(os.listdir(node))
if dirFiles:
for f in dirFiles[:-1]:
print_tree(node+'/'+f, prefix = cur_prefix, isLastNode = False, isInitialNode=False )
print_tree(node+'/'+dirFiles[-1], prefix = cur_prefix, isLastNode = True, isInitialNode=False )
print_tree(dir)
|
Output :
`- /home/pix/code/webservice
+- test1
| +- StockQuoteImpl.ja
| +- StockQuoteImpl.java~
| +- build
| +- build.xml
| +- build.xml~
| +- src
| | +- StockQuoteImpl.java~
| | +- main
| | | `- generated
| | | `- server
| | | `- wtp
| | | `- jaxws
| | | +- GetQuote.java
| | | `- GetQuoteResponse.java
| | `- wtp
| | `- StockQuoteImpl.java
| +- target
| | `- classes
| | `- wtp
| | +- StockQuoteImpl.class
| | `- jaxws
| | +- GetQuote.class
| | `- GetQuoteResponse.class
| +- webapp
| | `- WEB-INF
| | `- wsdl
| | +- StockQuoteService.wsdl
| | `- StockQuoteService_schema1.xsd
| `- wsexample.tar.gz
`- test2
+- jaxwstutorial
| +- .classpath
| +- .project
| +- build.xml
| +- local.properties
| `- src
| +- main
| | +- java
| | | `- com
| | | `- wakaleo
| | | `- tutorials
| | | `- webservices
| | | +- client
| | | | `- StockQuoteClient.java
| | | `- server
| | | `- StockQuoteImpl.java
| | +- test
| | | `- com
| | | `- wakaleo
| | | `- tutorials
| | | `- webservices
| | `- webapp
| | `- WEB-INF
| | +- sun-jaxws.xml
| | +- web.xml
| | `- wsdl
| | +- StockQuoteService.wsdl
| | `- StockQuoteService_schema1.xsd
| `- test
`- jaxwstutorial.zip
Dynamic programming
Finding the largest sum of elements in a contiguous subarrary A[i..j]. It showcases both and O(mn) space as well as a O(m) space algorithm. Using the operator module with a template pattern also makes it very easy to choose between computing the largest or the smallest sum.
import numpy
import sys
import operator
l = [ -6, 12, -7, 0, 14, -7, 5 ]
#l = [ 7, 3, 11, 9, 10 ]
def mnspace(sentinel = -sys.maxint - 1, op=operator.gt, desc='largest' ):
a = numpy.array( numpy.arange( 0, len( l )**2 ) )
a = a.reshape( len( l ), len( l ) )
a.fill( 0 )
a[ 0, 0 ] = l[ 0 ]
sen = sentinel
for y in xrange( 0, len( l ) ):
a[y, y] = l[y]
if op( a[y, y], sen ): #if a[x, y] > max:
sen = a[y, y]
for x in xrange( y + 1, len( l ) ):
a[x, y] = a[x-1, y] + l[x]
if op( a[x, y], sen ): #if a[x, y] > max:
sen = a[x, y]
print '%s sum of of elements in a contiguous subarray : %s' % ( desc, sen )
print 'DP Table,\n %s' % a
def mspace(sentinel = -sys.maxint - 1, op=operator.gt, desc='largest' ):
a = numpy.array( numpy.arange( 0, len( l ) ) )
a.fill( 0 )
sen = sentinel
for y in xrange( 0, len( l ) ):
a[y] = l[y]
if op( a[y], sen ): #if a[x] > max:
sen = a[y]
for x in xrange( y + 1, len( l ) ):
a[x] = a[x-1] + l[x]
if op( a[x], sen ): #if a[x] > max:
sen = a[x]
print '%s sum of of elements in a contiguous subarray : %s' % ( desc, sen )
print 'DP Table,\n %s' % a
def main():
mnspace()
mspace()
mnspace(sys.maxint, operator.lt, 'smallest')
mspace(sys.maxint, operator.lt, 'smallest')
|
WeirdStack
This one came from some random brain teaser. The aim is to implement a stack that allow the 2nd largest element contained in the stack to be queried in constant time, and at the same time keep push and pop operations also in constant time. Python again makes the task much easier with dynamic typing.
import copy
import exceptions
import random
class WeirdStack ():
''' stack that supports the 2nd largest element query in constant time.'''
def __init__(self):
self.stack = []
self.second = -1 # 2nd largest
self.max = -1 # max
def push_update(self, newvalue):
update = None
oldsecond = self.second
oldmax = self.max
if newvalue > self.max:
self.second = self.max
self.max = newvalue
update = (oldsecond, oldmax)
elif newvalue < self.max:
if self.second < newvalue:
self.second = newvalue
update = (oldsecond, -1)
# if there is an update we need a sentinel entry in the stack storing the previous value
# we need to restore the old value on pop
if update:
self.stack.append( update )
def second_max(self):
return self.second
def push(self, n):
if len( self.stack ) >= 1:
self.push_update( n )
else:
if n > self.max:
self.max = n
self.stack.append( n )
def pop(self):
top_element = self.stack.pop()
if len( self.stack ) > 0:
if isinstance( self.stack[-1], tuple ):
update = self.stack.pop()
self.second = update[0]
if update[1] > 0:
self.max = update[1]
return top_element
def sorted_sequence(self):
t = copy.copy( self.stack )
t = [ i for i in t if isinstance( i, int ) ]
t.sort()
return t
# testing that our implemention is okay
for j in xrange(1000):
s = WeirdStack()
input = random.sample(xrange(100), 10)
print 'Input sequence : %s' % input
print 'Commence push'
for i in input:
s.push(i)
ss = s.sorted_sequence()
so = [ i for i in s.stack if isinstance( i, int ) ]
print 'stack contents : %s, sorted :%s, 2nd max : %s' % ( so, ss, s.second_max() )
if len(ss) > 1 and ss[-2] != s.second:
raise exceptions.ValueError()
print 'Commence pop'
for i in range( len( input ) ):
s.pop()
ss = s.sorted_sequence()
so = [ i for i in s.stack if isinstance( i, int ) ]
print 'stack contents : %s, sorted :%s, 2nd max : %s' % ( so, ss, s.second_max() )
if len(ss) > 1 and ss[-2] != s.second:
raise exceptions.ValueError()
|
L-Systems and Hilbert Curves

I remember being very impressed when I saw the L-system fractal morph in Versus by Finnish demo group Electromotive Force. Below is a quick hack to generate the Hilbert Curve. Will see to add more interesting curves when I get more free time to kill =]
# Experimentation with L-systems
import wx
import copy
class MyFrame(wx.Frame):
"""a frame with a panel"""
def __init__(self, parent=None, id=-1, title=None, lstr = ''):
wx.Frame.__init__(self, parent, id, title)
self.panel = wx.Panel(self, size=(200, 200))
self.panel.Bind(wx.EVT_PAINT, self.on_paint)
self.panel.SetBackgroundColour(wx.WHITE)
self.lstr = lstr
self.Fit()
def on_paint(self, event):
# establish the painting surface
dc = wx.PaintDC(self.panel)
dc.SetPen(wx.Pen('pink', 2))
turtle = Turtle(8, 20, 20)
for c in self.lstr.split():
cur = turtle.cur_pos()
if c not in ['A', 'B']:
p=turtle.process_move(c)
if p != cur:
dc.DrawLine(cur[0], cur[1], p[0], p[1] )
def recursive_substitute( level, x ):
if level==0:
return x
else:
y = []
for c in x:
if c == 'A':
y.extend( A )
elif c == 'B':
y.extend( B )
else:
y.append( c )
return recursive_substitute( level - 1, y )
move_map = {
0 : (1, 0),
90 : (0, 1),
180 : (-1, 0),
270 : (0, -1),
}
class Turtle():
def __init__( self, stepsize, startx=0, starty=0 ):
self.x = startx
self.y = starty
self.angle = 0
self.stepsize = stepsize
def process_move(self, c):
'''fn returns the new position after the move'''
if c == 'l':
self.angle = (self.angle + 90) % 360
elif c == 'r':
self.angle = (self.angle - 90) % 360
elif c == 'f':
move = move_map[ self.angle ]
self.x, self.y = self.x + move[0] * self.stepsize, self.y + move[1] *self.stepsize
return ( self.x, self.y )
def cur_pos(self):
return ( self.x, self.y )
A = 'l B f r A f A r f B l'.split()
B = 'r A f l B f B l f A r'.split()
start=copy.deepcopy( A )
ans = ' '.join( recursive_substitute( 4, start ) )
app = wx.PySimpleApp()
frame1 = MyFrame(title='Hilbert Curve', lstr=ans)
frame1.Center()
frame1.Show()
app.MainLoop()
|
Roman Numerals
Some random question asked of me from somewhere. Given a number convert it to the roman numeral equivalent. The data file is taken from here.
nummap = {
'I' : 1,
'V' : 5,
'X' : 10,
'L' : 50,
'C' : 100,
'D' : 500,
'M' : 1000,
}
rnummap = {
1:'I',
5:'V',
10:'X',
50:'L',
100:'C',
500:'D',
1000:'M',
}
tryorder = [ 'M', 'D', 'C', 'L', 'X', 'V', 'I' ]
def decompose( value, trylist ):
res = []
if value == 1:
return ['I']
if value == 0: return []
n = trylist[0]
cval = nummap[ n ]
oldval = value
if cval in [ 5, 50, 500 ] :
# try things like IX
next = cval / 5
prev = cval * 2
if value - ( prev - next ) >=0:
res.append( rnummap[ next ] )
res.append( rnummap[ prev ] )
value -= ( prev - next )
elif value - cval >= 0:
res.append( n )
value -= cval
elif value - ( cval - next) >= 0:
res.append( rnummap[ next ] )
res.append( rnummap[ cval ] )
value -= ( cval - next )
elif value - cval >= 0:
res.append( n )
value -= cval
if oldval == value:
if len(trylist) > 1:
trylist = trylist[1:]
res.extend( decompose( value, trylist ) )
return res
def main( ):
f = open( 'data' )
while True:
line = f.readline()
if not line:
break
x, y = line.split()
print x, y
romannumeral = ''.join( decompose( int(y), tryorder ) )
# the romannumeral returned must be equal to x
print romannumeral, y
f.close()
main() |
Randomized selection
Fun to see some randomized algos working in action. This is to be used with a kd-tree data structure (which i'll put up when i have more time ) which is to be used in my PixRay ray tracer written in python ( which i'll also put up when i find some more time to write things up ). Stay tuned.
import random
def randomizedselect( k, array ):
if len( array ) == 1:
return array[0]
# randomize the pivot to avoid getting stuck in infinite loop
# if the partition results in array of same length
pivot = array[ random.randint( 0, len( array ) -1 ) ]
left, right, match = [], [], []
for x in array:
if x < pivot:
left.append( x )
elif x == pivot:
match.append( x )
else:
right.append( x )
size_left, size_match = len( left ), len( match )
if size_left >= k :
return randomizedselect( k , left )
elif k > size_left and k <= size_left + size_match:
return match[0]
else:
return randomizedselect( k - ( size_left + size_match ), right )
def randomized_median( array ):
n = len( array )
k = n / 2 + 1 if n % 2 != 0 else n / 2
return randomizedselect( k, array )
|
KDTrees
A fundamental type of spatial data structures in Computational Geometry. It's useful in spatial queries such as nearest neighbour search and also has popular use in raytracing for object culling. The fundamental decisions to be made during kdtree construction is the stopping criteria and the choice of the splitting plane. In this simple example we use the median algorithm for the partition plane. The example code below showcase simple construction of a kdtree for a given point set. More spatial queries such as nearest neighbour search will follow in further updates. Note: the use of a dictionary for storing the tree structure is mainly for easy pprint-ing in early debugging.
import copy
import matplotlib.pyplot as plt
import median
import numpy
import pprint
import random
class KDTree( object ):
_IDX_LOOKUP = { 'x-axis' : 0, 'y-axis' : 1 }
def __init__( self ):
self._tree = {}
def build_kdtree( self, point_list ):
self._point_list = point_list
dic = {}
dim = len( point_list[0] )
MAXLEVEL = 16
print 'processing points=%s' % point_list
def build( d, level, points ):
if points.size == 0:
return None
elif points.size == 1 or level == MAXLEVEL:
return points
axis_index = level % dim
_median = median.randomized_median( points[ :, axis_index ] )
median_points = points[ numpy.where( points[ :,axis_index ] == _median ) ]
left_points = points[ numpy.where( points[ :,axis_index ] < _median ) ]
right_points = points[ numpy.where( points[ :,axis_index ] > _median ) ]
d[ 'median_points' ] = median_points
d[ 'split_axis' ] = 'y-axis' if axis_index else 'x-axis'
d[ 'left_node' ] = build( {}, level + 1, left_points )
d[ 'right_node' ] = build( {}, level + 1, right_points )
return d
self._tree = build( dic, 0, point_list )
def pprint( self ):
pprint.pprint( self._tree )
def show( self ):
x, y = zip( *self._point_list )
plt.autoscale( enable=True, tight=False )
plt.margins( 0.1, 0.1 )
plt.plot( x, y, 'o', color='b' )
yline_color = '#FFB0B0'
#yline_color = '#FF9595'
xline_color = '#b0e2ff'
def plot_separating_planes( v, node):
idx = KDTree._IDX_LOOKUP[ node[ 'split_axis' ] ]
pos = node[ 'median_points' ][0][ idx ]
if idx == 0:
plt.vlines( pos, v[2], v[3], color=yline_color, linewidth=2.0 )
elif idx == 1:
plt.hlines( pos, v[0], v[1], color=xline_color, linewidth=2.0 )
if node[ 'left_node' ]:
v_new = copy.deepcopy( v )
if idx == 0: # decide to shorten the bounding box along whichever axis
v_new[1] = pos
elif idx == 1:
v_new[3] = pos
plot_separating_planes( v_new, node[ 'left_node' ] )
if node[ 'right_node' ]:
v_new = copy.deepcopy( v )
if idx == 0: # decide to shorten the bounding box along whichever axis
v_new[0] = pos
elif idx == 1:
v_new[2] = pos
plot_separating_planes( v_new, node[ 'right_node' ] )
v_start = numpy.array( plt.axis() )
plot_separating_planes( v_start, self._tree )
plt.show()
def random_points():
points = []
for i in xrange( 0, 20 ):
points.append( ( random.randint( 0, 100 ), random.randint( 0, 100 ) ) )
return points
def main():
#point_list = [(2,3), (5,4), (9,6), (4,7), (8,1), (7,2)]
point_list = random_points()
array = numpy.array( point_list )
kdtree = KDTree()
kdtree.build_kdtree( array )
kdtree.pprint()
kdtree.show()
main()
|
Nearest Neighbour search in KDTrees
In nearest neighbour queries, we want to answer, for a point set, the closest point to a specified query point. The kd-tree is one such computational geometric data structure which supports fast nearest neighbour queries. The below code fragment shows the additional logic that we need to introduce into the earlier kd-tree implementation to support nearest neighbour search. The sample code also provide a simple UI to visualize the location of the query pt as well as it nearest neighbour, and it shows that it satisfy the empty circle property. One of the cool things about computational geometry is that it sits on the cross-roads graphics, visualization and algorithms. Many of the algorithmic structures and highly non-trivial, and you get to see the results in a visual manner.
@staticmethod
def squared_dist( x, y ):
v = x - y
return numpy.vdot( v, v )
@staticmethod
def circleOverlap( center, pt, axis, pos ):
# ( x - a )^2 + ( y - b )^2 = r^2
#r = numpy.sqrt( numpy.vdot( pt - center ) )
v = pt - center
rsqr = numpy.vdot( v, v )
residue = rsqr - numpy.square( pos - center[ axis ] )
if residue > 0.0 :
return True
return False
def nearest_neighbour( self, point ):
# finds the point in the kdtree nearest to the given point
def np( node ):
# termination condition
if node[ 'left_node' ] == None and node[ 'right_node' ] == None:
return min( [ ( x, KDTree.squared_dist( x, point ) ) for x in node[ 'median_points' ] ], key=lambda x : x[1] )[0]
candidate = None
# 1. descend the tree until we get to the first candidate point
idx = KDTree._IDX_LOOKUP[ node[ 'split_axis' ] ]
explored = 0
if point[ idx ] < node[ 'median_points' ][ 0 ][ idx ]:
if node[ 'left_node' ]:
candidate = np( node[ 'left_node' ] )
else:
if node[ 'right_node' ]:
candidate = np( node[ 'right_node' ] )
explored = 1
# select possible candidates from median_points as well
mp_candidate = min( [ ( x, KDTree.squared_dist( x, point ) ) for x in node[ 'median_points' ] ], key=lambda x : x[1] )[0]
if candidate is None:
candidate = mp_candidate
elif KDTree.squared_dist( point, candidate ) > KDTree.squared_dist( point, mp_candidate ):
candidate = mp_candidate
# check if circle centered at point, with radius | point -> candidate | overlap the split plane, if so we need to descend down
# that node as well
split_axis = KDTree._IDX_LOOKUP[ node[ 'split_axis' ] ]
if KDTree.circleOverlap( point, candidate, split_axis, node[ 'median_points' ][0][ split_axis ] ):
if explored == 0:
toexplore = node[ 'right_node' ]
else:
toexplore = node[ 'left_node' ]
if toexplore:
p_candidate = np( toexplore )
if KDTree.squared_dist( point, candidate ) > KDTree.squared_dist( point, p_candidate ):
candidate = p_candidate
return candidate
return np( self._tree )
def show_nearest_pt( self, pt ):
n = self.nearest_neighbour( pt )
print 'nearest point to %s is %s' % ( pt, n )
v = pt - n
r = numpy.sqrt( numpy.vdot( v, v ) )
plt.plot( pt[0], pt[1], 'x', color='r' )
ax = plt.subplot( 111 )
ax.add_patch( plt.Circle( pt, r, fill=False ) )
self.show()
def random_points():
points = []
for i in xrange( 0, 25 ):
points.append( numpy.array( ( random.randint( 0, 100 ), random.randint( 0, 100 ) ) ) )
return points
def main():
point_list = random_points()
array = numpy.array( point_list )
kdtree = KDTree()
kdtree.build_kdtree( array )
querypt = ( random.randint( 0, 100 ), random.randint( 0, 100 ) )
kdtree.show_nearest_pt( numpy.array( querypt ) )
|