bubble sort in python:index out of range - python

I am new to python and I was trying out bubble sort. Not able to find the error.
Little help here.
def bubble(n, list):
for i in range(0, n):
for j in range(0, n - i - 1):
if list[j] > list[j + 1]:
list[j],list[j+1] = list[j + 1],list[j]
def main():
n = input('size')
n = int(n)
list = []
for i in range(0, n):
no = input('no')
list + [no]
bubble(n, list)
print(list)
main()
During execution, it's showing:
line 4, in bubble
if (list[j] > list[j + 1]):
IndexError: list index out of range
But I couldn't find out how. The index always will be

The first problem is that you don't convert the input('no') to int. It is not the cause of the current problem, but would cause problems later.
The second problem is that you use list as a variable name. list is a predefined Python class and you will overwrite it. Choose a different name.
The third problem is that you use list + [no]. That will not add no to list. It would just store the output temporarily and delete it automatically. There are 2 solutions:
1. Using +=
a += b is equal to a = a + b. This is also the case for many arithmetical operators. Just replace + with +=.
2. Using append
append is faster. Use it like somelist.append(somevalue).

Related

List index out of bounds and stack overflow error

I am trying to get the max pair wise product using python this time around and the concepts of certain aspects are still new to me. I continue to get a list index out of bounds error and stackoverflows of which I do not know how to deal with given the fact that I can not choose types in Python.
I looked into enumerate and other iterate(ble) functions but to no avail. Id answered this could help future people with simple for loop questions in migration from C to python.
def max_pairwise_product(numbers):
n = len(numbers)
max_product = 0
for first in range(n):
for second in range(first + 1, n):
max_product = max(max_product,
numbers[first] * numbers[second])
return max_product
def max_pairwise_product_fast(numbers):
n = len(numbers)
index1 = 1
for i in range(2,n,1):
if (numbers[i]>numbers[index1]):
index1 = i
if (index1 == 1):
index2 = 2
else:
index2=1
for i in range(1,n):
if(numbers[i]!=numbers[index1] and numbers[i]>numbers[index2]):
index2 = i
return (numbers[index1]*numbers[index2])
if __name__ == '__main__':
input_n = int(input())
input_numbers = [int(x) for x in input().split()]
print(max_pairwise_product_fast(input_numbers))
Traceback (most recent call last):
File "C:/Users/Tevin/.PyCharmCE2018.3/config/scratches/scratch_1.py", line 31, in <module>
print(max_pairwise_product_fast(input_numbers))
File "C:/Users/Tevin/.PyCharmCE2018.3/config/scratches/scratch_1.py", line 27, in max_pairwise_product_fast
return (numbers[index1]*numbers[index2])
IndexError: list index out of range
why dont you find the 2 max numbers in your list and multiply them to get the max product. find the max of list then save it in some variable. remove it from the list and find the max again. then multiply this with your saved variable.
as for your code, what is this line for?
input_n = int(input())
you are not using the input_n variable anywhere.
and the line:
input_numbers = [int(x) for x in input().split()]
your code will ask you for 2 inputs. when you first enter your input, it is saved in the input_n variable. then your second input is saved as input_numbers. something is wrong with the type of input you are giving the program.
If I understand your max_pairwise_product_fast correctly, you are trying to find the largest and second largest number and multiply them. The problem is that you initialize index1 as 1, and index2 with 1 or 2, but array-indexes start with 0. Thus, your code will fail for a list with only two elements, e.g. [1,2]. Change the starting indices to 0, and change the range in the loops accordingly, and it will work.
You can also remove some of the checks, e.g. the if/else, as that's redundant with the check you have in your second loop. Also, by comparing number[index1] and number[index2] you could miss the highest product if the highest number appears twice, e.g. [1,2,2].
Staying close to your original code, you can try this:
def max_pairwise_product_fast(numbers):
n = len(numbers)
index1 = 0
for i in range(n):
if numbers[i] > numbers[index1]:
index1 = i
index2 = 0
for i in range(n):
if index2 != index1 and numbers[i] > numbers[index2]:
index2 = i
return numbers[index1] * numbers[index2]
But you could also use max instead of those two loops:
def max_pairwise_product_fast(numbers):
n = len(numbers)
index1 = max(range(n), key=lambda i: numbers[i])
index2 = max((i for i in range(n) if i != index1), key=lambda i: numbers[i])
return numbers[index1] * numbers[index2]
Or sort the entire array and pick the highest two:
def max_pairwise_product_fast(numbers):
second, first = sorted(numbers)[-2:]
return first * second
Note, however, that this might still fail if the list includes negative numbers, e.g. [1, 2, -3, -4]. For this, you could call the same function again with all the numbers in the list negated and pick the higher of the two results.

How to update array Index in loop (IndexError: list index out of range)

I should not use advance function, as this is a logical test during interview.
Trying to remove all digits which appear more than once in array.
testcase:
a=[1,1,2,3,2,4,5,6,7]
code:
def dup(a):
i=0
arraySize = len(a)
print(arraySize)
while i < arraySize:
#print("1 = ",arraySize)
k=i+1
for k in range(k,arraySize):
if a[i] == a[k]:
a.remove(a[k])
arraySize -= 1
#print("2 = ",arraySize)
i += 1
print(a)
result should be : 1,2,3,4,5,6,7
But i keep getting index out of range. i know that it is because the array list inside the loop changed, so the "while" initial index is different with the new index.
The question is : any way to sync the new index length (array inside the loop) with the parent loop (index in "while" loop) ?
The only thing i can think of is to use function inside the loop.
any hint?
Re-Calculating Array Size Per Iteration
It looks like we have a couple issues here. The first issue is that you can't update the "stop" value in your inner loop (the range function). So first off, let's remove that and use another while loop to give us the ability to re-calculate our array size every iteration.
Re-Checking Values Shifted Into Removed List Spot
Next, after you fix that you will run into a larger issue. When you use remove it moves a value from the end of the list or shifts the entire list to the left to use the removed spot, and you are not re-checking the value that got moved into the old values removed spot. To resolve this, we need to decrement i whenever we remove an element, this makes sure we are checking the value that gets placed into the removed elements spot.
remove vs del
You should use del over remove in this case. remove iterates over the list and removes the first occurrence of the value and it looks like we already know the exact index of the value we want to remove. remove might work, but it's usage here over complicates things a bit.
Functional Code with Minimal Changeset
def dup(a):
i = 0
arraySize = len(a)
print(arraySize)
while i < arraySize:
k = i + 1
while k < arraySize: # CHANGE: use a while loop to have greater control over the array size.
if a[i] == a[k]:
print("Duplicate found at indexes %d and %d." % (i, k))
del a[i] # CHANGE: used del instead of remove.
i -= 1 # CHANGE: you need to recheck the new value that got placed into the old removed spot.
arraySize -= 1
break
k += 1
i += 1
return a
Now, I'd like to note that we have some readability and maintainability issues with the code above. Iterating through an array and manipulating the iterator in the way we are doing is a bit messy and could be prone to simple mistakes. Below are a couple ways I'd implement this problem in a more readable and maintainable manner.
Simple Readable Alternative
def remove_duplicates(old_numbers):
""" Simple/naive implementation to remove duplicate numbers from a list of numbers. """
new_numbers = []
for old_number in old_numbers:
is_duplicate = False
for new_number in new_numbers:
if old_number == new_number:
is_duplicate = True
if is_duplicate == False:
new_numbers.append(old_number)
return new_numbers
Optimized Low Level Alternative
def remove_duplicates(numbers):
""" Removes all duplicates in the list of numbers in place. """
for i in range(len(numbers) - 1, -1, -1):
for k in range(i, -1, -1):
if i != k and numbers[i] == numbers[k]:
print("Duplicate found. Removing number at index: %d" % i)
del numbers[i]
break
return numbers
You could copy contents in another list and remove duplicates from that and return the list. For example:
duplicate = a.copy()
f = 0
for j in range(len(a)):
for i in range(len(duplicate)):
if i < len(duplicate):
if a[j] == duplicate[i]:
f = f+1
if f > 1:
f = 0
duplicate.remove(duplicate[i])
f=0
print(duplicate)

Python: Int is object is not subscriptable

I know this is a topic that there are already several threads for. I've reviewed them and understand what this error means, but for some reason cannot get it to work for my code.
I'm trying to code a simple Python function that takes a list of integers as input and outputs the integers in the list that are exactly twice the amount of the previous integer in the list. Here is the code I have so far:
def doubles(lst):
i = -1
for num in lst:
if num == num[i + 1] / 2:
print(num)
Now I know the issue is that it is trying to print this integer as a string. I have tried editing the codes last line to say print(str(num)) and that does not work, nor does changing my if statement in line 4. Any assistance would be greatly appreciated!
if num == num[i + 1] / 2:
should be
if num == lst[i + 1] / 2:
Also, I recommend using enumerate to iterate over the list with indexes, but there are better ways of doing such a thing, as shown in galaxyan's answer
you can zip original list and list begin from second element,then compare two elements
def doubles(lst):
return [ i for i,j in zip(lst,lst[1:]) if j==i*2 ]
example:
lst = [1,2,3,5,66,2,4,5]
print doubles(lst)
[1, 2]
You're attempting to subscript an item in the list, not the list itself. Instead of iterating the items, you could iterate the list's indexes:
def doubles(lst):
for i in range(0, len(lst) - 1):
if lst[i] == lst[i + 1] / 2:
print(lst[i])

Simple selection sort in Python

I've seen the following code for the selection sort algorithm in Python, my question is more to do with the functionality of python than the algorithm.
def Selectionsort(A):
for i in range (0,len(A)-1):
minIndex=i
for j in range (i+1,len(A)):
if A[j]<A[minIndex]:
minIndex=j
if minIndex !=i:
A[i],A[minIndex]=A[minIndex],A[i]
A=[10,7,6,4,5,3,1,8,2,9]:
Selectionsort(A)
print(A)
My question is why after applying Selectionsort(A) does the new A equal the original A but in the sorted order? Why does Print(A) not return the original A?
how do i get my code to indent like it does written in the programme after pasting it?
I feel bad when I see code written in an actual programming language as if it was Pascal-pseudocode nonsense, so here's how the original idea of this code would look like if written using Python coding conventions:
def selection_sort(unsorted):
for i in range(len(unsorted) - 1):
min_index = i
for j in range(i + 1, len(unsorted)):
if unsorted[j] < unsorted[min_index]:
min_index = j
# You don't really need this if, if you don't check
# for this condition, the swap is going to be a noop
if min_index != i:
# This line swaps two elements of `unsroted' list
# by destructively modifying it
unsorted[i], unsorted[min_index] = unsorted[min_index], unsorted[i]
print unsorted
return unsorted
Still, this is very non-idiomatic Python, a more Python-like code would be something like this:
def selection_sort(unsorted):
for i in range(len(unsorted) - 1):
idx = min(enumerate(unsorted[i:]), key=lambda x: x[1])[0]
unsorted[i], unsorted[i + idx] = unsorted[i + idx], unsorted[i]
return unsorted

(Python) Checking the 3x3 in a Sudoku, are there better ways to do this?

My partner in a summative for HS gave me this algorithm, I was hoping somebody could tell me if there is a more eloquent way of coding this..
CB is current board position(global), its a list of lists.
for a in xrange(0, 3):
for b in xrange(0, 3):
for j in xrange(1, 4):
for k in xrange(1, 4):
boxsum += CB[3a + j][3b + k]
if not(boxsum == 45):
return False
boxsum = 0
First, the following code is not indented correctly:
if not(boxsum == 45):
return False
boxsum = 0
(with the current indentation it will always fail on the first time this code is executed)
Second, in the following line:
boxsum += CB[3a + j][3b + k]
you probably meant to do:
boxsum += CB[3*a + j][3*b + k]
And last, in order to check a 3x3 part of sudoku game it is not enough to check the sum - you should also check that every number between 1-9 is present (or in other words, that all the numbers are in the range 1-9 and there is no number that appears more than once).
There are dozens of "cleaner" ways to do so.
First of all, why not use numpy for matrices, where you are obviously working with a matrix? I am assuming your numeration (which is a bit odd, why you start numerating from "1"?)
import numpy as np
CB = np.array(CB)
def constraint3x3check(CB):
return np.all(np.sum( CB[3*a+1:3*a+3, 3*b+1:3*b+3)==45 for a in range(3) for b in range(3))
Given the sum of the box equals 45, that doesn't mean there are all 1-9 numbers present.
You could for example add your numbers to set and check if the length of the set is always 9.
Since the sum 45 does not mean the answer is correct, necessarily, a different way is needed. Personally, I would join the rows into a single list and compare them to the list (1,2,...9), e.g.
#assuming this is your format...
box = [[4,2,3],[1,5,9],[8,7,6]]
def valid_box(box):
check_list = []
for row in box:
check_list += row
return list(range(1,10)) == sorted(check_list)
Although the code creating the list could also be done with list comprehension (I have no idea which one is more efficient, processor-wise)
def valid_box2(box):
return list(range(1,10)) == sorted( [item for row in box for item in row ] )
Merge list code taken from Making a flat list out of list of lists in Python

Categories

Resources