[Tutor] 'Common' mistake ... for other newbies

David Broadwell dbroadwell at mindspring.com
Mon Apr 12 11:00:19 EDT 2004


I started with the text below, but if you don't like detailed reports of
newbie fumbles, skip this post. Points to not quitting but continuing to
hack at it ... my first real bug.

...

I'm having an odd problem that I don't know how to debug.
What is going on is as a exercise, I'm playing rock paper scissors in code.
I'm using; Python 2.2, Windows2kServer, PII450 at 386mb w/80gb

...

At full run with a 100 item result list it failed on the average 97th roll,
but with a 6 entry list only averages 10 rolls instead before dying. It
seems that the smaller the resultlist the more often an IndexError occurs.

The code is like this (static data for brevity);

>>> from random import randint
>>> resultlist = ['rock','paper','scissors','rock','paper','scissors']
>>> def roll():
    ''' returns a random item from resultlist '''
    return resultlist[randint(0,len(resultlist))]

>>> for item in range(1000):
	roll()

'scissors'
'paper'
'paper'
'paper'
'paper'
'rock'
'scissors'
Traceback (most recent call last):
  File "<pyshell#9>", line 2, in ?
    roll()
  File "<pyshell#3>", line 3, in roll
    return resultlist[randint(0,len(resultlist))]
IndexError: list index out of range
>>>

So to debug, I rewrote roll into debugroll()

>>> def debugroll():
    temp = len(resultlist)
    print "len(resultlist) = %s" % temp
    temp = randint(0,temp)
    print "randint(0,len(resultlist)) = %s" % temp
    temp = resultlist[temp]
    print "resultlist[randint(0,len(resultlist))] = %s" % temp
    return temp

>>> for item in range(1000):
	debugroll()

len(resultlist) = 6
randint(0,len(resultlist)) = 5
resultlist[randint(0,len(resultlist))] = scissors
'scissors'
len(resultlist) = 6
randint(0,len(resultlist)) = 6
Traceback (most recent call last):
  File "<pyshell#4>", line 2, in ?
    debugroll()
  File "<pyshell#0>", line 6, in debugroll
    temp = resultlist[temp]
IndexError: list index out of range

after a bit more testing (or frantically repeating the error) I noted that
it only died when the randomly generated index was 6 ... and then it hit me,
a list of len 6 has no index six and the uncrashable roll function needed to
reflect that is as follows.

The solution;
>>> def roll():
    ''' returns a random item from resultlist '''
    return resultlist[randint(0,len(resultlist)-1)]

...

I got bit because I count from 1 and the computer counts from 0, a 'common'
mistake.

As a note this was the last hurdle to having the code play rock paper
scissors against itself, I'm sure it's not nearly as elegant as it could be,
but it's very, very, readable.

--

Programmer's mantra; Observe, Brainstorm, Prototype, Repeat

David Broadwell




More information about the Tutor mailing list