How to randomly change boolean value in a list - python

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

Related

Adding every other integer from 0 to n (recursive func)

The function I am writing is meant to add every other integer from 0 to n. For example, if you inputted 6, you would get 12 because 6 + 4 + 2 + 0 = 12.
I was working with a list at first but realized I have to be working with integers instead. Below is my attempt, but I get TypeError: object of type 'int' has no len().
I'm confused as to how to fix this problem and make it a proper recursive function.
def addNum(n):
if len(n) == 0:
return 0
else:
return n[0] + addNum(n[::2])
print(addNum(6)) #example of how you would call the function
If you are looking to add just the alternating integers, it should be like
def addNum(n):
if n < 1 :
return 0
else:
return n + addNum(n-2)
print(addNum(6))
You pass an Integer to your function addnum, but you need a list. So you have to write addnum([6]) to create a list with the 6 as a single entry.
You have to call the function with the argument, reduced by 2 if you want to work without a list.
def addnum(n):
if n == 0:
return 0
else:
return n + addnum(n - 2)
print(addnum(6))
This gives the output 12.
so first of all the func len() is for lengths and you actually don't need that, what you need is a list comprehension. I assume that you don't know them so go and learn about them because they can help with these kinds of functions because they aren't that hard to write and are highly flexible.
The code below here does exactly what you want!
def addnum(n):
if n == 0:
return 0
else:
return sum([list for list in range(0,n+1,2)])
print(addnum(10))
first I create a function named addnum which has one parameter called n.
secondly I created the if else clauses, if the number is equal to 0 it returns 0. Else it returns the sum of every odd integer from 0 the the range. n+1 is here just to get the number you put in because the func range doesn't include the last value.

Multiply squares function

I've been trying to write a function that can take a different number of integer parameters and return the product of the squares of the parameters.
output should be:
multiply_squares(3,2,1)
multiply_squares(2,5)
36
100
So far I've been playing around with this:
def multiply_squares(*num_tuple):
result = []
for num in num_tuple:
c = num_tuple[num]**2
result.append(c)
for i in result:
d *= result[i]
print(d)
multiply_squares(3,2,1)
multiply_squares(2,5)
I've been getting "tuple index out of range" and haven't been able to solve this properly. Could anyone help me out? And also show me how to turn this into a recursive function?(if possible)
I got a test on Tuesday and I'm trying to understand the logic behind this :)
Any feedback/guidance is appreciated !
for num in num_tuple means iterate over num_tuple and set each value to num. num isn't the index of the tuple.
def multiply_squares(*num_tuple):
result = []
for num in num_tuple:
c = num**2
result.append(c)
d = 1
for i in result:
d *= i
print(d)
return d
multiply_squares(3,2,1)
multiply_squares(2,5)
Regarding recursive solution:
def multiply_squares(*num_tuple):
if not num_tuple: # Base case:
return 1
return (num_tuple[0] ** 2) * multiply_squares(*num_tuple[1:])
Why the need for the intermediary list?
def multiply_squares(*num_tuple):
r = 1
for n in num_tuple:
r *= n * n
return r
and it works:
>>> multiply_squares(3,2,1)
36
>>> multiply_squares(2,5)
100
Recursively:
def multiply_squares(*num_tuple):
return num_tuple[0] ** 2 * multiply_squares(*num_tuple[1:]) if num_tuple else 1
Just to help with the understanding, I'll just print the inputs to each function call:
>>> multiply_squares(3,2,1)
(3, 2, 1)
(2, 1)
(1,)
()
36
So each guy who gets called knows: its job and its inputs (the numbers). So all it needs to return (either to the initial caller (you) or the guy above him) is what the product of the squares of inputs are.
To do this, the guy can break down his problem by just multiplying the square of the first input to whatever the result of the product of the squares of the other inputs is (through recursively calling himself).
And this will work perfectly... Until, eventually, there are no other inputs. In this case, what does the guy do? Well, this is a special case which will only be instantiated by another person solving the same problem as he is. And the person above him is relying on him to return the product of the squares of that guy's remaining inputs so he can multiply his result to that result. For that reason, he must return 1 otherwise the whole system wouldn't work.
In Python we can test whether the function had no inputs by checking the truthiness of the input tuple. This just so happens to equate to checking whether that data structure has any elements.
I.e.
bool(tuple()) #empty tuple
#False
bool((1,2,3)) #populated tuple
#True
We could just as easily checked whether the length of the tuple was equal (or in this case not equal) to 0.
I.e.
len(tuple()) != 0
#False
len((1,2,3)) != 0
#True
So walking it through:
num_tuple[0] ** 2 * multiply_squares(*num_tuple[1:]) if num_tuple else 1
# ^ ^ ^ ^ ^
# 1st input sqrd | by the prod of sqrs of rest | given inputs | otherwise 1
# multiplied only if
Why doesn't your code work:
The line:
for num in num_tuple:
iterates over the elements of the num_tuple tuple, not the indicies.
This means that in the first example, num will be 3, then 2 and then 1. Then, instead of indexing the num_tuple with what you thought were the indicies (0, 1 and 2) you are instead indexing with these inputs to the function.
This results in the out of range error as you try to index the tuple with 3 when the length of the tuple is only three elements long (making [2] the last index).
To remedy your solution, you could either change that line to:
for index in range(num_tuple):
and then your indexing will work (if you also replace all previous occurrences of num with index).
Alternatively, a better solution would be to scrap the indexing altogether and just use the elements directly as that is what you want.
That would look something like:
def multiply_squares(*num_tuple):
result = []
for num in num_tuple:
c = num**2
result.append(c)
r = 1
for i in result:
r *= i
return r
which now works as expected.
Please have a look at this two-line solution (because of the assertion) using functools.reduce:
from functools import reduce
a = (3, 2, 1)
b = (2, 5)
c = 2
def multiply_squares(*nums):
assert nums # make sure we get input
return reduce(lambda x, y: x * (y**2), nums, 1)
print(multiply_squares(*a))
print(multiply_squares(*b))
print(multiply_squares(c))
print(multiply_squares())
'''Output:
36
100
4
Traceback (most recent call last):
File "test.py", line 16, in <module>
print(multiply_squares())
File "test.py", line 9, in multiply_squares
assert nums
AssertionError
'''
which is actually very robust.

Why do I get a 'valueError' despite explicitly returning the expected number of values?

This is merge sort tweaked to count inversions. My code throws an odd error
(I'm implementing algos to learn python 3.x).
In line 11,
in merge_sort first_sorted_half, x = merge_sort(arr[:half])
[Previous line repeated 12 more times] ValueError: not enough values
to unpack (expected 2, got 1)
Even though I explicitly return two values? I'm new to python 3 so I'd like to understand exactly what's going on here, I can't seem to find a similar issue anywhere. A link to python docs for more on this would also be appreciated!
def merge_sort(arr):
if len(arr) <= 1:
return arr
half = int(len(arr)/2)
first_sorted_half, x = merge_sort(arr[:half])
second_sorted_half, y = merge_sort(arr[half:])
merged_halves, z = merge(first_sorted_half, second_sorted_half)
return merged_halves, x + y + z
def merge(first_half, second_half):
n = len(first_half) + len(second_half)
i = 0
j = 0
split_inversions = 0
ans = []
for k in range(n):
if i >= len(first_half):
ans.append(second_half[j])
j += 1
continue
if j >= len(second_half):
ans.append(first_half[i])
i += 1
continue
if first_half[i] > second_half[j]:
ans.append(second_half[j])
j += 1
split_inversions += len(first_half) - i
elif first_half[i] < second_half[j]:
ans.append(first_half[i])
i += 1
return ans, split_inversions
numbers = [3,2,1,4,5,6,8,10,9]
print(merge_sort(numbers))
The error you are getting says that your program executed that recursive call 12 times, and at the end it couldn't unpack the result.
What that means is, python expects you to return two values from merge_sort, because you unpack the result into first_sorted_half and x. However, when you return only arr from the condition len(arr) <=1, there is no value to unpack, only there exists the array.
So how you fix that is returning a value for the base case, like return arr, len(arr).
Whilst ilke444 is right - a bit more clarification is needed. To start: returning data variables is what you need but I do not know much about the len(arr) <=1 , and I am quite new to stackflow, I do not know this feature of Python 3. I specialize in Pygame/ standard packages.
First thing - arr in this "Code Snippet" (If it is) is not defined; and/or will need to be defined. Len stands for length as you know - and uses a quote (' ') to use it.
Like so:
len('arr')
would print:
3
because there are 3 Characters in this set. You are obviously new to python 3 as you said because the syntax is slightly different.
As this probably only solves the first bit - with this info I will leave you with 1 thing more.
Call to print requires a quote (' '),
Lists have [ ] Brackets instead of (),
Dictionaries have {} brackets and variables now require definition either by variable definition or function unless put in quote marks.
Thanks,
Jerry

Python Type Error: 'List' object is not callable

I'm getting this error with this small code content of Python27. Can anyone help me with this? Thanks in advance.
Run Time Error Traceback (most recent call last): File
"5eb4481881d51d6ece1c375c80f5e509.py", line 57, in
print len(arr) TypeError: 'list' object is not callable
global maximum
def _lis(arr , n ):
# to allow the access of global variable
global maximum
# Base Case
if n == 1 :
return 1
# maxEndingHere is the length of LIS ending with arr[n-1]
maxEndingHere = 1
"""Recursively get all LIS ending with arr[0], arr[1]..arr[n-2]
IF arr[n-1] is maller than arr[n-1], and max ending with
arr[n-1] needs to be updated, then update it"""
for i in xrange(1, n):
res = _lis(arr , i)
if arr[i-1] < arr[n-1] and res+1 > maxEndingHere:
maxEndingHere = res +1
# Compare maxEndingHere with overall maximum. And
# update the overall maximum if needed
maximum = max(maximum , maxEndingHere)
return maxEndingHere
def lis(arr):
# to allow the access of global variable
global maximum
# lenght of arr
n = len(arr)
# maximum variable holds the result
maximum = 1
# The function _lis() stores its result in maximum
_lis(arr , n)
return maximum
num_t = input()
len = [None]*num_t
arr = []
for i in range(0,num_t):
len[i] = input()
arr.append(map(int, raw_input().split()))
print len(arr)
break
You have created a list named len as you can see here from the fact that you're able to index it:
len[i] = input()
So naturally, len is no longer a function that gets the length of a list, leading to the error you receive.
Solution: name your len list something else.
That is what happens when you define a variable that is also a built-in function name.
Change the variable len to something else.

lndexError: list index out of range

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))

Categories