Categories
Software

Python II: Fibonacci Sequence

Tim’s second exercise (here’s the first):

Write a recursive function that calculates the value of Fibonacci numbers. These are your acceptance criteria:

  • Calculating fib(250) must return 7896325826131730509282738943634332893686268675876375
  • The function must use recursion. No intermediary data structures, etc.
  • The implementation must be written in pure python – no C extension modules, that’s cheating.
  • The function must calculate the 250th Fibonacci number in under one second.

    You will get extra points if:

  • You can also demonstrate a proof for the Reciprocal Fibonacci constant, meeting the following conditions
    • Your proof must also run in under one second
    • Your proof must not duplicate any of the concerns addressed by your original Fibonacci function implementation.
    • Your proof is allowed to call into the Fibonacci function though!

The Reciprocal Fibonacci constant is defined as:

P(F) = Sum[k = 1..infinity] 1/F(k) = 3.35988566…

Where F is a Fibonacci number

Here’s a couple of hints about things to look for:

  • Memoization
  • Function decorators

I haven’t tried the extra credit section yet, but this is what I came up with. Again, starting with a naive solution with some doctest tests:

#!/usr/bin/env python

"""
>>> fib(1)
1
>>> fib(2)
1
>>> fib(3)
2
>>> fib(4)
3
>>> fib(5)
5
"""
def fib(n):
	if n <= 2:
		return 1
	else:
		return fib(n-2) + fib(n-1)

def _test():
   import doctest
   doctest.testmod()

if __name__ == "__main__":
   _test()

Well that seems to work OK. Now, try adding a test for the 250th number:

>>> fib(250)
7896325826131730509282738943634332893686268675876375

And wait … and wait …

No, doesn't look like that's going to return any time soon. Of course when you look at what it's doing, the complexity's increasing in the order of 2n or something, which isn't good.

OK, I guess this is where memoisation comes in. After much head-scratching on the train this morning, I came up with this:

fibs = {}

def fib(n):
	if n <= 2:
		return 1
	elif fibs.has_key(n):
		return fibs[n]
	else:
		fibs[n] = fib(n-1) + fib(n-2)
		return fibs[n]

A little tweak to allow it to be called from the command line with the value of n passed as an argument, and here's the final version:

#!/usr/bin/env python
import sys

fibs = {}

def fib(n):
	if n <= 2:
		return 1
	elif fibs.has_key(n):
		return fibs[n]
	else:
		fibs[n] = fib(n-1) + fib(n-2)
		return fibs[n]

def _test():
  import doctest
  doctest.testmod()

if len(sys.argv) > 1:
	print fib(int(sys.argv[1]))
if __name__ == "__main__":
  _test()
fib(master) $ time ./fib.py 250
7896325826131730509282738943634332893686268675876375

real	0m0.280s
user	0m0.161s
sys	0m0.047s

Sorted!

[tags]python, web21c, fibonacci[/tags]

Categories
Software

First stab at Python

Monty Python foot “It is an ex parrot. It has ceased to be.”

No, of course not. I’m talking about the other Python. Not the one with the silly walks, dead parrot and singing lumberjacks, but the one with the idiosyncratic approach to whitespace.

One of the APIs available for the Web21C SDK is Python, and there was recently some concern that we didn’t have enough expertise in the team to continue providing technical support for the Python SDK. A bunch of us have volunteered to start learning the language, and as a first step, Tim set us some homework:

Write a program that processes a list of numbers from 1 to 100. For each number, if the number is a multiple of 3, print “FIZZ”; if the number is a multiple of 5, print “BANG”; otherwise, print the number.

You are *NOT* allowed to use any *IF/ELSE* statements in your code. You can use the list-accessing ternary operator hack, but whilst I’ll accept your homework if you do, you’ll miss out on the prize (alcoholic), which goes to the most concise code (not including whitespace).

Now I have no idea what this mysterious ‘list-accessing ternary operator hack’ might be, but it sounds painful (as does missing out on an alcoholic prize), so it looks like I need to eschew ifs completely.

Since I’ve never written a line of Python in my life, I decided the easiest way to proceed would be to start off by figuring out enough syntax to solve the problem as defined by the first paragraph, then write a test which the simple code passes, then factor out the conditional logic. Normally I’d start with the test, but I think learning a new language is one of the cases where TDD isn’t really appropriate.

So here’s my first working code:

for n in range(1, 100):
	if n % 3 == 0:
		if n % 5 == 0:
			print 'FIZZBANG'
		else:
			print 'FIZZ'
	elif n % 5 == 0:
		print 'BANG'
	else:
		print n

This prints out what you would expect:

PyMate r8111 running Python 2.5.1 (/usr/bin/env python)
>>> fizzbang.py

1
2
FIZZ
4
BANG
FIZZ
7
8
FIZZ
BANG
11
FIZZ
13
14
FIZZBANG
16
...

OK, so far so good. The next step was to find out what the Pythonistas use for unit testing. As a card-carrying BDD and RSpec fan, I was initially interested to see that there’s a PySpec, but at first glance it doesn’t look that great (maybe it’s just that I’m not used to reading Python code). Then I came across the bundled DocTest, and while I’m not entirely convinced by its description on the Wikipedia BDD page as ‘BDD for Python’, it looked ideal for the task at hand.

Here’s the same code, but with the addition of a parameter to specify the number to count up to, and a DocTest test:

#!/usr/bin/env python

"""
Print numbers up to limit, replacing those divisible by 3 and/or 5 with FIZZ
and/or BANG.

>>> fizzbang(20)
1
2
FIZZ
4
BANG
FIZZ
7
8
FIZZ
BANG
11
FIZZ
13
14
FIZZBANG
16
17
FIZZ
19
BANG
"""
def fizzbang(limit):
	for n in range(1, limit + 1):
		if n % 3 == 0:
			if n % 5 == 0:
				print 'FIZZBANG'
			else:
				print 'FIZZ'
		elif n % 5 == 0:
			print 'BANG'
		else:
			print n

def _test():
   import doctest
   doctest.testmod()

if __name__ == "__main__":
   _test()

OK, now to start thinking about the hard bit – getting rid of those ifs. As a first step, I got rid of the nested logic by appending the ‘FIZZ’ and/or ‘BANG’ to a temporary string, then either printing that string, or the original number if it was empty:

def fizzbang(limit):
	for n in range(1, limit + 1):
		out = ''
		if n % 3 == 0:
			out += 'FIZZ'
		if n % 5 == 0:
			out += 'BANG'
		print out or n

At this point, I hit on the idea of using arrays to select either an empty string or the appropriate word:

def fizzbang(limit):
	for n in range(0, limit):
		print ['', '', 'FIZZ'][n%3] + ['', '', '', '', 'BANG'][n%5] or n + 1

Now all that’s left is to remove the limit parameter so the code merely satisfies the original criteria:

for n in range(100):
	print ['', '', 'FIZZ'][n%3] + ['', '', '', '', 'BANG'][n%5] or n + 1

I expect there are other more concise (and no doubt more efficient) solutions – I look forward to seeing what the other ‘pupils’ come up with!

[tags]python,web21c,fizzbang,fizzbuzz[/tags]

Categories
General nonsense Software

What’s your command-line top ten?

Here’s mine:

~ $ history|awk '{a[$2]++} END{for(i in a){printf "%5d\t%s\n",a[i],i}}'|sort -rn|head
  232	git
   82	cd
   30	ls
   20	sudo
   18	rm
   13	./script/server
   12	mate
   11	rake
    7	vi
    7	ssh

Probably slightly skewed by the fact that I was doing a git demo yesterday.

Meme via Simon Brunning.

Categories
Agile BT

InfoWorld Article on BT and Agile

Some time last year I was interviewed by Tom Hoffman for Infoworld, as part of a piece he was writing on BT’s (ongoing) transition to an agile software development model. Here’s the article:

BT: A case study in agile programming

Categories
Agile Rants Software

Government IT waste

Money down the drainThere’s an article in today’s Guardian called Not fit for purpose: £2bn cost of government’s IT blunders, with the following summary:

The cost to the taxpayer of abandoned Whitehall computer projects since 2000 has reached almost £2bn – not including the bill for an online crime reporting site that was cancelled this week, a survey by the Guardian reveals.

I have no doubt whatsoever that the government wastes a vast amount on IT contracts, but I think that, by concentrating on the cost of cancelled projects, the article misses the point slightly.

If a project is clearly never going to deliver, it’s far better to cancel it than to fall into the trap of the sunk cost fallacy, and keep pouring money in in the hope that eventually everything will turn out OK in the end.

The real questions for me are ‘are the government’s IT needs being met at the most cost-effective manner?’ and ‘why does it take so long to realise that a project is doomed?’

I don’t know anything about the projects discussed in the article, or about how government IT contracts are handled in general, but I’d be willing to bet that the following guesses aren’t too wide of the mark:

  • Someone decides that a new system is required, and produces a huge list of everything they think it needs to do. This goes out to tender, and the job goes to whoever manages to produce the lowest quote while still giving a reasonably credible impression that they can actually complete the work in the specified time.
  • The contractor goes off and starts work. They talk to the civil servants who are responsible for specifying the system, but probably not to the people who will actually have to use it. They then go off and produce a design, get it signed off, and set up teams to work on all the identified subsystems.
  • Every few months they deliver a progress report, assuring the client that everything’s progressing according to plan. After a year or so the schedule probably slips a bit, but they assure everyone that it’s jsut a blip, and the final delivery won’t be significantly affected (we can always trim the testing phase a little, right?)
  • Because the contract fixed time, cost and scope, there’s only one thing that can be adjusted to keep the project profitable when the estimates turn out to have been optimistic: quality. Of course this ripples forward, with more and more time spent chasing problems caused by poor quality work in existing parts of the system.
  • When (eventually) the first version of the system is delivered, there are integration problems, it doesn’t quite do what the people specifying it actually wanted, and it turns out that large parts of the specification weren’t that important, but some vital features have been missed out altogether. Depending on just how big a disaster it all was, one of two things happens:
    • The project gets cancelled. The contractor moves on to the next lucrative contract, and an enquiry’s set up to investigate the specific reasons for the project failure, completely missing the big picture.
    • The problems are slowly ironed out, and the missing features are added to the requirements for the next release. The contractor rubs its collective hands at the thought of the massive fees they can charge for the change requests, and a huge amount of time is wasted arguing about whether each change is a new feature or a bug request.

I’m not (quite) naive enough to suggest that all these problems could be solved by wholesale adoption of XP, but I get the impression that the government (and the media reporting on these fiascos) isn’t even aware that there is a better way. With major companies adopting an agile approach now (or at least pretending to), how long before the people responsible for spending our taxes wake up?

[tags]government,it,waste,agile[/tags]

Categories
Java Software

Java ‘Good for Nothing’?

In Language Explorations, Ola Bini (of JRuby fame) suggests that there won’t be any more ‘big languages’, but instead more of a mix-and-match approach, with different languages used for different parts of an application according to their strengths, all running on the JVM (or presumably .NET if you’re on the dark side).

An interesting opinion (which I’ve slightly mischievously taken out of context here) from the article:

In fact, I’m not sure if Java the language is good enough for anything, anymore.

Categories
Software

Happy New Year

JanusSo, that’s 2007 over with. Is it just me getting old, or did the past year go by even quicker than normal?

Amongst other things, 2007 was (for me at least) the year of Ruby. Obviously Rails had already been around for a while, and the language itself even longer, but they both seemed to be popping up all over the place last year, and gaining acceptance where they had previously been ignored as not mature or “enterprisey” enough. It’ll probably still be a while before large companies look at Ruby and Rails in the same way they currently look at Java and J2EE, but at least in my little corner of a large company I was able to spend the whole year writing Rails apps. It doesn’t look like there’s going to be any slacking of the pace in 2008 either, with the last few weeks of 2007 seeing the release of Rails 2.0, RSpec 1.1, Ruby 1.9 and JtestR (the last of which should be cool for Ruby people still stuck in a Java world).

It was also the year of ‘social networking’ websites in general, and Facebook in particular. Halfway through the year they introduced their developers’ API, and the web was awash with people praising their openness. Over the following months people started to realise that that ‘openness’ was very much one way, intended to get your applications running on their platform rather than allowing users to expose their data on the Web, and much of the shine wore off. Of course, most of us still use it now and again (if only to play Scrabulous), and there are a few signs that they’re starting to open the door to the Web ever-so-slightly in the other direction, so we’ll see what happens. There’s also OpenSocial to keep an eye on, of course, with Google so far managing to stay just on the right side of the good/evil line (all-seeing eye notwithstanding).

At the lighter end of the social networking scale, the star of 2007 was undoubtedly Twitter. Never has something so simple and apparently pointless been so intriguing and useful. Their business model (at least in the UK) is still a mystery though.

Some would say that 2007 was the year when Agile Software Development finally crossed into the mainstream. Unfortunately I tend to side more with Simon and Gus, and call it the year of compromised agile. It seems that for many large companies ‘agile’ has just become another buzzword. They talk about ‘enterprise scale agile’ and introduce a few of the easier, non-technical practices (daily stand-ups, retrospectives and so on), and put off making the real changes that are required for a truly agile organisation (co-located self-organising teams, daily customer involvement, devolution of decision-making, genuine focus on business value, an emphasis on technical excellence, test-driven development etc), while persisting with anti-agile behaviours such as outsourcing development, big up-front design, ivory tower architecture and fixed time, scope and budget. Baby steps are great, but there’s an implicit assumption that you take lots of them, instead of a few large ones.

Last but not least, 2007 was, of course, the year of the lolcat!


So what does 2008 hold in store? Unfortunately I didn’t get a crystal ball for Christmas, but here are a few guesses and hopes.

Will 2008 really be the year of Erlang? It seems to be building up the same kind of following (amongst many of the same people) that Ruby had 18 months ago, so who knows? It’s an interesting language, but I still find that the syntax grates.

Perhaps this will be the year when everyone finally realises that ‘Web 2.0’ has become so overloaded as to be meaningless. Sadly, even if that happens we’ll probably just see the buzzword bandits start calling something ‘Web 2.1’ or ‘Web 3.0’, so that’s a battle that’s never likely to be won.

Finally, could it be the year of OpenID and OAuth? If it weren’t for my poor security practices when it comes to personal site registrations, I’d have no chance of remembering account details for the myriad sites I’ve registered on, so wider adoption of OpenID would be nice. Similarly, it’s a pain finding and adding friends in yet another ‘social network’ application. I don’t really want to be handing out my GMail password left right and centre, and OAuth would (amongst other things) provide a neat way to request friends lists from other sites (and of course using OpenID would make it easier to identify people). Personally, I’d prefer it if everywhere just exposed my friends list publicly like Twitter does, or at least gave me that option. If they all used FOAFXFN, so much the better.

Anyway, I ought to post this while it’s still New Year’s Day. Whatever technologies 2008 has in store, I hope it’s a good year for you.

[tags]ruby, rails, rspec, jtestr, facebook, agile, enterprise, compromised agility, lolcats, erlang, new year, 2007, 2008, web 2.0, openid, oauth, foaf[/tags]

Categories
Agile

The Neglected Practice of Iteration

“It’s not iteration if you only do it once.”

I’ve already mentioned Jeff Patton’s XPDay keynote, where he talked about the importance of working in iterations (as opposed to increments). Jeff has now written a column, The Neglected Practice of Iteration, on StickyMinds, making the same point (but without the music!)

Excellent stuff, and well worth a read. I suspect most people who claim to follow an iterative development process are prone to lapsing into an incremental mentality – I know I am.

[tags]Jeff Patton, iteration[/tags]

Categories
Rails rspec Ruby

“You have to declare the controller name in controller specs”

For ages I’ve been getting an intermittent problem with RSpec, where occasionally I’d see the following error on a model spec:

You have to declare the controller name in controller specs. For example:
describe "The ExampleController" do
controller_name "example" #invokes the ExampleController
end

The problem seemed to depend on which order the specs were run in, and for rake it could be avoided by removing --loadby mtime --reverse from spec.opts. It was a real pain with autotest though, and today (my original plan of “wait for RSpec 1.1 and hope it goes away” having failed) I finally got round to looking into it properly.

It seemed that the error was being triggered by the rather unpleasant code I wrote a while ago to simplify testing of model validation. Digging into the RSpec source to see what was happening, I found that that error message only gets returned when (as you’d expect) you don’t declare the controller name in a controller spec (specifically in an instance of Spec::Rails::Example::ControllerExampleGroup). The code that decides what type of example group to create lives in Spec::DSL::BehaviourFactory, and according to its specs, there are two methods it uses to figure out what type of spec it’s looking at:

it "should return a ModelExampleGroup when given :type => :model" do
...
it "should return a ModelExampleGroup when given :spec_path => '/blah/spec/models/'" do
...
it "should return a ModelExampleGroup when given :spec_path => '\\blah\\spec\\models\\' (windows format)" do
...
it "should favor the :type over the :spec_path" do
...

I began to suspect that the problem was caused by the fact that my specify_attributes method wasn’t declared in a file in spec/models, so I thought I’d try specifying the type explicitly. So instead of this:

describe "#{label} with all attributes set" do

I changed it to this:

describe "#{label} with all attributes set", :type => 'model' do

Sure enough, it worked! Not sure whether anyone else is likely to see the same problem (unless they’re foolish enough to use my validation spec code), but hopefully if you do, a Google search will bring up this post and it might point you in the right direction.

Categories
General nonsense Rails

Rails Envy’s take on the werewolf question

This clip [MP3, 57s] from a Rails Envy podcast made me laugh. It’s referring to Charles Nutter’s recent musings on whether werewolf is killing the conference hackfest.

Incidentally, how often do you get the chance to Google for “nutter werewolf”?

[tags]rails envy, werewolf[/tags]