Thursday, 23 July 2009

Russian peasant multiplication in python

The Daily WTF recently suggested a programming challenge (or Praxis in their terms) to write a Russian peasant multiplication algorithm. I thought this would be a good opportunity to improve my python programming and inline I have described a few of the python specific techniques I used.

The algorithm itself is very simple:

multiply(a, b)

repeat until a = 0
  1. if a is an odd number add b to the accumulator
  2. divide a by 2 (throwing away the remainder)
  3. multiply b by 2
The accumulator will contain the desired result.




#!/usr/bin/python

from sys import argv

if len(argv) < 3:
print "input values missing"
print "usage: "
print argv[0] + " value1 value2"
exit()

# The int() function converts a string or number to an integer

a = int(argv[1])
b = int(argv[2])
acc = 0 # the accumulator
sep = " x " # separator for output formatting
justWidth = 5 # justification width for output formatting

while (a > 0):
if a & 0x1:
acc = acc + b
print " ",
else:
print "--",

# the str() function converts an object to a string
# rjust(n) right justifies strings to a given width

print str(a).rjust(justWidth) + sep + str(b).rjust(justWidth)

# Only output the x separator the first time round - after that use
# spaces. It is inefficient to continually reset this but IMO makes
# the code clearer than keeping a separate flag.

sep = " "

a = a >> 1
b = b << 1

# The output width is the width of the two numbers plus the
# separator

fullWidth = (justWidth*2)+len(sep)

# A neat python feature is that using the * operator on a string will
# repeat a string a multiple number of times so this line outputs
# 2 spaces followed by (2*justWidth) + separator length dashes

print " " + "-" * fullWidth
print " =" + str(acc).rjust(fullWidth)



This Gives output as follows:


>pmath.py 18 23
-- 18 x 23
9 46
-- 4 92
-- 2 184
1 368
-------------
= 414

The lines starting with -- are considered to be crossed out and only the numbers on the other lines should be added - in this case 46 and 368.

This little experiment has only strengthened my interest in python - it took very little time to come up with this code, even having to learn about int(), str(), rjust() and the * operator for strings. Using the python interpreter command line is also a great bonus to check things like the << and & 0x1 syntax work as expected

No comments: