How to fix an 'index out of range' error in Python? - python

I would like to write en auxiliar function which is counting the occurences of every integer between 0 and li[-1], saying that li is a sorted list.
I can't see my mistake... I know what this kind of error message means, but I don't know where the variable j is reaching a limit.
def aux_compter_occurence(li):
resu = [0] * (li[-1]+1)
i = 0
j = 0
while i < (li[-1] + 1):
while li[j] == i:
resu[i] += 1
j +=1
i += 1
return resu
For example, with the input [2,4,4,4,7,8,8], the output should be [0,0,1,0,3,0,0,1,2]

collections.Counter can be passed an iteratable and will count each occurance, we can then use a simple comprehension to generate the result
import collections
def aux_compter_occurence(li):
counts = collections.Counter(li)
return [counts.get(i, 0) for i in range(li[-1] + 1)]
Or if you wish to use the previous method of incrementing the values in a list, you already know the index in the list because it is equal to the integer value. We can simplify quite a bit
def aux_compter_occurence(li):
resu = [0] * (li[-1] + 1)
for i in li:
resu[i] += 1
return resu

I added "j < len(li)" to your code and now it works.
def aux_compter_occurence(li):
resu = [0] * (li[-1]+1)
i = 0
j = 0
while i < (li[-1] + 1):
while j < len(li) and li[j] == i:
resu[i] += 1
j +=1
i += 1
return resu

Related

make function return something specific in a pre-set while-loop: How to approach an assignment

In the following code I am trying to figure out what to put into a list L for f(L) to return 3.
The logic of it makes me a bit confused.
Can someone help me out in how to approach this? I am thinking that it has to be a negative number as the code will only add 1 to 0 (cnt) when n (length of integer) is smaller than 0.
L = []
def f(L):
"""Function to return 3"""
n = len(L)
i = 0
cnt = 0
while i < n:
if L[i] < 0:
cnt = cnt + 1
i = i + 1
return cnt

Can't get out of While loop(Python 3.9)

I'm a new at programming, I like solving this euler questions and I know there are solutions for this problem but it's not about the problem at all actually.
So, i managed to create a working function for finding example: 33. triangular number. It works but i couldn't manage to properly desing my while loop. I wanted to make it like, it starts from first triangular checks it's divisors make list of it's divisors, checks the length of the divisors, because problem wants "What is the value of the first triangle number to have over five hundred divisors?" . But i never managed to work the while loop. Thank you for reading.
nums = [1]
triangles = [1]
divisors = []
def triangularcreator(x):
if x == 1:
return 1
n = 1
sum = 0
while n!=0:
n += 1
nums.append(n)
for i in range(len(nums)):
sum += nums[i]
triangles.append(sum)
sum = 0
if x == len(triangles):
n = 0
return triangles[-1]
counter = 1
while True:
for i in range(1, triangularcreator(counter) + 1):
if triangularcreator(counter) % i == 0:
divisors.append(i)
if len(divisors) == 500:
print(triangularcreator(counter))
break
counter +=1
divisors.clear()
You should try to change a few things, starting with calculating just once the value of triangularcreator(counter) and assigning this value to a variable that you can use in different points of your code.
Second, you create a loop which will be calculate always triangularcreator(1). At the end of each iteration you increase the value of counter+=1, but then at the beginign of the new iteration you assignt it again value 1, so it will not progress as you expect. Try this few things:
counter = 1
while True:
triangle = triangularcreator(counter)
for i in range(1, triangle + 1):
if triangle % i == 0:
divisors.append(i)
if len(divisors) == 500:
print(triangle )
break
counter +=1
Also these two arrays nums = [1], triangles = [1] should be declared and initialized inside the def triangularcreator. Otherwise you would be appending elements in each iteration
Edit: I believe it is better to give you my own answer to the problem, since you are doing some expensive operations which will make code to run for a long time. Try this solution:
import numpy as np
factor_num = 0
n = 0
def factors(n):
cnt = 0
# You dont need to iterate through all the numbers from 1 to n
# Just to the sqrt, and multiply by two.
for i in range(1,int(np.sqrt(n)+1)):
if n % i == 0:
cnt += 1
# If n is perfect square, it will exist a middle number
if (np.sqrt(n)).is_integer():
return (cnt*2)-1
else:
return (cnt*2)-1
while factor_num < 500:
# Here you generate the triangle, by summing all elements from 1 to n
triangle = sum(list(range(n)))
# Here you calculate the number of factors of the triangle
factor_num = factors(triangle)
n += 1
print(triangle)
Turns out that both of your while loop are infinite either in triangularcreatorin the other while loop:
nums = [1]
triangles = [1]
divisors = []
def triangularcreator(x):
if x == 1:
return 1
n = 1
sum = 0
while n:
n += 1
nums.append(n)
for i in range(len(nums)):
sum += nums[i]
triangles.append(sum)
sum = 0
if len(triangles) >= x:
return triangles[-1]
return triangles[-1]
counter = 1
while True:
check = triangularcreator(counter)
for i in range(1, check + 1):
if check % i == 0:
divisors.append(i)
if len(divisors) >= 500:
tr = triangularcreator(counter)
print(tr)
break
counter +=1
Solution
Disclaimer: This is not my solution but is #TamoghnaChowdhury, as it seems the most clean one in the web. I wanted to solve it my self but really run out of time today!
import math
def count_factors(num):
# One and itself are included now
count = 2
for i in range(2, int(math.sqrt(num)) + 1):
if num % i == 0:
count += 2
return count
def triangle_number(num):
return (num * (num + 1) // 2)
def divisors_of_triangle_number(num):
if num % 2 == 0:
return count_factors(num // 2) * count_factors(num + 1)
else:
return count_factors((num + 1) // 2) * count_factors(num)
def factors_greater_than_triangular_number(n):
x = n
while divisors_of_triangle_number(x) <= n:
x += 1
return triangle_number(x)
print('The answer is', factors_greater_than_triangular_number(500))

Mean, Median, and Mode in Python

I'm doing a statistical problem set in Python on Hackerrank. When I input a list of values to calculate the mode. It shows me a runtime error.
# Enter your code here. Read input from STDIN. Print output to STDOUT
N = int(input())
X = list(map(int, input().split()))
X.sort()
# Find the mean
mean = sum(X) / N
print(mean)
# Find the median
if N % 2 == 0:
median = (X[N//2] + X[N//2 - 1]) / 2
else:
median = X[N//2]
print(median)
# Find the mode
occurrence = list([1 for _ in range(N)])
for i in range(N):
for j in range(i+1, N):
if X[i] == X[j]:
occurrence += 1
if max(occurrence) == 1:
mode = min(X)
else:
mode = X[occurrence[max(occurrence)]]
print(mode)
When I take a 2500 input for X, it just shows me a runtime error.
This is the link to the test case
enter link description here
I use this when looking for mean, median, and mode
import numpy as np
from scipy import stats
n = int(input())
arr = list(map(int, input().split()))
print(np.mean(arr))
print(np.median(arr))
print(stats.mode(arr)[0][0])
You are trying to add 1 to occurence which is of list type:
Also, I'm sure this may be a copying mistake but your loop is incorrect:
for i in range(N):
for j in range(i+1, N):
if X[i] == X[j]:
occurrence += 1
# It will be
for i in range(N):
for j in range(i+1, N):
if X[i] == X[j]:
occurrence += 1
Then you might wanna change your occurrence to something like:
occurrence[i] += 1
# from
occurrence += 1
Hope this helps
I have run your code, here is the compile problem:
for i in range(N):
for j in range(i+1, N):
if X[i] == X[j]:
occurrence += 1
I think your meaning is if inside two for, like:
for i in range(N):
for j in range(i + 1, N):
if X[i] == X[j]:
occurrence += 1
but occurrence is list here, can't plus by one, I think you means to count the occurrence of int, and output the max one? you can use defaultdict or Counter here, but defaultdict is only in one loops.
# import collections
# import operator
# Find the mode
occurrence = collections.Counter(X)
# occurrence = collections.defaultdict(int)
#
# for i in range(N):
# occurrence[X[i]] += 1
mode = max(occurrence.items(), key=operator.itemgetter(1))[0]
print(mode)
Here is a Mean, Median, and Mode class.
import statistics
from collections import Counter
def median(list):
n = len(list)
s = sorted(list)
return (sum(s[n//2-1:n//2+1])/2.0, s[n//2])[n % 2] if n else None
def mean(list):
if len(list) == 0:
return 0
list.sort()
total = 0
for number in list:
total += number
return total / len(list)
def mode(list):
counter = Counter(list)
if len(counter) > 1:
possible_mode, next_highest = counter.most_common(2)
if possible_mode[1] > next_highest[1]:
return possible_mode[0]
return "None"

count an occurrence of a string in a bigger string

I am looking to understand what I can do to make my code to work. Learning this concept will probably unlock a lot in my programming understanding. I am trying to count the number of times the string 'bob' occurs in a larger string. Here is my method:
s='azcbobobegghakl'
for i in range(len(s)):
if (gt[0]+gt[1]+gt[2]) == 'bob':
count += 1
gt.replace(gt[0],'')
else:
gt.replace(gt[0],'')
print count
How do I refer to my string instead of having to work with integers because of using for i in range(len(s))?
Try this:
def number_of_occurrences(needle, haystack, overlap=False):
hlen, nlen = len(haystack), len(needle)
if nlen > hlen:
return 0 # definitely no occurrences
N, i = 0, 0
while i < hlen:
consecutive_matching_chars = 0
for j, ch in enumerate(needle):
if (i + j < hlen) and (haystack[i + j] == ch):
consecutive_matching_chars += 1
else:
break
if consecutive_matching_chars == nlen:
N += 1
# if you don't need overlap, skip 'nlen' characters of 'haystack'
i += (not overlap) * nlen # booleans can be treated as numbers
i += 1
return N
Example usage:
haystack = 'bobobobobobobobobob'
needle = 'bob'
r = number_of_occurrences(needle, haystack)
R = haystack.count(needle)
print(r == R)
thanks. your support help to birth the answer in. here what I have :
numBobs = 0
for i in range(1, len(s)-1):
if s[i-1:i+2] == 'bob':
numBobs += 1
print 'Number of times bob occurs is:', numBobs

Deleting element in a python list iterated by index

folks
i have the following code:
for i in range(len(self.corpses)):
for j in range(len(self.corpses))[i+1:]:
if self.corpses[i].collides(self.corpses[j]):
self.corpses[i] = self.corpses[i] + self.corpses[j]
self.corpses.remove(self.corpses[j])
but this keeps going out of index.I would like to know what I do to remove the corpse under those conditions.
Thanks in advance.
You changed the length of the list. You could use a while loop instead:
i, l = 0, len(self.corpses)
while i < l:
j = i + 1
while j < l:
if self.corpses[i].collides(self.corpses[j]):
self.corpses[i] = self.corpses[i] + self.corpses[j]
del self.corpses[j]
l -= 1
else:
j += 1
i += 1
This way you keep full control over all changes.

Categories

Resources