string index out of range list iteration - python

I am fairly new to python, I am not sure on how to fix a index string out of range. it happens right after the while loop when I want to send mylist[i][0] to formatting function. Any pointer on my code in general would be awesome!
def formatting(str1):
if str1 == '?':
return True
else:
return False
while(i <= len(mylist)):
val = formatting(mylist[i][0])
if val == True:
str1 = mylist[i]
str2 = mylist[i+1]
i = i + 2
format_set(str1, str2)
else:
if format == True:
if (margin + count + len(mylist[i])) <= width:
if (i == (len(mylist)-1)):
list2.append(mylist[i])
print(" " * margin + " ".join(list2))
break
list2.append(mylist[i])
count += len(mylist[i])
i += 1
else:
print(" " * margin + " ".join(list2))
list2 = []
count = 0
else:
temp_margin = margin
temp_width = width
width = 60
margin = 0
if (margin + count + len(mylist[i])) <= width:
if (i == (len(mylist)-1)):
list2.append(mylist[i])
print(" " * margin + " ".join(list2))
margin = temp_margin
width = temp_width
break
list2.append(mylist[i])
count += len(mylist[i])
i += 1
else:
print(" " * margin + " ".join(list2))
list2 = []
count = 0

change
i <= len(mylist)
to
i < len(mylist)

In the last iteration of the while loop, i is referring to the last value. Hence,
str2 = mylist[i+1]
is trying to reference a string outside the allowed range and you get an error.
EDIT: Also, as Wcrousse mentioned, the while (i <= len(...)) should be changed to i < len(...) because indexes go from 0 - (length-1).

Related

Character counter should not display amount if amount is 1

def encode(message):
encoded_message = ""
i = 0
while (i <= len(message)-1):
count = 1
ch = message[i]
j = i
while (j < len(message)-1):
if (message[j] == message[j+1]):
count = count+1
j = j+1
else:
break
encoded_message=encoded_message+str(count)+ch
i = j+1
return encoded_message
#Provide different values for message and test your program
encoded_message=encode("ABBBBCCCCCCCCAB")
print(encoded_message)
This code generates the following output: 1A4B8C1A1B
But if the value is 1 it should just display the letter like this: A4B8CAB
Simply replace this line:
encoded_message=encoded_message+str(count)+ch
with this:
encoded_message += (str(count) if count > 1 else "") + ch
It should do the trick. Now it only appends the count to the string if said count is bigger than one.

How to replace all "&int-int" with the respective string slices in an input string?

I have a school project question (for Python) that goes like this:
Given a string_input such as "abcd&1-4efg", the function must remove the "&1-4" and insert the string slice from 1 to 4 where the "&1-4" was.
eg. if string_input = "abcd&1-4efg",
"&1-4" is removed.
The remaining characters are indexed as follows: a=0, b=1, c=2, d=3, e=4, f=5, g=6
The new string becomes:
"abcdbcdeefg"
I've managed to write a long chunk of code to do this, but I'm wondering if anyone has any more efficient solutions?
Things to note:
The instructions can include double digits (eg. &10-15)
If the index isn't found, the returned string should print "?" for every missing index
(eg. "abcd&5-10efgh" would return "abcdfgh???efgh")
Intructions can be back-to-back (eg. "&10-15abcdef&1-5&4-5pqrs")
The code I've written is:
def expand(text):
text += "|"
import string
digits_dash = string.digits + "-"
idx_ref_str = ""
replace_list = []
record_val = False
output_to_list = []
instruct = ""
and_idx_mark = 0
#builds replace_list & idx_ref_list
for idx in range(len(text)):
if text[idx] == "&" and record_val==True:
output_to_list.append(instruct)
output_to_list.append(and_idx_mark)
replace_list.append(output_to_list)
output_to_list, instruct, inst_idx, and_idx_mark = [],"",0,0
and_idx_mark = idx
continue
elif text[idx] == "&":
record_val = True
and_idx_mark = idx
continue
#executes if currently in instruction part
if record_val == True:
#adds to instruct
if text[idx] in digits_dash:
instruct += text[idx]
#take info, add to replace list
else:
output_to_list.append(instruct)
output_to_list.append(and_idx_mark)
replace_list.append(output_to_list)
output_to_list, instruct, inst_idx, and_idx_mark, record_val = [],"",0,0,False
#executes otherwise
if record_val == False:
idx_ref_str += text[idx]
idx_ref_str = idx_ref_str[:-1]
text = text[:-1]
#converts str to int indexes in replace list[x][2]
for item in replace_list:
start_idx = ""
end_idx = ""
#find start idx
for char in item[0]:
if char in string.digits:
start_idx += char
elif char == "-":
start_idx = int(start_idx)
break
#find end idx
for char in item[0][::-1]:
if char in string.digits:
end_idx = char + end_idx
elif char == "-":
end_idx = int(end_idx)
break
start_end_list = [start_idx,end_idx]
item+=start_end_list
#split text into parts in list
count = 0
text_block = ""
text_block_list = []
idx_replace = 0
for char in text:
if char == "&":
text_block_list.append(text_block)
text_block = ""
count += len(replace_list[idx_replace][0])
idx_replace +=1
elif count > 0:
count -= 1
else:
text_block += char
text_block_list.append(text_block)
#creates output str
output_str = ""
for idx in range(len(text_block_list)-1):
output_str += text_block_list[idx]
#creates to_add var to add to output_str
start_repl = replace_list[idx][1]
end_repl = replace_list[idx][1] + len(replace_list[idx][0])
find_start = replace_list[idx][2]
find_end = replace_list[idx][3]
if end_idx >= len(idx_ref_str):
gap = end_idx + 1 - len(idx_ref_str)
to_add = idx_ref_str[find_start:] + "?" * gap
else:
to_add = idx_ref_str[find_start:find_end+1]
output_str += to_add
output_str += text_block_list[-1]
return output_str
Here's how I would do it. Always open to criticism.
import re
s = 'abcd&1-4efg'
c = re.compile('&[0-9]+-[0-9]+')
if (m := c.search(s)):
a, b = m.span()
left = s[:a]
right = s[b:]
o = [int(x) for x in m.group(0)[1:].split('-')]
mid = (left+right)[o[0]:o[1]+1]
print(left + mid + right)

Output matches expected output. Yet submission is not being accepted

https://www.hackerrank.com/challenges/designer-door-mat/problem
Below is my submission:
n = input().split(' ')
rows, columns = int(n[0]), int(n[1])
if(rows % 2 == 1 and columns == 3*rows):
printale = ''
j = 1
k = rows - 7
for i in range(int(rows/2), -1, -1):
printale = '---'*i + '.|.'*j + '---'*i
if(i == 0):
print('-'*int(j+k/2) + 'Welcome' + '-'*int(j+k/2))
j -= 2
else:
print(printale)
j += 2
for l in range(1, int(rows/2)+1):
printale = '---'*l + '.|.'*j + '---'*l
print(printale)
j -= 2
Is there anything wrong with the code?
Yes, there is. The "WELCOME" in the problem statement is all-caps.

Can anyone please advise me where I'm going wrong with this binary search code? Unable to print index to user

def binarySearch(list, selection):
start = 0
end = len(list) - 1
while start <= end:
middle = start + (end - start) // 2
middleValue = list[middle]
if middleValue == selection:
return middle
elif selection < middleValue:
end = middle - 1
else:
start = middle + 1
return None
lista = [1, 5, 7, 10, 11, 19,]
print(lista)
selectiona = int(input('Enter a number to search for: '))
index = lista.index(selectiona)
binarySearch(lista, selectiona)
print(str(selectiona)) + "found at index " + str(index))
exit = input()
It works without printing the index, but this is a requirement. If anyone can advise me on what I'm doing wrong I'd be greatly appreciative. thanks
In the line print(str(selectiona)) + "found at index " + str(index)) your parentheses are wrong, you close one too many after selectiona. Try this instead:
print(str(selectiona) + "found at index " + str(index))
Additionally, the result of your binary search isn't what you're printing. Did you mean to do index = binarySearch(lista, selectiona) instead?
You are fetching the index using python modules in the line index = lista.index(selectiona) and you are not using the output provides by the binarySearch function.
def binarySearch(list, selection):
start = 0
end = len(list) - 1
while start <= end:
middle = start + (end - start) / 2
middleValue = list[middle]
if middleValue == selection:
return middle
elif selection < middleValue:
end = middle - 1
else:
start = middle + 1
return None
lista = [1, 5, 7, 10, 11, 19,]
print(lista)
selectiona = int(input('Enter a number to search for: '))
index = binarySearch(lista, selectiona)
if index:
print(str(selectiona) + " found at index " + str(index))
else:
print(str(selectiona) + " is not there in the list")
exit = input()

Genetic algorithm suspends in python?

I have implemented a simple genetic algorithm in python - here is the most of the code:
import random
ings = (('w1', 200, 25, 80),
('su1', 50, 55, 150),
('su2', 400, 100, 203),
('sy1', 10, 150, 355),
('sy2', 123, 88, 101),
('sy3', 225, 5, 30),
('sy4', 1, 44, 99),
('sy5', 500, 220, 300))
mutationRate = 0.2
crossoverRate = 0.9
iterations = 100
file = open('D:\\logfile2.txt', 'a')
class Ingredient:
def __init__(self, n, p, mi, ma):
self.name = n
self.price = p
self.min = mi
self.max = ma
self.perc = random.randrange(self.min, self.max)
class Drink:
def __init__(self):
self.ing = [Ingredient(*x) for x in ings]
self.normalize()
self.fitness = self.evaluate()
def normalize(self):
sum = 0
for x in self.ing:
sum += x.perc
if sum < 1000:
offset = 1000 - sum
while not offset == 0:
index = random.randrange(len(self.ing))
val = self.ing[index].max - self.ing[index].perc
threshold = random.randrange(val) if val > 0 else 0
threshold = threshold if threshold < offset else offset
self.ing[index].perc += threshold
offset -= threshold
if sum > 1000:
offset = sum - 1000
while not offset == 0:
index = random.randrange(len(self.ing))
val = self.ing[index].perc - self.ing[index].min
threshold = random.randrange(val) if val > 0 else 0
threshold = threshold if threshold < offset else offset
self.ing[index].perc -= threshold
offset -= threshold
def evaluate(self):
fitness = 0
for x in self.ing:
fitness += x.perc * x.price
return 300000 - fitness
class GeneticAlgorithm:
def __init__(self):
self.drinkList = [Drink() for x in range(8)]
self.pool = []
def mutate(self, index):
ing1, ing2 = random.randrange(8), random.randrange(8)
while ing1 == ing2:
ing2 = random.randrange(8)
ptr = self.drinkList[index].ing
ing1thr = ptr[ing1].max - ptr[ing1].perc
ing2thr = ptr[ing2].perc - ptr[ing2].min
if ing1thr & ing2thr:
change = random.randrange(ing1thr if ing1thr < ing2thr else ing2thr)
ptr[ing1].perc += change
ptr[ing2].perc -= change
def crossover(self, index1, index2):
ing1, ing2 = random.randrange(8), random.randrange(8)
while ing1 == ing2:
ing2 = random.randrange(8)
ptr1 = self.drinkList[index1].ing[:]
ptr2 = self.drinkList[index2].ing[:]
resultIndex1 = random.randrange(len(self.drinkList))
while True:
resultIndex2 = random.randrange(len(self.drinkList))
if not resultIndex1 == resultIndex2:
break
bias = 1 if ptr1[ing1].perc > ptr2[ing1].perc else -1
if bias == 1:
maxChange = min(ptr1[ing1].perc - ptr1[ing1].min,
ptr1[ing2].max - ptr1[ing2].perc,
ptr2[ing1].max - ptr2[ing1].perc,
ptr2[ing2].perc - ptr2[ing2].min)
if maxChange:
change = random.randrange(maxChange)
ptr1[ing1].perc -= change
ptr1[ing2].perc += change
ptr2[ing1].perc += change
ptr2[ing2].perc -= change
self.drinkList[resultIndex1].ing = ptr1[:]
self.drinkList[resultIndex2].ing = ptr2[:]
if bias == -1:
maxChange = min(ptr1[ing1].max - ptr1[ing1].perc,
ptr1[ing2].perc - ptr1[ing2].min,
ptr2[ing1].perc - ptr2[ing1].min,
ptr2[ing2].max - ptr2[ing2].perc)
if maxChange:
change = random.randrange(maxChange)
ptr1[ing1].perc += change
ptr1[ing2].perc -= change
ptr2[ing1].perc -= change
ptr2[ing2].perc += change
self.drinkList[resultIndex1].ing = ptr1[:]
self.drinkList[resultIndex2].ing = ptr2[:]
def roulette(self):
sum = 0
lst = []
for x in self.drinkList:
sum += x.fitness
lst.append(sum)
return lst
def selectOne(self):
selection = random.randrange(self.pool[-1])
index = 0
while selection >= self.pool[index]:
index += 1
return index
def selectCouple(self):
selection1 = random.randrange(self.pool[-1])
index1, index2 = 0, 0
while selection1 >= self.pool[index1]:
index1 += 1
while True:
selection2 = random.randrange(self.pool[-1])
while selection2 >= self.pool[index2]:
index2 += 1
if not index1 == index2: break
return (index1, index2)
def save(self, text):
file.write(text)
for x in self.drinkList:
for y in x.ing:
file.write('min: ' + str(y.min) +
' max: ' + str(y.max) +
' value: ' + str(y.perc) + '\n')
file.write('\n\n')
file.write('\nPopulation fitness: ' +
str(self.calculatePopulationFitness()) +
'\n\n----------------------------------------------\n\n')
def run(self):
file.write("Genetic algorithm\n\nAttributes values:\n" +
"Mutation rate: " + str(mutationRate) +
"\nCrossover rate: " + str(crossoverRate) +
"\nIterations: " + str(iterations) +
"\nIngredients:\n\n" + str(ings))
self.save('\n\n--First population--\n\n')
for cnt in range(iterations):
self.updateFitness()
self.pool = self.roulette()
if random.random() < mutationRate:
index = self.selectOne()
self.showFitness('Mutation in iteration ' + str(cnt))
self.mutate(index)
self.updateFitness()
self.showFitness('Results: ')
if random.random() < crossoverRate:
index1, index2 = self.selectCouple()
self.showFitness('Crossover in iteration ' + str(cnt))
self.crossover(index1, index2)
self.updateFitness()
self.showFitness('Results: ')
self.save('--Final population--\n\n')
def calculatePopulationFitness(self):
sum = 0
for x in self.drinkList:
sum += x.fitness
return sum
def updateFitness(self):
for x in self.drinkList:
x.fitness = x.evaluate()
def showFitness(self, text):
lst = [x.fitness for x in self.drinkList]
all = sum(lst)
file.write(text + '\n' + str(lst) + '||' + str(all) + '\n')
To run it I create an instance of GeneticAlgorithm and launch it through run() method.
The problem is, for low level of iterations the program works more or less fine, but if I set iteration to 50 for example, it seems to fall in infinite loop or suspend at random iteration (the logfile is not updated anymore and the program does not stop - happenes at random iteration). What can be the cause of this?
PS: Can you suggest any changes to the coding style? I'm quite new to python and i don't know all the conventions yet.
I don't completely understand your algorithm but it looks like your code hangs in this loop here:
while True:
selection2 = random.randrange(self.pool[-1])
while selection2 >= self.pool[index2]:
index2 += 1
if not index1 == index2: break
It gets to a point where you never get a value where index1 != index2. This could either indicate you have a mistake somewhere in your code, or that there isn't a situation that meets this condition. You could try putting a cap on the number of iterations of this, for example:
iters = 0
while iters < 5000:
selection2 = random.randrange(self.pool[-1])
while selection2 >= self.pool[index2]:
index2 += 1
iters += 1
if index1 != index2: break
if iters == 5000:
# Deal with not being able to identify a Couple
I know the question is more than a year old. Still I wanted a GA code in python to start with and found the problem.
while True:
selection2 = random.randrange(self.pool[-1])
while selection2 >= self.pool[index2]:
index2 += 1
if not index1 == index2: break
The problem is in this loop. once index2 is found to be equal it is not reset back to zero before trying to find a new value.
while True:
index2 = 0
selection2 = random.randrange(self.pool[-1])
while selection2 >= self.pool[index2]:
index2 += 1
if not index1 == index2: break

Categories