I am a newbie to programming. I am working on Heap's Algorithm, specifically non-recursive method. There is not so much explanation available on internet, to how the algorithm works. I found this piece of work from Bernardo Sulzbach but he doesn't explain how his algorithm works. I am stuck on it from days, tried everything couldn't figure it out. I have added comments after each line to make myself understand -- what's happening here? but I still couldn't make it work. Am I doing something wrong? Please help.
# Heap's Algorithm (Non Recursive)
# function to swap values in python
def swap(elements, i, j):
elements[i], elements[j] = elements[j], elements[i]
# function to generate permutation
def generate_permutations(elements, n):
# Passing two parameters of elements and n to function "generate_permutations".
c = [0] * n
# c is a new list and its value set to an array literal with value 0, n times.
# Example - [a] * 3 ==> ['a', 'a', 'a', 'a']
yield elements
# "yield" statement is used to define generators, while "return" statement causes a function to exit.
# "yield" replacing the return of a function to provide a result to its caller without destroying
# local variables. Unlike a function, where on each call it starts with new sets of variables, a generator
# will resume the execution where it left off.
i = 0
# i is a new variable and its value is set to 0. It can also be used to count the number of loop runs.
while i < n:
# while loop ==> while i is less than n, do following:
if c[i] < i:
# if statement ==> while i is less than n and if any element from 'c' list is less than i,
# then do following:
if i % 2 == 0:
# if statement ==> while i is less than n, and if any element in 'c' list is less than i, and
# i is an even number, then do following:
swap(elements, 0, i)
# calling swap function and passing following arguments: elements, '0' and 'i'
else:
# else, if all three conditions above are not true then do following:
swap(elements, c[i], i)
# calling swap funtions and passing following arguments: elements, an item from 'c' list and 'i'
yield elements
# ??? yield elements
c[i] += 1
# after that, increment c[i] by 1.
i = 0
# set the value of i to 0
else:
# else, if c[i] < i is not true the do the following.
c[i] = 0
# set the value of c[i] to 0
i += 1
# and increment i by 1
def permutations(elements):
return generate_permutations(elements, len(elements))
# Driver Code
# c = ?
# n = ?
# i = ?
print(permutations(['abc']))
Just cleaning up your code (too many comments):
# Heap's Algorithm (Non Recursive)
# https://en.wikipedia.org/wiki/Heap%27s_algorithm
def swap(seq, i, j):
seq[i], seq[j] = seq[j], seq[i]
def generate_permutations(seq, seqLen, resLen):
c = [0] * seqLen
yield seq[:resLen]
i = 0
while i < seqLen:
if c[i] < i:
if i % 2 == 0:
swap(seq, 0, i)
else:
swap(seq, c[i], i)
yield seq[:resLen]
c[i] += 1
i = 0
else:
c[i] = 0
i += 1
def permutations(seq, resLen=None):
if not resLen: resLen = len(seq)
return generate_permutations(seq, len(seq), resLen)
for p in permutations([1,2,3]): print(p)
for p in permutations([1,2,3],2): print(p)
The following is a class of heap. I am trying to sort the heap but i have a problem with my max_heapify function. I have inserted the values [10, 9, 7, 6, 5, 4, 3] and my heap sort prints the given output. The given output and expected output is given below the class
class of heap
class Heap(object):
def __init__(self):
self.A = []
def insert(self, x):
self.A.append(x)
def Max(self):
"""
returns the largest value in an array
"""
return max(self.A)
def extractMax(self):
"""
returns and remove the largest value from an array
"""
x = max(self.A)
self.A.remove(x)
self.max_heapify(0)
return x;
def parent(self, i):
"""
returns the parent index
"""
i+=1
i = int(i/2)
return i
def left(self, i):
"""
returns the index of left child
"""
i = i+1
i = 2*i
return i
def right(self, i):
"""
returns the index of right child
"""
i+=1;
i = 2*i + 1
return i
def heap_size(self):
"""
returns the size of heap
"""
return len(self.A)
def max_heapify(self, i):
"""
heapify the array
"""
l = self.left(i)
r = self.right(i)
if(l < self.heap_size() and self.A[l] > self.A[i]):
largest = l
else:
largest = i
if(r < self.heap_size() and self.A[r] > self.A[largest]):
largest = r
if largest != i:
temp = self.A[i]
self.A[i] = self.A[largest]
self.A[largest] = temp
self.max_heapify(largest)
def build_max_heap(self):
n = len(self.A)
n = int(n/2)
for i in range(n, -1, -1):
self.max_heapify(i)
def heap_sort(self):
"""
sorts the heap
"""
while self.heap_size() > 0:
self.build_max_heap()
temp = self.A[0]
n = len(self.A) - 1
self.A[0] = self.A[n]
self.A[n] = temp
x = self.A.pop()
print(x)
self.max_heapify(0)
h = Heap()
h.insert(10)
h.insert(9)
h.insert(7)
h.insert(6)
h.insert(5)
h.insert(4)
h.insert(3)
h.heap_sort()
given output
10
7
6
5
4
3
9
expected output
10
9
7
6
5
4
3
It looks like you're trying to build a max-heap with the root at A[0]. If that's correct, then your left, right, and parent index calculations are not correct. You have:
def parent(self, i):
"""
returns the parent index
"""
i+=1
i = int(i/2)
return i
def left(self, i):
"""
returns the index of left child
"""
i = i+1
i = 2*i
return i
def right(self, i):
"""
returns the index of right child
"""
i+=1;
i = 2*i + 1
return i
So if i=0, the left child would be 2, and the right child would be 3. Worse, given i=3, parent will return 2. So you have the case where parent(right(i)) != i. That's never going to work.
The correct calculations are:
left = (2*i)+1
right = (2*i)+2
parent = (i-1)/2
I don't know why your extractMax is calling max(self.A). You already know that the maximum element is at A[0]. To extract the maximum item, all you need to do is:
returnValue = save value at self.A[0]
take last item in the array and place at self.A[0]
decrease length of array
maxHeapify(0)
I've used pseudo-code because I'm not particularly comfortable with Python.
The loop inside your heapSort method is seriously non-optimum. You're calling self.build_max_heap at each iteration. You don't need to do that. If extractMax is working correctly, all you have to do is:
while self.heap_size() > 0:
temp = self.extractMax()
print temp
Now, if you want to sort the array in-place, so that self.A itself is sorted, that's a bit more tricky. But it doesn't look like that's what you're trying to do.
I am trying to write an efficient 0(nlogn) algorithm for longest increasing subseuqnce:
def whereToInsert(a, k):
l, r = 0, len(a)-1
while l<=r:
m = l + (r-l)//2
if a[m]==k:
return m
elif a[m]>k:
r = m - 1
else:
l = m + 1
if l==len(a)-1:
return l+1
else:
return l
#print(whereToInsert([1,2,3,4,5,6,7,8,9], 0.5)) #This works fine
def lengthOfLISEfficient(nums):
lis = [nums[0]]
for x in nums[1:]:
t = whereToInsert(lis,x)
if t>=len(lis):
lis.append(0)
lis.insert(t, x)
return len(lis)
print(lengthOfLISEfficient([10,9,2,5,3,4]))
But the answer returned is 7 whereas the logest increasing subsequence 2 3 4 is of length 3.
The algorithm is described at the end in https://leetcode.com/problems/longest-increasing-subsequence/.
I am not getting why the answer is coming 7, my algorithm is following the correct logic.
Thanks for your help.
There are a number of issues with your code. Firstly, in the method,
def lengthOfLISEfficient(nums):
when you state:
lis = [nums[0]]
you send only the first item of the list [10,9,2,5,3,4] to the method:
def whereToInsert(a, k):
whereas the latter method is meant to position a number within a list.
Here is a different approach, which involves matching each sublist of the main list with a sorted version of that sublist:
def lengthOfLISEfficient(nums):
#lis = [nums[0]]
lisList = []
for h in range(len(nums)-1):
lis = []
#numberNow = nums[h]
addableLength = len(nums) - h
#lis.append(numberNow)
for f in range(addableLength):
additem = nums[h+f]
lis.append(additem)
lisList.append(lis)
print(lisList) #just for check, feel free to delete this line
subsequenceList = []
for list in lisList:
sortedList = list.copy()
sortedList.sort()
subsequence = []
for e in range(len(list)):
if len(subsequence) > 0:
if prev <= list[e] and sortedList.index(list[e]) == index+1:
subsequence.append(list[e])
else:
continue
else:
subsequence.append(list[0])
prev = list[e]
index = sortedList.index(prev)
subsequenceList.append(subsequence)
print(subsequenceList) #just for check, feel free to delete this line
lengths = []
for l in range(len(subsequenceList)):
lengths.append(len(subsequenceList[l]))
if len(lengths) == len(subsequenceList):
longest = max(lengths)
longestSublist = subsequenceList[lengths.index(longest)]
return longest, longestSublist # Don't return longestSublist if you do not want it
print(lengthOfLISEfficient([10,9,2,5,3,4]))
I'm having trouble writing a function in python that will take a list, split it into 2 equal sides and then recursively add each element in each half. In the end returning the sum of both halves.
def sumLists(aList):
half = len(aList)//2
leftHalf = aList[half:]
rightHalf = aList[:half]
if len(aList) == 1:
return aList[0]
else:
sumOfLeft = sumLists(leftHalf[1:])
resultLeft = leftHalf[0] + sumOfLeft
sumOfRight = sumLists(rightHalf[1:])
resultRight = rightHalf[0] + sumOfRight
return resultLeft + resultRight
Any tips are appreciated, thanks!
You're overcomplicating the else block. You don't need to call sumLists on leftHalf[1:] and rightHalf[1:] and manually add the first respective elements; it suffices to call sumLists on the complete lists.
This slicing is what's causing your RuntimeError. A leftHalf with length one will have a leftHalf[1:] of length zero. But your function recurses forever for lengths of length zero because you didn't write an if case for that scenario.
You could rewrite your else so that it doesn't require slicing:
def sumLists(aList):
half = len(aList)//2
leftHalf = aList[half:]
rightHalf = aList[:half]
if len(aList) == 1:
return aList[0]
else:
return sumLists(leftHalf) + sumLists(rightHalf)
... Or you could add a special case for empty lists:
def sumLists(aList):
half = len(aList)//2
leftHalf = aList[half:]
rightHalf = aList[:half]
if len(aList) == 0:
return 0
elif len(aList) == 1:
return aList[0]
else:
sumOfLeft = sumLists(leftHalf[1:])
resultLeft = leftHalf[0] + sumOfLeft
sumOfRight = sumLists(rightHalf[1:])
resultRight = rightHalf[0] + sumOfRight
return resultLeft + resultRight
Or both:
def sumLists(aList):
half = len(aList)//2
leftHalf = aList[half:]
rightHalf = aList[:half]
if len(aList) == 0:
return 0
if len(aList) == 1:
return aList[0]
else:
return sumLists(leftHalf) + sumLists(rightHalf)
I think aList[half:] is the right side, and aList[:half] is the left side, is it right?
the follow code will sum the list left and right side, hope this can solve your problem.
def sumlist(l):
if not l or not isinstance(l, list):
return 0 # or return other default value.
if len(l) == 1:
return l[0]
half = len(l) // 2
left = l[:half] # left
right = l[-half:] # right
return sumlist(left) + sumlist(right)
test:
l = [1,2,3,4,5,6,7,8,9]
result = sumlist(l)
print(result) # 40
Maybe I misread your question, but do you actually need to do both things in one function?
To sum a list recursively, you could define that the empty list (your base case) has the sum 0. Any non-empty list has the sum of the first element plus the sum of the remainder (the "tail") of the list:
def sumList(a):
return 0 if not a else a[0] + sumList(a[1:])
To split a list recursively, you could keep track of the "left" and "right" list. The left list starts out being your input, the right list is empty. You then recursively prepend the last element of the left list to the right list until the right list is no longer shorter than the left:
def splitList(a, b=None):
b = b or []
return (a, b) if len(a) <= len(b) else splitList(a[:-1], [a[-1]] + b)
I suspect that passing around slices of lists is very inefficient in Python, so it might be better to rather pass around indices, e.g.
def sumList(a, idx=None):
idx = idx or 0
return 0 if idx >= len(a) else a[idx] + sumList(a, idx+1)
I want to create a reverse method for a list. I know there already is such a method built into python but I want to try it from scratch. Here's what I have and it seems to make sense to me but it just returns the list in the same order. My understanding was that lists are mutable and I could just reassign values in the loop.
def reverse(data_list):
length = len(data_list)
s = length
for item in data_list:
s = s - 1
data_list[s] = item
return data_list
def reverse(data_list):
return data_list[::-1]
>> reverse([1,2,3,4,5])
[5, 4, 3, 2, 1]
By the time you are half-way through the list, you have swapped all the items; as you continue through the second half, you are swapping them all back to their original locations again.
Instead try
def reverse(lst):
i = 0 # first item
j = len(lst)-1 # last item
while i<j:
lst[i],lst[j] = lst[j],lst[i]
i += 1
j -= 1
return lst
This can be used in two ways:
a = [1,2,3,4,5]
reverse(a) # in-place
print a # -> [5,4,3,2,1]
b = reverse(a[:]) # return the result of reversing a copy of a
print a # -> [5,4,3,2,1]
print b # -> [1,2,3,4,5]
You are changing the list that you iterate on it (data_list) because of that it's not working , try like this:
def reverse(data_list):
length = len(data_list)
s = length
new_list = [None]*length
for item in data_list:
s = s - 1
new_list[s] = item
return new_list
an easy way in python (without using the reverse function) is using the [] access operator with negative values such as (print and create a new list in reverse order):
x = [1, 2 ,3, 4, 5]
newx = []
for i in range(1, len(x)+1):
newx.append(x[-i])
print x[-i]
the function would be:
def reverse(list):
newlist = []
for i in range(1, len(list)+1):
newlist.append(list[-1])
return newlist
I do not get the same list when I try to run your code. But I also do not get a reversed list because the list is moving forward through the list state which is changing from end back. I think the way you are looking to do it is:
def reverse(data_set):
length = len(data_set)
for i in range(0, length / 2):
length = length - 1
hold = data_set[i]
data_set[i] = data_set[length]
data_set[length] = hold
return data_set
here we actually reverse in half the iterations and we memoize the value of the index we are changing so we can set the "reversal" in the same step.
word_reversed = ''
for i in range(len(word) -1, -1, -1):
word_reversed += word[i]
That will reverse a string of unknown length called (word) and call it (word_reversed).
I am using it to check to see if a word is a palindrome and I'm not allowed to use .reverse or word[::-1].
# Tyler G
# April 10, 2018
# Palindromes
import re
word = input("Palindromes are words that spell the same thing forwars or backwards, enter a word and see if its one!: ")
word = word.lower()
word = re.sub("[^a-zA-Z]+", "", word)
# count the number of characters in the string
# make a if <string>[0] = <string[counted char -1]
# repeat that over and over
# make a else print("not a ...")
word_reversed = ''
for i in range(len(word) - 1, -1, -1):
word_reversed += word[i]
itis = 0
if len(word) > 12:
print("It is not a Palindrome")
else:
for i in range(0, len(word)):
if word[i] == word_reversed[i]:
itis = itis + 1
else:
itis = itis - len(word)
if itis > 0:
print("It is a palindrome")
else:
print("It is NOT a Palindrome")
itis = 0
if len(word) > 12:
print("It is not a Palindrome")
There are two simple ways to solve the problem :
First using a temp variable :
maList = [2,5,67,8,99,34]
halfLen = len(maList) // 2
for index in range(halfLen):
temp = maList[index]
maList[index] = maList[len(maList) - 1 - index]
maList[len(maList) - 1 - index] = temp
print(maList)
Second is using a new list where to store the reversed values :
newList = []
for index,value in enumerate(maList):
newList.append(maList[len(maList) - 1 - index])
print(newList)
Something like this should work:
mylist = [1,2,3,4,5]
def reverse(orig_list):
data_list = orig_list[:]
length = len(data_list)
for i in xrange(0, length/2):
tmp = data_list[length-i-1]
data_list[length-i-1] = data_list[i]
data_list[i] = tmp
return data_list
reverse(mylist)
mylist
There are two ways of doing this
Pythonic Swap:
def Reverse_Function(item):
for i in range(len(item)/2):
item[i], item[-(i+1)] = item[-(i+1)], item[i]
return item
or
XOR application:
def Reverse_Function(item):
for i in range(len(item)/2):
item[i] = item[i] ^ item[-(i+1)]
item[-(i+1)] = item[i] ^ item[-(i+1)]
item[i] = item[i] ^ item[-(i+1)]
return item
Not looking to create a new list to hold your "temp" data?
Its simple if you look at the pattern:
reverse_list([a, b, c, d, e]) => [e, d, c, b, a]
This means that position 0 -> n, 1 -> (n - 1), 2 -> (n - 2). Which means that you can pop the last item and put it in the current index...
def reverse_list(list):
i = 0
while i < (len(list) - 1):
list.insert(i, list.pop())
i += 1
from array import *
x=array('i',[1,2,3,98,5,6,7,8])
y=array('i',[])
for i in x:
y.insert(0,i)
print(y)
Normally you can use either reversed() in general, or [::-1] on sequences. Since you are trying to implement a function from scratch, consider using stack, which is a common Abstract Data Type.
Given
import queue
s = "abc"
lst = list(s)
iter_ = iter(s)
Code
The following works on sequences and iterators similar to reversed():
def reversed_iter(iterable):
"""Yield items in reverse with a queue."""
stack = queue.LifoQueue() # 1
for x in iterable: # 2
stack.put(x)
while not stack.empty(): # 3
yield stack.get()
Demo
list(reversed_iter(s))
# ['c', 'b', 'a']
list(reversed_iter(lst))
# ['c', 'b', 'a']
list(reversed_iter(iter_))
# ['c', 'b', 'a']
Details
A stack is type of queue where the last element placed in is the first element removed. Imagine placing elements on top of each other in a container.
↓ ↑
| "c" |
| "b" |
| "a" |
-----------
Here the last element placed (enqueued) is the first to remove (dequeue), e.g. "c".
In the code, we:
Initialize a stack (the same as a LifoQueue)
Enqueue items to the stack
Dequeue items from the stack
The result are elements yielded in reversed order.
A queue is not required. Alternatively, we can emulate a stack with a simple list:
def reversed_iter(iterable):
"""Yield items in reverse with a list."""
stack = []
for x in iterable:
stack.append(x)
while stack:
yield stack.pop()
list(reversed_iter(s))
# ['c', 'b', 'a']
Emulating the Abstract Data Type is all that is needed in both examples.
list = [23, 3, 33, 44, 55, 16, 27 ];
1.more codes
def conver(list):
list.sort()
length = len(list)
s = length
new_list = [None]*length
for item in list:
s = s - 1
new_list[s] = item
print(new_list)
conver(list)
output:
[55, 44, 33, 27, 23, 16, 3]
2.easiest
list.sort()
list.reverse()
print(list)
output:
[55, 44, 33, 27, 23, 16, 3]
The following code demonstrates how to accept input:
a=[]
n=int(input("enter the no.of elements ")
for I in range(0,n):
a.insert(I,int(input(" enter elements: ")))
def rev_list(a):
print(a[::-1])
rev_list(a)
def reverseOrder():
my_list = []
a = input("What is your word?")
count = len(a) - 1
x = ''
for i in range(0, len(a)):
my_list.append(a[count])
count = count - 1
x = x.join(my_list)
print(x)
reverseOrder()
This is what I did. First I made an empty list. Then I stored users answer in a variable and subtracted one for indexing purposes. Now start a for loop and you set 'range' from 0 , len(a) then you append into the list backwards since count is = len(a). After that you set the .join function and join the list together. This is why there was variable x before the for loop.