What is wrong wtih my Insertion Sort Code - python

I am trying to write code that is an insertion sort. I am trying to get the code to take 2 values and put them into a new list while sorting it. So far it just puts the values into the list without them being sorted, i'm not quite sure why
pos = 0
pos2 = 1
go = True
while go == True:
for i in range(len(ex)-1):
stack.append(ex[pos])
print(stack)
stack.append(ex[pos2])
print(stack)
if stack[pos] > stack[pos2]:
stack[pos], stack[pos2] = stack[pos2], stack[pos]
print(stack)
pos = pos + 2
pos2 = pos2 + 2
I know it's not efficient, but it is based off code i made for a bubble sort which does
go = True
add = 0
while go == True:
for i in range(len(ex)-1):
if ex[i] > ex[i+1]:
go = True
ex[i], ex[i+1] = ex[i+1], ex[i] #flips the numbers in the list
print(ex)
add = add + 1
if add >= len(ex):
go = False
EDIT
I have changed it drastically, but there is still a problem. It only swaps the values once, even if it needs to be swapped multiple times to be in the right place. Here is the code
pos = 0
while pos < len(ex)-1:
for i in range(len(ex)-1):
stack.append(ex[i])
print(stack)
if stack[i-1] > stack[i]:
stack[i-1], stack[i] = stack[i], stack[i-1]
pos = pos + 1
else:
pos = pos + 1

You have to compare ex[pos] with ex[pos2] then you append the right element first :
if ex[pos] > ex[pos2]:
stack[pos].append(ex[pos2])
else stack[pos].append(ex[pos])
print(stack)

Here is the pseudo code for a classic insertion sort from https://visualgo.net/sorting a great resource for learning sorting algorithms:
mark first element as sorted
for each unsorted element
'extract' the element
for i = lastSortedIndex to 0
if currentSortedElement > extractedElement
move sorted element to the right by 1
else: insert extracted element
And here is how you could implement insertion sort in python:
def insertion_sort(l):
for i in range(1, len(l)):
j = i-1
key = l[i]
while (l[j] > key) and (j >= 0):
l[j+1] = l[j]
j -= 1
l[j+1] = key
return l
Once you understand the basic insertion sort you should be able to understand where you went wrong in your implementation in that you are not properly storing stack[pos] in your implementation.

Related

python (passing parameters to functions)

I'm not really new to python but I came across this problem that has just puzzled me.
So I was solving the maze runner problem, using A* and then was finding the hardest possible maze for a given dimension. For this purpose, I created a function called generateHardMaze() that is called from the main function and takes an attribute newMaze.
Now here is where things get weird, when I change the value of newMaze in the if condition within the while loop the hardMaze value changes without the code entering the second if condition. I'm not really sure why this happening was hoping someone could help me.
I'm using pycharm as my IDE and python3.6.* if that makes any difference.
I'm sure this isn't how oops works but I'm thinking this is a python thing. Has anyone ever come across anything like this? If yes please sympathize.
Thanks in advance.
def solveMazeAManH(newMaze,rows,cols):
startTime = time.time()
backTrackPriority = []
setup_cells(rows, cols)
# start and end points of the maze
start = (0, 0)
end = (rows - 1, cols - 1)
current = start
print("The path to be take is: ")
print(current)
frinLength = 0
# traversing the neighbours
while current != end:
unvisited.remove(current)
neighboursDFSandA(newMaze, current, rows, cols)
heuristic = calManhattanDis(current, end) # finding the heuristic for every traversal
try:
if not currentNeighbours:
if not backTrackPriority:
print("No path available!")
return 0
else:
while not currentNeighbours:
current = nextPopMan(backTrackPriority, end)
backTrackPriority.remove(current)
neighboursDFSandA(newMaze, current, rows, cols)
neighbor = leastPathChildMan(heuristic, current, end)
backTrackPriority.append(current)
current = neighbor
print(current)
frinLength += 1
except:
print("No path Found!")
return 0
return frinLength
endTime = time.time()
print("The time taken to solve the maze using A* with manhattan distance: ")
print(startTime - endTime)
def generateHardMaze(newMazes):
rows = len(newMazes)
cols = len(newMazes[0])
hardMaze = newMaze
print("Solving the original maze!")
fringLength = solveMazeAManH(newMazes, rows, cols)
print("Creating new harder Maze:")
pFlag = True
pCout = 0
while pFlag:
count = 0
flag = True
while flag:
point = choice(setup_cells(rows, cols))
if (newMazes[point[0]][point[1]] == 1):
newMazes[point[0]][point[1]] = 0
else:
newMazes[point[0]][point[1]] = 1
if (fringLength < solveMazeAManH(newMazes, rows, cols)):
print("Harder Maze--------------------")
hardMaze = newMaze
fringLength = solveMazeAManH(newMazes, rows, cols)
count = 0
else:
count += 1
if count >= 10:
flag = False
print("one")
newMazes = creatMaze(rows)
pCout += 1
if pCout >= 100:
pFlag = False
print(hardMaze)

Without using built-in functions, a function should reverse a string without changing the '$' position

I need a Python function which gives reversed string with the following conditions.
$ position should not change in the reversed string.
Should not use Python built-in functions.
Function should be an efficient one.
Example : 'pytho$n'
Result : 'nohty$p'
I have already tried with this code:
list = "$asdasdas"
list1 = []
position = ''
for index, i in enumerate(list):
if i == '$':
position = index
elif i != '$':
list1.append(i)
reverse = []
for index, j in enumerate( list1[::-1] ):
if index == position:
reverse.append( '$' )
reverse.append(j)
print reverse
Thanks in advance.
Recognise that it's a variation on the partitioning step of the Quicksort algorithm, using two pointers (array indices) thus:
data = list("foo$barbaz$$")
i, j = 0, len(data) - 1
while i < j:
while i < j and data[i] == "$": i += 1
while i < j and data[j] == "$": j -= 1
data[i], data[j] = data[j], data[i]
i, j = i + 1, j - 1
"".join(data)
'zab$raboof$$'
P.S. it's a travesty to write this in Python!
A Pythonic solution could look like this:
def merge(template, data):
for c in template:
yield c if c == "$" else next(data)
data = "foo$barbaz$$"
"".join(merge(data, reversed([c for c in data if c != "$"])))
'zab$raboof$$'
Wrote this without using any inbuilt functions. Hope it fulfils your criteria -
string = "zytho$n"
def reverse(string):
string_new = string[::-1]
i = 0
position = 0
position_new = 0
for char in string:
if char=="$":
position = i
break
else:
i = i + 1
j = 0
for char in string_new:
if char=="$":
position_new = i
break
else:
j = j + 1
final_string = string_new[:position_new]+string_new[position_new+1:position+1]+"$"+string_new[position+1:]
return(final_string)
string_new = reverse(string)
print(string_new)
The output of this is-
nohty$x
To explain the code to you, first I used [::-1], which is just taking the last position of the string and moving forward so as to reverse the string. Then I found the position of the $ in both the new and the old string. I found the position in the form of an array, in case you have more than one $ present. However, I took for granted that you have just one $ present, and so took the [0] index of the array. Next I stitched back the string using four things - The part of the new string upto the $ sign, the part of the new string from after the dollar sign to the position of the $ sign in the old string, then the $ sign and after that the rest of the new string.

List of lists Python. Multiple controls

I have a list of lists.
Each element of the list is made in this way [id1, id2, timex, value].
Given two external numbers ex and lx (ex < lx), I want to:
1. Check each element of the list, and see if timex < ex. If I find an element in which timex < ex, then I can end everything.
2. If I don't find it, then I want to make another check, starting for the first element of the list, and see if I can find an element in which ex < timex < lx.
3. If I don't find what said in point 2, I want to make another control and check whether there is an element with timex > lx.
What I did is this. But I want to know if there is a better way to do it.
f1 = 0
f2 = 0
found = False
# 1
count = 0
while (found == False) and (count < len(Listx)):
if Listx[count][2] <= ex:
print "Found - 1"
f1 = Listx[count][0]
f2 = Listx[count][1]
Listx[count][2] = Listx[count][2] + dx
found = True
count = count + 1
# 2
count = 0
while (found == False) and (count < len(Listx)):
if (Listx[count][2] > ex) and (Listx[count][2] <= lx):
print "Found - 2"
Listx[count][2] = Listx[count][2] + ex
f1 = Listx[count][0]
f2 = Listx[count][1]
found = True
count = count + 1
#3
count = 0
while (found == False) and (count < len(Listx)):
if (Listx[count][1] < lx):
f1 = Listx[count][0]
f2 = Listx[count][1]
found = True
count = count + 1
You don't necessarily need to index your list with 'count' every time, you can use for loops to iterate through. If you need that index for something else, you can use a for loop in the style of
for index, value in enumerate(lst):
# code
There are also some other modules that could help, depending on the nature of your data. See test if list contains a number in some range for examples of a few.
That said, here's my solution.
f1 = 0
f2 = 0
found = False
for element in Listx :
if element[2] <= ex:
print "Found - 1"
f1 = element[0]
f2 = element[1]
element[2] = element[2] + dx
found = True
break
if found = False:
for element in Listx :
if (element[2] > ex) and (element[2] <= lx):
print "Found - 2"
element[2] = element[2] + ex
f1 = element[0]
f2 = element[1]
found = True
break
if found = False:
for element in Listx :
if (element[1] < lx):
print "Found - 3"
f1 = element[0]
f2 = element[1]
found = True
break
You can write things a lot more compactly using for loops and for...else statements.
# 1
for item in Listx:
if item[2] <= ex:
print ("Found - 1")
f1, f2 = item[:2]
item[2] += dx
break
else:
# begin # 2 here...
The other loops can be similarly condensed. To describe the syntax going on here:
for x in y:
// ...
is essentially
i = 0
while i < len(y):
x = y[i]
// ...
i = i + 1
except that you don't get the i variable.
item[:1] uses list slicing to give us item[0], item[1].
Now something like a, b = x, y sets the variables respectively. It's shorthand for
a = x
b = y
Finally, break will break you out of the current loop immediately. The else is another fancy Python thing. The else code triggers when the previous loop was not broken out of.
I'll admit I used some "Pythonic" shortcuts above that use some of the features that I think makes Python great. :)

Project Euler Project 67 - Python

I am doing the Project Euler #67 in Python. My program, which worked for Project 18, does not work for Project 67.
Code (excludes the opening of the file and the processing of information):
for i in range(len(temp)):
list1 = temp[i]
try:
list2 = temp[i+1]
trynum1 = list1[lastinput] + max(list2[lastinput],list2[lastinput+1])
try:
trynum2 = list1[lastinput+1] + max(list2[lastinput+1],list2[lastinput+2])
if trynum1 > trynum2:
outputlist.append(list1[lastinput])
else:
outputlist.append(list1[lastinput+1])
lastinput += 1
except IndexError:
outputlist.append(list1[0])
except IndexError:
if list1[lastinput] > list1[lastinput+1]:
outputlist.append(list1[lastinput])
else:
outputlist.append(list1[lastinput+1])
Variables:
temp is the triangle of integers
outputlist is a list which stores the numbers chosen by the program
I know the answer is 7273, but my program finds 6542. I cannot find an error which causes the situation. Please may you help me on it.
Logic
My approach to this program is to find one number (list1[lastinput]) and add it up with the larger number of the two below it (trynum1), compare with the number to the right of the first number (list1[lastinput+1]), adding the larger number of two below it (trynum2). I append the larger one to the output list.
This approach is logically flawed. When you're in row 1, you don't have enough information to know whether moving right or left will lead you to the largest sum, not with only a 2-row lookahead. You would need to look all the way to the bottom to ensure getting the best path.
As others have suggested, start at the bottom and work up. Remember, you don't need the entire path, just the sum. At each node, add the amount of the better of the two available paths (that's the score you get in taking that node to the bottom). When you get back to the top, temp[0][0], that number should be your final answer.
I thought day and night about problem 18 and I solved it, the same way I solved this one.
P.S. 100_triangle.txt is without 1st string '59'.
# Maximum path sum II
import time
def e67():
start = time.time()
f=open("100_triangle.txt")
summ=[59]
for s in f:
slst=s.split()
lst=[int(item) for item in slst]
for i in range(len(lst)):
if i==0:
lst[i]+=summ[i]
elif i==len(lst)-1:
lst[i]+=summ[i-1]
elif (lst[i]+summ[i-1])>(lst[i]+summ[i]):
lst[i]+=summ[i-1]
else:
lst[i]+=summ[i]
summ=lst
end = time.time() - start
print("Runtime =", end)
f.close()
return max(summ)
print(e67()) #7273
Though starting from the bottom is more efficient, I wanted to see if I could implement Dijkstra's algorithm on this one; it works well and only takes a few seconds (didn't time it precisely):
from math import inf
f = open("p067_triangle.txt", "r")
tpyramid = f.read().splitlines()
f.close()
n = len(tpyramid)
pyramid = [[100 - int(tpyramid[i].split()[j]) for j in range(i+1)] for i in range(n)]
paths = [[inf for j in range(i+1)] for i in range(n)]
paths[0][0] = pyramid[0][0]
def mini_index(pyr):
m = inf
for i in range(n):
mr = min([i for i in pyr[i] if i >= 0]+[inf])
if mr < m:
m, a, b = mr, i, pyr[i].index(mr)
return m, a, b
counter = 0
omega = inf
while counter < n*(n+1)/2:
min_weight, i, j = mini_index(paths)
if i != n-1:
paths[i+1][j] = min( paths[i+1][j], min_weight + pyramid[i+1][j])
paths[i+1][j+1] = min( paths[i+1][j+1], min_weight + pyramid[i+1][j+1])
else:
omega = min(omega, min_weight)
paths[i][j] = -1
counter += 1
print(100*n - omega)
Here is my solution. Indeed you have to take the bottom - up approach.
Result confirmed with PE. Thanks!
def get_triangle(listLink):
triangle = [[int(number) for number in row.split()] for row in open(listLink)]
return triangle
listOfLists = get_triangle('D:\\Development\\triangle.txt')
for i in range(len(listOfLists) - 2, -1, -1):
for j in range(len(listOfLists[i])):
listOfLists[i][j] += max(listOfLists[i+1][j], listOfLists[i+1][j+1])
print(listOfLists[0][0])

How to do an insertion sort on a list of dictionaries in python?

I have a list of dictionaries with various keys, all of which are integers, and I need to write a function which uses insertion sort to sort them by the specific key.
def insertionsort(alldata, key):
for i in alldata :
temp = alldata[i]
j = i
while j > 0 and alldata[i['key']] < alldata[j - 1['key']]: # no idea how to put this
alldata[j] = alldata[j-1]
alldata[j] = temp
i['key'] looks like mistake. You aren't using your key variable here.
Try alldata[i][key] < alldata[j - 1][key] as a condition
Also you need to change j in your while loop or it can ran forever
def insertionsort(alldata, key):
for i in alldata :
temp = alldata[i]
j = i
while j > 0 and alldata[i][key] < alldata[j - 1][key]:
alldata[j] = alldata[j - 1]
j -= 1
alldata[j] = temp
Every thing after the for loop shuld be indented 1 more time (whatever number of spaces you use for indenting)
As for any other issues, I dont know.

Categories

Resources