Monday 15 June 2015

It's...

The boys at Programming Throwdown have drawn attention to a post by Santiago L. Valdarrama provocatively titled Five programming problems every Software Engineer should be able to solve in less than 1 hour.

Is that one hour each or one hour altogether?  Doesn't say.  Anyway I'm curious because it's a chance for me to prove that I really am as clever as I think I am.  That's the draw of a title like that, surely? You say: I will either solve the problems, thereby proving that other software engineers who can't solve them are idiots: or else I can't solve them, proving that the guy who posted the problem is the idiot.  Either way you can't lose...

Also the Throwdown team have mentioned a substitute text shell called Babun that they reckon is worth checking out.

This Babun shell comes with Python.  I've never tried Python so this is a good excuse.  I understand it is supposed to be easy to pick up, but also people do write serious systems with it.  Python has been sitting in the background of the programming world for years patiently waiting for Perl to die, and now it finds that Ruby has appeared from nowhere and claimed its patch.

Anyway, the first task is to write code that works out the sum of a list of numbers three ways, by a for loop, by a while loop, and by recursion.

So, here goes.

Start up Python from the fancy new shell:-

{ ~ }  » python  ~
Python 2.7.8 (default, Jul 28 2014, 01:34:03)
[GCC 4.8.3] on cygwin
Type "help", "copyright", "credits" or "license" for more information.

Python 2.7 classes itself as "legacy" - the current thinking is in Python version 3.  However.

Create a list of numbers with a nice easy sum:

>>> numbers = [50,25,12,7,3,2,1]

Now to use for - well, looks like Python has several way to use a for construction. First we can for over a range of consecutive numbers. Note that in Python, lists start at element zero.  Thank you, note taken.  The range you specify starts at the first number and stops before the second number you specify.  That makes it easy: to scan over all the elements of the array we do this:

>>> sum = 0
>>> for ix in range(0, len(numbers)):
...     sum = sum + numbers[ix]
...
>>> print sum
100

Using sum to accumulate the result each time of course.

>>> is the Python shell prompt at the top level, and ... is the prompt when you are inside a multi-line construction.  Block structure is defined in the syntax by the indentation.  Bold move.

There is also a for construction that gives you the elements in a collection without your having to pick an index, so alternatively we can say this:

>>> sum = 0
>>> for n in numbers:
...     sum = sum + n
...
>>> print sum
100
>>>

To run over the list with a while construction I'll use two index variables, ix to step through and iy to be the first index I don't want to see, which will be the length of the list. I set this before I go into the loop as I don't want to have to evaluate the len() function more than once if I don't have to.

So:-

>>> sum = 0
>>> ix = 0
>>> iy = len(numbers)
>>> while ix < iy:
...     sum = sum + numbers[ix]
...     ix = ix + 1
...
>>> print sum
100
>>>

Yes, I derive an obscure comfort from naming variables after Z80 registers. It's a bit like making a drink in a favourite cup or taking notes with a favourite pen.  You just know where you are, you see.

Now, lst[0] corresponds to (CAR lst) in Lisp.  You get the first element from the list.  In addition to writing lst[ix] to pick a specific element you can get sub-lists.  For example lst[1:] returns the list of elements starting after the zero element in the list - so this corresponds to (CDR lst) in Lisp. With these two in mind we can write the recursive solution that looks just like a Lisp one:

>>> def sum_list(ns):
...     if ns == []:
...             return 0
...     else:
...             return ns[0] + sum_list(ns[1:])
...
>>> print sum_list(numbers)
100
>>>

Hey, we are Python-enabled.  Cool.  Spam.

Did that take an hour?  I don't know, I lost track of time watching Babun download.

No comments:

Post a Comment