I can't seem to make my selection sort work. Any idea whats wrong? When run it gives me [5,6,3,1]
Thx!
aList = [1,5,6,3]
def selection_sort( aList):
for i in range(len(aList)):
min = i
j = i + 1
for j in range(len(aList)):
if aList[j] < aList[min]:
min = j
swap(aList, min, i)
print(aList)
def swap(aList, x, y):
temp = aList[x]
aList[x] = aList[y]
aList[y] = temp
selection_sort(aList)
As I mentioned in the comment, it seemed to me that you used j = i + 1 in hopes that it will somehow effect the j in the subsequent loop, but it is a different variable. So is the aList in your function definition, it can have any name, even aList. Your j is iterating over the entire list again and again and hence the min or the smallest value is carried wherever i goes (so it ended up in the end). So what you need to do is make your second loop only iterate through the next items after i.
aList = [1,5,6,3]
def selection_sort(List):
for i in range(len(List)):
min = i
for k in range(i,len(List)):
if List[k] < List[min]:
min = k
swap(List, min, i)
print(List)
def swap(List, x, y):
temp = List[x]
List[x] = List[y]
List[y] = temp
selection_sort(aList)
def select_sort(l):
for i in range(len(l)):
min_loc = i
for j in range(i+1, len(l)):
if l[j] < l[min_loc]:
min_loc = j
l[min_loc],l[i] = l[i], l[min_loc]
return l
Related
I was trying to use heap sort to sort an array into descending order but I ran into some problems. Here is my current code:
def heap(list):
for i in range(len(list)//2-1, len(list)):
heapify(list, i, len(list))
for i in range(0, len(list)-1):
list[i], list[0] = list[0], list[i]
heapify(list, 0, i)
def heapify(list, i, n):
left = len(list) - (2*i+1)
right = len(list)-(2*i+2)
print(left, right)
largest = i
if left < n and list[left] > list[largest]:
largest = left
if right < n and list[right] > list[largest]:
largest = right
if largest != i:
list[i], list[largest] = list[largest], list[i]
heapify(list, largest, n)
I'm not sure where I went wrong. Could someone please help me? Thanks in advance
You could just implement a traditional heap sort and allow for a reverse parameter (just like the built-in sort functionality). Then test for it and use a reversing slice if required.
Note that this implementation sorts in situ
import random
def heapify(lst, n, i):
m = k if (k := 2 * i + 1) < n and lst[i] < lst[k] else i
if (k := k + 1) < n and lst[m] < lst[k]:
m = k
if m != i:
lst[i], lst[m] = lst[m], lst[i]
heapify(lst, n, m)
def heap(lst, reverse=False):
n = len(lst)
for i in range(n//2, -1, -1):
heapify(lst, n, i)
for i in range(n-1, 0, -1):
lst[i], lst[0] = lst[0], lst[i]
heapify(lst, i, 0)
if reverse:
lst[:] = lst[::-1]
a = [random.randint(1, 10_000) for _ in range(1_000)]
b = a[::]
heap(a)
assert a == sorted(b)
a = [random.randint(1, 10_000) for _ in range(1_000)]
b = a[::]
heap(a, reverse=True)
assert a == sorted(b, reverse=True)
Note:
This is interesting as a pure programming exercise but should not be used to replace Python's built-in (and very efficient) sorting functionality
So I have this code in python and currently it only returns the maximum value for cutting a rod. How can I modify this to also give me where the cuts were made? It takes a list of prices whose indices+1 correspond to the value of the rod at each length, and n, for length of the rod.
the problem:http://www.radford.edu/~nokie/classes/360/dp-rod-cutting.html
def cutRod(price, n):
val = [0 for x in range(n+1)]
val[0] = 0
for i in range(1, n+1):
max_val = 0
for j in range(i):
max_val = max(max_val, price[j] + val[i-j-1])
val[i] = max_val
return val[n]
If this is the question : Rod cutting
Assuming code works fine, You will have to add a condition instead of Max operation to check which of two was picked and push that one in an array :
def cutRod(price, n):
val = [0 for x in range(n+1)]
val[0] = 0
output = list()
for i in range(1, n+1):
max_val = 0
cur_max_index = -1
for j in range(i):
cur_val = price[j] + val[i-j-1]
if(cur_val>max_val):
max_val = cur_val #store current max
cur_max_index = j #and index
if cur_max_index != -1:
output.append(cur_max_index) #append in output index list
val[i] = max_val
print(output) #print array
return val[n]
I know this is old but just in case someone else has a look...I was actually just looking at this problem. I think the issue is here that these dp problems can be tricky when handling indices. The previous answer is not going to print the solution correctly simply because this line needs to be adjusted...
cur_max_index = j which should be cur_max_index = j + 1
The rest...
def cut_rod(prices, length):
values = [0] * (length + 1)
cuts = [-1] * (length + 1)
max_val = -1
for i in range(1, length + 1):
for j in range(i):
temp = prices[j] + values[i - j - 1]
if temp > max_val:
max_val = prices[j] + values[i - j - 1]
cuts[i] = j + 1
values[i] = max_val
return values[length], cuts
def print_cuts(cuts, length):
while length > 0:
print(cuts[length], end=" ")
length -= cuts[length]
max_value, cuts = cut_rod(prices, length)
print(max_value)
print_cuts(cuts, length)
Well, if you need to get the actual pieces that would be the result of this process then you'd probably need a recursion.
For example something like that:
def cutRod(price, n):
val = [0 for x in range(n + 1)]
pieces = [[0, 0]]
val[0] = 0
for i in range(1, n + 1):
max_val = 0
max_pieces = [0, 0]
for j in range(i):
curr_val = price[j] + val[i - j - 1]
if curr_val > max_val:
max_val = curr_val
max_pieces = [j + 1, i - j - 1]
pieces.append(max_pieces)
val[i] = max_val
arr = []
def f(left, right):
if right == 0:
arr.append(left)
return
f(pieces[left][0], pieces[left][1])
f(pieces[right][0], pieces[right][1])
f(pieces[n][0], pieces[n][1])
return val[n], arr
In this code, there is an additional array for pieces which represents the best way to divide our Rod with some length.
Besides, there is a function f that goes through all pieces and figures out the optimal way to divide the whole Rod.
How do you sort a list with a while loop? Having a bit of a problem, thanks very much in advance.
a = [12,0,39,50,1]
first = a[0]
i = 0
j = 1
while i < len(a):
if a[i] < first:
tmp = a[i]
a[i] = a[j]
a[j] = tmp
i += 1
print(a)
You can create an empty list that would store your sorted numbers
a = [12,0,39,50,1]
kk = len(a)
new_a = []
i = 0
while i < kk:
xx = min(a) ## This would retreive the minimum value from the list (a)
new_a.append(xx) ## You store this minimum number in your new list (new_a)
a.remove(xx) ## Now you have to delete that minimum number from the list a
i += 1 ## This starts the whole process again.
print(new_a)
Please, note that I used the original length of the list a (kk) for the while statement so as not to stop the iteration because the length of the list a decreases as we delete the minimum numbers.
Following is the implementation of basic sorting using two while loops.
In every iteration, the minimum element (considering ascending order) from the unsorted subarray is picked and moved to the sorted subarray.
:
a=[12,0,39,50,1]
i=0
while i<len(a):
key=i
j=i+1
while j<len(a):
if a[key]>a[j]:
key=j
j+=1
a[i],a[key]=a[key],a[i]
i+=1
print(a)
# By using For loop
def ascending_array(arr):
print(f"Original array is {arr}")
arr_length = len(arr)
if arr_length <= 1:
return arr
for i in range(len(arr)):
for j in range(i+1, len(arr)):
if arr[i] >= arr[j]:
arr[i], arr[j] = arr[j], arr[i]
print(f"The result array is {arr}") # [0,0,0,1,10,20,59,63,88]
arr = [1,10,20,0,59,63,0,88,0]
ascending_array(arr)
# By using While loop
def ascending_array(arr):
print(f"Original array is {arr}")
arr_length = len(arr)
if arr_length <= 1:
return arr
i = 0
length_arr = len(arr)
while (i<length_arr):
j = i+1
while (j<length_arr):
if arr[i] > arr[j]:
arr[i], arr[j] = arr[j], arr[i]
j+=1
i+=1
print(f"The result array is {arr}") # [0,0,0,1,10,20,59,63,88]
arr = [1,10,20,0,59,63,0,88,0]
ascending_array(arr)
For-loop is best in terms of performance. while-loop is checking condition every iteration.
You can also concatenate two lists and sort them in decreasing/increasing order using this example:
x = [2,9,4,6]
y = [7,8,3,5]
z = []
maxi = x[0]
pos = 0
print('x: '+str(x))
print('y: '+str(y))
for i in range(len(y)):
x.append(y[i])
for j in range(len(x)-1):
maxi = x[0]
for i in range(len(x)):
if maxi < x[i]:
maxi = x[i]
pos = i
z.append(maxi)
del x[pos]
z.append(x[0])
print('z: '+str(z))
class Island (object):
def __init__(self, i,j,k, wolf_count=0, eagle_count=0, rabbit_count=0, pigeon_count=0,):
'''Initialize grid to all 0's, then fill with animals
'''
# print(n,prey_count,predator_count)
self.i=i
self.j=j
self.k=k
self.cube= []
for k in range(k):
self.square=[]
for j in range(j):
row=[0]*i
self.square.append(row)
self.cube.append(self.square)
self.init_animals(wolf_count, eagle_count, rabbit_count, pigeon_count)
def init_animals(self,wolf_count, eagle_count, rabbit_count, pigeon_count):
count = 0
while count < wolf_count:
i = random.randint(0,self.i-1)
j = random.randint(0,self.j-1)
k = 0
if not self.animal(i,j,k):
new_Wolf=Wolf(island=self,i=i,j=j,k=0)
count += 1
self.register(new_Wolf)
def animal(self,i,j,k):
'''Return animal at location (i,j,k)'''
if 0 <= i < self.i and 0 <= j < self.j and 0 <= k < self.k:
return self.cube[i][j][k]
else:
return -1
These are sections of my program which are calling each other. When I try to run the program it gives me:
IndexError: list index out of range.
It says it for the return self.cube[i][j][k] in animal(). In reference to the if not self.animal(i,j,k): section in init_animals(). which is again in reference to the line isle = Island(i,j,k, initial_Wolf, initial_Pigeon, initial_Eagle, initial_Rabbit) in __init__().
any idea why I get this error? Sorry if its hard to read.
Your outer list self.cube has k entries, each a nested list with j entries, each containing lists of i entries. Reverse your indices:
return self.cube[k][j][i]
or invert the way you are creating your self.cube list:
for _ in range(i):
square = []
for _ in range(j):
square.append([0] * k)
self.cube.append(self.square)
or more compact still using list comprehensions:
self.cube = [[[0] * k for _ in range(j)] for _ in range(i)]
I want it to take as input a set of numbers, such as [1,2,3,4], and only give the subsets with odd sums. For example, [1],[1,2],[2,3] etc.
I haven't tried much, I'm not sure where to start. Sorry, I'm very new to programming, but here's what I have so far. It generates all the possible subsets.
def rsubsets(s):
if len(s) == 0:
return [[]]
temp = rsubsets(s[1:])
new = []
for itm in temp:
new.append(itm)
n = len(new)
for j in range(n):
new[j] = new[j] + [s[0]]
return temp + new
Thanks.
Build upon your existing function:
def odd_subsets(s):
return [x for x in rsubsets(s) if sum(s) % 2 == 1]
Or without the comprehension:
def odd_subsets(s):
odd = []
for subset in rsubsets(s):
if sum(s) % 2 == 1:
odd.append(subset)
return odd
def odd_subsets(s):
lRet = []
for i in range(len(s)):
lRet.extend([c for c in itertools.combinations(s,i+1) if sum(c)%2==1])
return lRet
If you are dead set on using your initial function this is the easiest way to pull it off
def rsubsets(s):
def all_subsets(s):
if len(s) == 0:
return [[]]
temp = all_subsets(s[1:])
new = []
for itm in temp:
new.append(itm)
n = len(new)
for j in range(n):
new[j] = new[j] + [s[0]]
return temp + new
return [i for i in all_subsets(s) if sum(i)%2==1]
Pretty much what this does is call your initial recursive function and filter the results.
Another way is to use a flag...
def rsubsets(s,bFilter=True):
if len(s) == 0:
return [[]]
temp = rsubsets(s[1:],False)
new = []
for itm in temp:
new.append(itm)
n = len(new)
for j in range(n):
new[j] = new[j] + [s[0]]
if bFilter:
return [i for i in temp+new if sum(i)%2 ==1]
return temp + new