jmitt
jmitt

Reputation: 46

List slicing errors in python

I guess my problem isn't so much with methods as it is with slicing a list (such as list[2:5]). When the code is actually being run, it is not cutting the list at the right place. The program is attempting to guess a number that was given to it by a user. It is doing this using the random module ,which i know may not be the best way, but I was experimenting.

The Code:

import random

number = input('Pick a number from 1-100 for the computer to guess, \nand find out how many tries it takes the computer: ')

print number

possibilities = range(101)

del possibilities[0]

tries = 1

guess = random.choice(possibilities)

print "\n", guess

while guess != number:
    if guess > number:
        possibilities = possibilities[:(guess-1)]
    else:
        possibilities = possibilities[(guess-1):]
    print possibilities
    guess = random.choice(possibilities)
    print guess
    tries += 1

Example of the errors:

Output of the program, from the print statements above. I would also like to mention that it does not always malfunction, about 50-60% of the time it works fine. Also, it is not just the numbers that I put in, for example, 45 may work fine, or it may fail as it did below, it seems like a pretty random occurrence.

With initial input 45:

45

30 [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]

88 Initial Error (the program should have cut off the list past 88) [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]

54 [30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82] 40 Fatal Error (Where it cut off the list, removing the number it was 'looking' for) [69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82] 72 [69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82]

With initial input 6:

6

48
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]
9
[1, 2, 3, 4, 5, 6, 7, 8]

5  **Initial Error** (the program should have eliminated 5 from the list below this line)
[5, 6, 7, 8]

5  **Fatal Error** (the program deleted the rest of the list)
[]

Traceback (most recent call last):
  File "C:\Users\Joseph\Documents\Programming fun\computer guessing a number game.py", line 32, in <module>
    guess = random.choice(possibilities)
  File "C:\Python27\lib\random.py", line 274, in choice
    return seq[int(self.random() * len(seq))]  # raises IndexError if seq is empty
IndexError: list index out of range

I would like to know why Python is doing this, and if it is avoidable or not. I don't think there is a problem with my code, it looks to me like Python is just not working the way it is supposed to, but I am extremely new to programming so I am not sure if I am missing something.

Thank you for any help that may be provided.

Upvotes: 0

Views: 688

Answers (4)

Geoff Reedy
Geoff Reedy

Reputation: 36011

Slices are defined by the index not the value of the element. If you have a slice x[a:b] of a list that gives a list with the ath item followed by the a+1th item up to but not including the bth item. If b is less than or equal to a the result will be empty. If b is greater than or equal to the number of items in the list every item after the ath will be included. If you omit the first number, 0 is assumed and if you omit the second number, the number of items in the list is assumed. Here's an example that doesn't use numbers in the list to avoid confusion:

x = ['a','b','c','d','e','f','g']
print x[3:] # prints ['d','e','f','g']
print x[:2] # prints ['a','b']
print x[1:4] # prints ['b','c','d']

If you use a negative number in a slice then the length of the list will be added to the number to determine the final index.

To get your code to work correctly and still use slices to refine the list of possibilities, there is an index method for lists that will give the index (of course) of the item passed as an argument. So for your program you could change the lines to read

if guess > number:
    possibilities = possibilities[:possibilities.index(guess)]
else:
    possibilities = possibilities[possibilities.index(guess):]

A better way to write a guess-the-number type program is to instead use just two variables hi and lo that keep track of the biggest and lowest numbers, respectively, that the answer could be. If the answer is greater than the guess then set lo to be the guess plus one and if the answer is less than the guess set hi to be the guess minus one.

Upvotes: 0

Junuxx
Junuxx

Reputation: 14261

You are confusing the values in possibilities with their indices. mylist[:i] means "all values in mylist up to the ith element", not "up to the element with the value i".

Initially, confusing indices and values doesn't cause a problem because your list values are (almost, since you skip 0) equal to their indices. But when you start cutting pieces of the list away, you get the situation that the list is shorter than some of the values in it. For example, when everything below 80 has been removed and you guess 90, possibilities[90:] tries to access the 90th element onwards from a list of length 20. Of course, that doesn't work.

Try this instead:

i = possibilities.index(guess)    
possibilities = possibilities[:(i-1)]

Upvotes: 1

WhyNotHugo
WhyNotHugo

Reputation: 9926

When "5" is selected, this code will remove from the fifth position onwards. You array has only four elements, so that means all of it.

Upvotes: 0

Ned Batchelder
Ned Batchelder

Reputation: 375594

When you do guess = random.choice(possibilities), you are getting a value from the list, but then you use it as an index when you do this: possibilities = possibilities[:(guess-1)]. After a few times around the loop, your list has values that are outside the range of indexes:

[80, 81, 82, 83, 84, 85, 86, 87]

When you select a value from here (like 85), then do possibilities = possibilities[85:], you get back an empty list.

You need to stick to indexes.

Upvotes: 2

Related Questions