Simple selection sort in Python - 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

Related

Why does my insertion sort Algorithm return out of order

I am working on creating a basic insertion sort algorithm using Python.
My textbook shows the psudeocode of an insertion sort algorithm here.
If I follow that convention using python 3, I produce the following code:
def insertionSort(arr):
#Traverse through 1 to len array
for j in range(1, len(arr)):
key = arr[j]
i = j-1
while i >0 and arr[i] > key: #this line seems incorrect?
arr[i+1] = arr[i]
i = i-1
arr[i+1] = key
return arr
If I set
arr = [12,11,13,5,6]
The result returns as [12,5,6,11,12,13] which obviously is not a correct sort.
After tweaking with the algorithm for some time changing the line I marked as incorrect to while i>=0 and arr[i] > key:
the algorithm gives the correct output. Is my book incorrect in omitting the equal sign or am I not understanding how the psuedocode operates within my textbook?
It looks like you mostly correctly translated the book's algorithm into Python. As you see, the book's algorithm is 1-based while Python is 0-based.
The book's algorithm starts at index 2 but you have to start at index 1.
This also translates to keeping the while loop going until the first index. In the book's case, that's 1 and in your case it should be 0 in Python. So the book is correct but you are also correct (because of the differences in indexing conventions).
def insertionSort(arr):
#Traverse through 1 to len array
for j in range(1, len(arr)):
key = arr[j]
i = j-1
# you need to change here to i>=0
while i >= 0 and arr[i] > key: #this line seems incorrect?
arr[i+1] = arr[i]
i = i-1
arr[i+1] = key
return arr

bubble sort in python:index out of range

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

Index out of range in implementation of a variation of mergesort algorithm in python?

I have done a variation of my merge sort algorithm in python, based on what I've learnt from the CLRS book, and compared it with the implementation done on the introductory computer science book by MIT. I cannot find the problem in my algorithm, and the IDLE gives me an index out of range although everything looks fine to me. I'm unsure if this is due to some confusion in borrowing ideas from the MIT algorithm (see below).
lista = [1,2,3,1,1,1,1,6,7,12,2,7,7,67,4,7,9,6,6,3,1,14,4]
def merge(A, p, q, r):
q = (p+r)/2
L = A[p:q+1]
R = A[q+1:r]
i = 0
j = 0
for k in range(len(A)):
#if the list R runs of of space and L[i] has nothing to compare
if i+1 > len(R):
A[k] = L[i]
i += 1
elif j+1 > len(L):
A[k] = R[j]
j += 1
elif L[i] <= R[j]:
A[k] = L[i]
i += 1
elif R[j] <= L[i]:
A[k] = R[j]
j += 1
#when both the sub arrays have run out and all the ifs and elifs done,
# the for loop has effectively ended
return A
def mergesort(A, p, r):
"""A is the list, p is the first index and r is the last index for which
the portion of the list is to be sorted."""
q = (p+r)/2
if p<r:
mergesort(A, p, q)
mergesort(A, q+1, r)
merge (A, p, q, r)
return A
print mergesort(lista, 0, len(lista)-1)
I have followed the pseudocode in CLRS as closely as I could, just without using the "infinity value" at the end of L and R, which would continue to compare (is this less efficient?). I tried to incorporate ideas like that in the MIT book, which is to simply copy down the remaining L or R list to A, to mutate A and return a sorted list. However, I can't seem to find what has went wrong with it. Also, I don't get why the pseudo code requires a 'q' as an input, given that q would be calculated as (p+q)/2 for the middle index anyway. And why is there a need to put p
On the other hand, from the MIT book, we have something that looks really elegant.
def merge(left, right, compare):
"""Assumes left and right are sorted lists and
compare defines an ordering on the elements.
Returns a new sorted(by compare) list containing the
same elements as(left + right) would contain.
"""
result = []
i, j = 0, 0
while i < len(left) and j < len(right):
if compare(left[i], right[j]):
result.append(left[i])
i += 1
else :
result.append(right[j])
j += 1
while (i < len(left)):
result.append(left[i])
i += 1
while (j < len(right)):
result.append(right[j])
j += 1
return result
import operator
def mergeSort(L, compare = operator.lt):
"""Assumes L is a list, compare defines an ordering
on elements of L.
Returns a new sorted list containing the same elements as L"""
if len(L) < 2:
return L[: ]
else :
middle = len(L) //2
left = mergeSort(L[: middle], compare)
right = mergeSort(L[middle: ], compare)
return merge(left, right, compare)
Where could I have gone wrong?
Also, I think the key difference in the MIT implementation is that it creates a new list instead of mutating the original list. This makes it quite difficult for me to understand mergesort, because I found the CLRS explanation quite clear, by understanding it in terms of different layers of recursion occurring to sort the most minute components of the original list (the list of length 1 that needs no sorting), thus "storing" the results of recursion within the old list itself.
However, thinking again, is it right to say that the "result" returned by each recursion in the MIT algorithm, which is in turn combined?
Thank you!
the fundamental difference between your code and the MIT is the conditional statement in the mergesort function. Where your if statement is:
if p<r:
theirs is:
if len(L) < 2:
This means that if you were to have, at any point in the recursive call tree, a list that is of len(A) == 1, then it would still call merge on a size 1 or even 0 list. You can see that this causes problems in the merge function because then your L, R, or both sub lists can end up being of size 0, which would then cause an out if bounds index error.
your problem could then be easily fixed by changing your if statement to something alike to theirs, like len(A) < 2 or r-p < 2

(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

Python - Sorting lists of numbers

Just learning Python and got on to the subject of sorting lists. Two types of algorithms were shown: insertion and selection. So, I had an idea and created this:
def DiffSort(lst):
lstDiff = [None] * len(lst)
i = 0
while i < len(lst):
lstDiff[i] = lst[i] - lst[i-1] if i != 0 else lst[0]
if lstDiff[i] < 0:
sbj, tmp = lst[i], lstDiff[i]
while tmp < 0:
i -= 1
tmp += lstDiff[i]
lst[i+1] = lst[i]
lst[i] = sbj
else:
i += 1
lst = [13,25,18,122,32,1,0.78,25,85,1,32,56,0.55,0.6,17]
print(lst)
DiffSort(lst)
print(lst)
Any good? Is there a similar method out there already?
list.sort() if you want to sort a list in-place.
sorted(list) if you want to return a sorted copy of the list.
The second option works with any iterable type, whereas the first is list-exclusive (although some other types may have the same or a similar function defined as well, but you can generally not expect that).
Since you seem to care about the algorithmic part of it, this may be of interest to you:
http://svn.python.org/projects/python/trunk/Objects/listsort.txt
Isn't lst.sort() good enough? It's bound to be much faster than a Python solution that has to run in O(n^2) time.

Categories

Resources