lndexError: list index out of range - python

I need to generate a string from random letters given in list take_from. The first time the function was executed it generated a phrase but all my following tries prompted an error "list index out of range". I can`t understand this error in my case and I tried while loop instead of for loop but it did not work either.
from random import randint
def make_a_phrase():
random_string = ''
take_from = ['a','b','c','d','e','f','g','h','i','j','k','l',
'm','n','o','p','q','r','s','t','v','u','w','x',
'y','z',' ']
for i in range(28):
random_string = random_string + take_from[randint
(0,len(take_from))]
return random_string

From the docs
random.randint(a, b)
Return a random integer N such that a <= N <= b.
Alias for randrange(a, b+1).
Therefore you can get values from 0 to len(take_from) - inclusive the endpoints - which in case of the upper bound would be out of list's index range as it is zero based and as such only has len(take_from) - 1 elements

In Python, lists are indexed with integers ranging from 0 to 1 less than the length of the list. E.g., a list with 10 items in it would have indexes from 0 to 9.
Your call to randint() attempts to get indexes from zero to the full length of the list, which will cause this exception. Change it to:
for i in range(28):
random_string = random_string + take_from[randint
(0,len(take_from)-1)]

The reason this happens, is because the len returns the length, but the last index is always the length - 1 (since indices start from 0).
So eventually, the random integer that comes up is the length, and of course, there is no element at that number.
Here is a simple example:
>>> i = [1,2,3]
>>> len(i)
3
>>> i[len(i)]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list index out of range
However, if you -1 from the length you will get the last item:
>>> i[len(i)-1]
3

You should change your loop to say:
for i in range(0, len(take_from)):
You are currently experiencing an off-by-one error because you only have 27 elements in your list, not 28.

You could try something like this instead
from string import ascii_lowercase
import random
def make_a_phrase():
return ''.join(random.choice(ascii_lowercase + ' ') for i in range(28))

Related

How to randomly change boolean value in a list

I'm trying to randomly assign a 'True' value to a list of booleans. When I run the code, I keep getting an error. Here's the code:
for x in population:
if x:
r = random.randint(0, len(population))
population[r] = True
Which keeps throwing the error:
"Traceback (most recent call last):
population[r] = True
IndexError: list assignment index out of range"
I'm sure it's something trivial, but I can't figure it out. How is the index assignment out of range when I constrain it to within the length of the list?
random.randint(a, b) returns a number between a and b inclusive. If the result of the function call equals len(population), then you're trying to do population[len(population)], which will raise an IndexError because indexing starts at 0.
Simple change: Just minus 1 from len(population):
r = random.randint(0, len(population)-1)
Or use randrange(a, b), which is not inclusive:
r = random.randrange(len(population))
Note that if the first argument is 0 we don't need it since it will assume the start is 0.
According to the documentation, random.randint(a, b)
Return a random integer N such that a <= N <= b.
Since arrays are indexed starting at 0 in Python, len(population) is outside the range of the array (hence your error). As #TerryA indicated, you actually want the range to be from 0 to len(population) - 1.
try :
for x in population:
if x:
r = random.randint(0, len(population)-1)
population[r] = True

Trying to create finit sequences of numbers in python2: IndexError (beginner)

edit: The initial problem is solved now, look at the bottom of the question; I have another problem.
I have a list, s2 that its first element (s[0]) is a list of numbers with the length of n (defined by user input) and its elements are also defined by the user. What I want to do is to create n-1 more sequences of numbers as other elements of s2. Each of those sequences is made of the subtraction of the sequential elements in the previous sequence. (the right element - the left element) so the second sequence's length is n-1, the third: n-2 ... and the nth sequence's length (s2[n-1]'s) is 1.
for j in range(1, n):
for k in range(0,n-j):
s2[j].append(s2[j-1][k+1] - s2[j-1][k])
but I get this error:
Traceback (most recent call last):
File "[path]", line 9, in <module>
s2[j].append(s2[j-1][k+1] - s2[j-1][k])
IndexError: list index out of range
Can you help me debug this?
edit:
n = int(raw_input())
s = raw_input()
s1 = [int(i) for i in s.split(" ")]
s2 = []
s2.append(s1)
for j in range(1, n):
for k in range(0,n-j):
s2[j].append(s2[j-1][k+1] - s2[j-1][k])
example input:
4
1 2 3 4
ps: Can you suggest me another method to get the nth one faster than this? instead of creating all of these lists? (I want it to take less than 1 sec even when n is very big)
You are referring to s2[j], but haven't created it. Try something like this
for j in range(1, n):
s2.append([])
for k in range(0, n-j):
s2[j].append(s2[j-1][k+1] - s2[j-1][k])
You need to initialize every s2 element before trying to use it. Otherwise how would python know what type it is?
for j in range(1, n):
s2.append(list())
for k in range(0, n-j):
s2[j].append(s2[j-1][k+1] - s2[j-1][k])

IndexError: list index out of range in codewars puzzle

As a beginner in Python I decided to have a go at the Codewars puzzles.
Codewars uses Python 2.7.6.
The second puzzle requires you to:
Write a function that will return the count of distinct case-insensitive alphabetic characters and numeric digits that occur more than once in the input string. The input string can be assumed to contain only alphabets (both uppercase and lowercase) and numeric digits.
For example, if you give the program "abcde" it should give you 0, because there are no duplicates. But, if you give it "indivisibilities" it should give you 2, because there are 2 duplicate letters: i (occurs 7 times) and s (occurs twice).
As a beginner I came up with an approach that I imagine is very crude, but nevertheless it works perfectly on my system:
def duplicate_count(text):
# the number of duplicates
dupes = 0
# convert input string to lower case and split into individual characters
list_of_chars = list(text.lower())
# sort list into groups
sorted_chars = sorted(list_of_chars)
# get length of list
n = len(sorted_chars)
# check whether the first element of the list is the same as the second. If
# it is, add one to the dupes count
if sorted_chars[0] == sorted_chars[1]:
dupes += 1
else:
dupes += 0
# start with the second element (index: 1) and finish with the (n - 1)-th
# element
for i in range(1, n - 1):
# if the ith element of the list is the same as the next one, add one
# to the dupes count. However, since we only want to count each
# duplicate once, we must check that the ith element is not the same as
# the previous one
if sorted_chars[i] == sorted_chars[i + 1] and sorted_chars[i] != sorted_chars[i - 1]:
dupes += 1
else:
dupes += 0
return dupes
This passes all of the automated tests, but when I submit this as a solution I get an STDERR:
Traceback:
in <module>
in duplicate_count
IndexError: list index out of range
As I understand it, this error is given if I try and access an element of the list that does not exist. But I cannot see where in my code I am doing that. I calculate the length of my list and store it in n. So let's say I supply the string "ababa" to duplicate_count, it should generate a list sorted_chars: ['a', 'a', 'a', 'b', 'b'] of length 5. So n = 5. Therefore range(1, n - 1) = range(1, 4) which will generate the numbers 1, 2 and 3. Thus for i in range(1, n - 1) is, mathematically speaking, for each i ϵ I = {1, 2, 3}. The largest index I therefore use in this code is 4 (if sorted_chars[i] == sorted_chars[i + 1]), which is fine, because there is an element at index 4 (in this case 'b').
Why, then, is Codewars giving me this error.
In this case, your function requires at least two characters to work. Try running duplicate_count('a') and see the error it throws. Add the following after n = len(sorted_chars):
if n < 2:
return 0
That will stop running the rest of the function and return 0 duplicates (because you can't have any if there's only one character).

Python 3 k-mers count errors

I have to solve a problem (problem and the code is given below) and I'm getting errors on executing this program.
Traceback (most recent call last):
File "C:/Python33/exercise1.py", line 9, in <module>
for n in range[len(string) - k]:
TypeError: unsupported operand type(s) for -: 'int' and 'list'
-
Frequent Words Problem: Find the most frequent k-mers in a string.
Input: A string Text and an integer k. [XGMcKJXnoMhmuXcsjswaejVunrrsDhoiWEzXbiKoiYBEpVmhJszFWCFJAHLPzKfKBhWbCABPCTqASGvgquUtnwSeeYkXtLcbzMxvcsUwjmhHfexpEEhjhjzKvYdODZeCgrehxUnYqDwYMBxaFsYAqIFsBSZslMmTNXPovRtRbqFOhMXMUErCnRgjiBIovOWXxlkYInG]
Output: All most frequent k-mers in Text.
My designed code is:
k=open("dataset_3_6.txt").readlines()
import string
string = str()
for k in string:
k = int(k)
kmer_count = {}
for n in range(len(string) - k):
c = string[n:n+k]
kmer_count[c] = kmer_count[c] + 1 if kmer_count.has_key(c) else 1
max = 0
max_kmer = []
for k,v in kmer_count.iteritems():
if v > max:
max_kmer = [k]
max = v
elif v == max:
max_kmer += [k]
print("max_kmer")
There are a huge number of problems right at the top:
import string
Why are you importing this module? Are you planning to use it?
string = str()
This hides the string module so you can never use it again, and creates a default (that is, empty) string (which is easier to do with string = '').
for k in string:
k = int(k)
Since string is an empty string, this loops zero times.
Even if it weren't empty, k = int(k) wouldn't have any effect; you're just rebinding the loop variable over and over again. If you wanted to replace the string string with a list of numbers, where each number is the integer value of the corresponding character in the string, you'd need to build a list, either by creating an empty list and calling append, or by using a list comprehension (e.g., string = [int(k) for k in string]). I have no idea whether that's what you're actually trying to do here.
Anyway, if string weren't empty, after the loop, k would be the int value of the last character in the string. But since it is, k is still the result of calling open("dataset_3_6.txt").readlines() earlier. That is, it's a list of lines. So, in this:
for n in range(len(string) - k):
You're trying to subtract that list of lines from the number 0. (Remember, you set string to an empty string, so its len is 0.)
I have no idea what you expected this to do.
Part of the confusion is that you have meaningless variable names, and you reuse the same names to refer to different things over and over. First k is the list of lines. Then it's a loop variable. Then… you apparently intended it to be something else, but I don't know what. Then, it's each key in a dictionary.

python: iteration over non sequence error

Just starting problem 164 for project euler, and i want a function to output a list of the sum of each set of 3 consecutive digits in a 20 digit number. Here is my function.
def func(n):
sumlist = []
m = str(n)
for i in range(0,18):
sumlist.append(sum(int(m[i])+int(m[i+1])+int(m[i+2])))
return sumlist
I keep getting the iteration over non sequence error and i can't figure out why i should. Any help would be appreciated, thanks.
EDIT
The full traceback is:
Traceback (most recent call last):
File "peproblem164.py", line 8, in ? print func(11201201201201201201)
File "peproblem164.py", line 5, in func
sumlist.append(sum(int(m[i])+int(m[i+1])+int(m[i+2])))
TypeError: iteration over non-sequence'
That's because
int(m[i]) + int(m[i+1]) + int(m[i+2])
isn't a sequence. It's an int. I believe you mean:
sumlist.append(sum((int(m[i]), int(m[i+1]), int(m[i+2]))
this will work because
(int(m[i]), int(m[i+1]), int(m[i+2]))
is a sequence.
All in all, it would be easier to work with a list of integers, rather than a string, so it would make sense to convert m into ints first:
m = map(int, str(n))
and then use Python's slicing syntax to get the subsequence sums:
for i in range(18): #Leaving out the start argument is equivalent to range(0, 18)
sumlist.append(sum(m[i:i+3]))
and it would be even more pythonic to use a list comprehension instead (not to mention faster):
sumlist = [m[i:i+3] for i in range(18)] #same thing as the for loop
You really don't need the sum call. Replace
sumlist.append(sum(int(m[i])+int(m[i+1])+int(m[i+2])))
with
sumlist.append(int(m[i])+int(m[i+1])+int(m[i+2]))

Categories