peak finding algorithm error in python - python

I am trying to implement peak finding algorithm in Python 2.7. The program intends to find the index of the peak element. A peak element is defined as an element that is not smaller than its immediate neighbors(In case of first and last elements,only one side is checked).My code always prints "None" irrespective of the input. Please look in the code:
def peak(L,l,r,n):
if l<r:
m = l + (r-l)//2
if L[m] < L[m+1] and m < n: # n is the length of the array L
return peak(L,m+1,r,n)
elif m > 0 and L[m] < L[m-1]: # l and r are left and right bounds of
return peak(L,l,m-1,n) # the array
else:
return m

You are recursively increasing l or decreasing r, but since yout first if has no else it will at some point return None.
Your code is equivalent to
def peak(L,l,r,n):
if l<r:
... #recursion
else:
return None

Related

Return maximum value after K swaps using recursion

I am attempting following problem from geeks for geeks, problem link; [enter link description here][1]
Here is my python code to solve it;
def swap_kdigits(s, k, maximum):
if k == 0:
return
for i in range(0, len(s) - 1):
/* find maximum element on the right */
maxc = s[i]
for j in range(i + 1, len(s)):
if int(s[j]) > int(maxc):
maxc = s[j]
if maxc != s[i]:
idx = s.index(maxc)
ll = list(s)
# do the swap
ll[i], ll[idx] = ll[idx], ll[i]
s = ''.join(ll)
maximum = max(int(s), maximum) /* update maximum values*/
# make a recursive call on the new string
swap_kdigits(s, k - 1, maximum)
# backtrack
ll[i], ll[idx] = ll[idx], ll[i]
s = ''.join(ll)
def main_fn(s, k):
maximum = int(s) /*initialize maximum variable*/
return swap_kdigits(s, k, maximum) /* call helper function */
Can I please get some help on how to return the maximum value obtained to the calling function? As you can see, right now nothing is been returned. Help is appreciated.
[1]: https://practice.geeksforgeeks.org/problems/largest-number-in-k-swaps-1587115620/1/?page=2&category[]=Strings&sortBy=submissions
Edited Code Without Recursion
def swap_kdigits(s, k):
# define current max
maximum = int(s)
for i in range(0, len(s) - 1):
maxc = s[i]
if k == 0:
break
for j in range(i + 1, len(s)):
if int(s[j]) > int(maxc):
maxc = s[j]
if maxc != s[i]:
k -= 1
idx = s[i + 1:].rfind(maxc) + i + 1 # find last occurrence
ll = list(s)
# do the swap
ll[i], ll[idx] = ll[idx], ll[i]
s = ''.join(ll)
# find the new max
maximum = max(int(s), maximum)
return maximum
As I don't have a GeeksForGeeks account, I cannot login into the site and see for myself if there's an actual answer to this question. I'm telling this, because I don't know why you came up with a recursive function for the solution.
After testing your script and making some modifications, I realized your script should work without any recursion. That's right, you made a procedural solution. But why it's not working?
Reason 1) Where is the string s being updated? From what I saw, you are updating the sequence s on this line: ll[i], ll[idx] = ll[idx], ll[i]. That's ok, but note this doesn't need any recursion. There's no point in calling swap_kdigits again from the for-loop.
strings in python are immutable objects. Unless you return the string sequence from a swap_kdigits call, you're never really updating the string s on any deeper levels of recursive calls. You are only modifying it on the root level, and again, never returning anything. That's why your script returns nothing.
Reason 2) If recursive calls are pointless here, where should you use k? My guess is whenever a swap is made towards the final maximum sequence.
Reason 3) About this line: maximum = max(int(s), maximum). Sure, it makes sense. You're always walking towards the maximum value. But will int(s) be always higher than maximum?
As a short answer: I don't know, didn't tested it so far... So in order to contain possible errors with the script, I've placed a safeguard using your backtracking line in the script below.
Reason 4) On this line: idx = s.index(maxc), this line should be idx = s[i + 1:].index(maxc) + i + 1. Confusing? I bet, but it makes sense: on the for-loop you're seeking the maxc on the sequence after index i. So, when seeking the index of maxc, you should pass only the subset where maxc is present, not the whole string.
If you didn't do this, your script would give you a wrong result when testing on this sequence: "3435335". The reason are the repeated characters.
Finally, here's the working version of your script. It's not recursive anymore because as I explained before, it never needed recursion the way it was written.
def swap_kdigits(s, k, maximum):
# Iterate over every character of the sequence, except the last character
for i in range(0, len(s) - 1):
maxc = s[i]
# If the k number of swaps are exceeded, stop the algorithm
if (k == 0):
break
# Find the maximum character on the subset s[i+1:]
for j in range(i + 1, len(s)):
if int(s[j]) > int(maxc):
maxc = s[j]
if maxc != s[i]:
# Remember the for-loop with j?
# We are not seeking the maxc in the entire string,
# only in the subset starting from index: i+1
idx = s[i + 1:].index(maxc) + i + 1
ll = list(s)
# Swap character to obtain a new maximum sequence
ll[i], ll[idx] = ll[idx], ll[i]
s = ''.join(ll)
# This is a safe guard.
#
# In the examples provided by the GeeksForGeeks, the
# else block is never executed.
#
# However, what if int(s) is not really the maximum
# number?
#
# Then, we make a backtrack to return to the previous
# maximum sequence.
if (int(s) > maximum):
# Edit: update maximum number
maximum = int(s)
# Made a swap, decrease k
k -= 1
else:
# Go back to the previous sequence
ll[i], ll[idx] = ll[idx], ll[i]
s = ''.join(ll)
# Return the maximum sequence
return s
def main_fn(s, k):
maximum = int(s)
return swap_kdigits(s, k, maximum)
if __name__ == '__main__':
print(main_fn("3435335", 3))
I'm editing this answer to show you how I would make a recursive solution to this example:
def rec_swap(seq, k, offset=0):
# Check if the number of swaps is still valid, or
# if the offset has reached the end of the sequence
if (k > 0 and offset < (len(seq)-1)):
# Select maxc from a subset of right characters
subset = seq[offset:]
# Find the max character on the subset
maxc = max(list(subset), key=lambda c: int(c))
# Find the index of maxc on the subset
maxi = subset.index(maxc)
# Transform maxi to relate to the whole sequence seq
maxi += offset
# Cannot swap same character
if (maxi != offset):
# Create a previous of the swapped sequence
# swapped = swap(seq, offset, maxi)
#
# Using this print we can see how many iterations it took
# to find the maximum sequence. It might be less than k.
print('SWAP: ', seq[offset], seq[maxi])
swapped = seq[:offset] + seq[maxi] + seq[offset+1:maxi] + seq[offset] + seq[maxi+1:]
# Only go deep if next sequence is higher than current one
if (int(swapped) > int(seq)):
# Return deepest, or maximum, sequence possible:
#
# As we made a swap on this recursion level, k is decreased by -1
# As we move one character to the right, offset is increased by 1
return rec_swap(swapped, k-1, offset+1)
# If there's nothing to do, return current sequence
return seq
def main():
result = rec_swap("3435335", 3)
print('RESULT: ', result)
if __name__ == '__main__':
main()
In this recursive example, you can see I do not rely on altering the sequence seq as if passed by reference. I simply return seq at the end of the recursive call, or when I go down one level. This allows me to always return the deepest recursion sequence.
As strings in python are immutable data, there's no need for backtracking.
Also, instead of making a for-loop to find maxc, I used the built-in function max(target, key), using a lambda on the key paramter to iterate over the list, and find the max character (when converted to an int).
I left this line on purpose print('SWAP: ', seq[offset], seq[maxi]). When the recursive function is called, this print shows the actual number of swap operations made to the sequence seq.
Output of recursive script:
SWAP: 3 5
SWAP: 4 5
SWAP: 3 4
RESULT: 5543333

Ceiling of the element in sorted array

Hi I am doing DSA problems and found a problem called as ceiling of the element in sorted array. In this problem there is a sorted array and if the target element is present in the sorted array return the target. If the target element is not found in the sorted array we need to return the smallest element which is greater than target. I have written the code and also done some test cases but need to check if everything works correctly. This problem is not there on leetcode where I could run it with many different cases. Need suggestion/feedback if the problem is solved in the correct way and if it would give correct results in all cases
class Solution:
#My approch
def smallestNumberGreaterThanTarget(self, nums, target):
start = 0
end = len(nums)-1
if target > nums[end]:
return -1
while start <= end:
mid = start + (end-start)//2
if nums[mid] == target:
return nums[mid]
elif nums[mid] < target:
if nums[mid+1] >= target:
return nums[mid+1]
start = mid + 1
else:
end = mid-1
return nums[start]
IMO, the problem can be solved in a simpler way, with only one test inside the main loop. The figure below shows a partition of the real line, in subsets associated to the values in the array.
First, we notice that for all values above the largest, there is no corresponding element, and we will handle this case separately.
Now we have exactly N subsets left, and we can find the right one by a dichotomic search among these subsets.
if target > nums[len(nums)-1]:
return None
s, e= 0, len(nums);
while e > s:
m= e + ((s - e) >> 1);
if target > nums[m]:
s= m+1
else:
e= m
return s
We can formally prove the algorithm using the invariant nums[s-1] < target <= nums[e], with the fictional convention nums[-1] = -∞. In the end, we have the bracketing nums[s-1] < target <= nums[s].
The code errors out with an index out-of-range error for the empty list (though this may not be necessary because you haven't specified the problem constraints).
A simple if guard at the top of the function can fix this:
if not nums:
return -1
Otherwise, it seems fine to me. But if you're still not sure whether or not your algorithm works, you can always do random testing (e.g. create a linear search version of the algorithm and then randomly generate inputs to both algorithms, and then see if there's any difference).
Here's a one-liner that you can test against:
input_list = [0, 1, 2, 3, 4]
target = 0
print(next((num for num in input_list if num >= target), -1))

Code simplifcation using iteration and recursion

I would like to 1)simplify the code below using iteration 2)implement it using recursion
This code features an equation similar to the Fibonacci series the difference being the previous answer is multiplied by a function in this case just 2 by index.
The algorithm will input different images and calculate the total incremented points, the flattened optimal matrix will give the highest value.
Note that list_c should give the highest value.
sum_list=[]
list_a= [1,0,1,0,1]
list_b= [1,0,0,1,1]
list_c= [1,1,1,0,0]
def increment(input_list):
global i #i added it because i received an error
""" returns
Incrementing_answer = previous_answer + (list[i+1])
for which previous_answer begins with list[0]
if list[0] =0 then list[0]=-1
for example, list_a should be evaluated as follows
- ans = 1+2*(1)
= 3
- ans = 3+ 2*(0) --since since its 0 ,-1 is replaced
= 3+ 2*(-1)
= 1
- ans = 1+2(1)
=3
and so on
Incrementing_answers = sum_list=[3,1,3,1,3] =11
"""
for i in range(0,len(input_list)):
if input_list[i] == 0 :
input_list[i] == -1
ans = input_list[i]+2*input_list[i]
sum_list.append(ans)
else:
ans = ans+input_list[i]
sum_list.append(ans)
return sum(sum_list)
Previous answers have been helpful, the code above does not work
1)I would like corrections
2)Is it possible to solve the same problem using recursion
3) I also just realised the code does not work well for large arrays(preprocesed_images)
4) for lists or arrays that include floating points I get the error ('
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()')
3)Feedback on using good programming practices
4) Any additional advice on how to tackle the problem is Welcome, the inputted images will be captured using cv2 and the algorithm has to pick optimal images in real-time, to solve the puzzle.
Thanks very much in advance
Global variables are discouraged over passing arguments as parameters to function
Use of PEP 8 naming conventions is encouraged (i.e. name function increment rather than Increment)
Single letter variable names are discouraged (i.e. no idea of what a, l, p represents) (adopting Dan's comment below).
Code
def increment(a, l, p):
"""
Returns in an incrementing value ,using the formula a(n)=a(n)+l(i+1)
were a(n) starts with the starts with l[0] and then l(i+1)
"""
for i in range(len(l)):
if l[i] == 0: # equation
a += -2 # no change to l
else:
a += 2*l[i]
p.append(a)
return sum(p)
Usage
l = [1,0,1,0,1]
p=[]
a = 0
print(f'Increment: {increment(a, l, p)}')
print(f'l unchanged: {l}')
print(f'Updated p: {p}')
a = p[-1] # a is last p
print(f'Updated a: {a}')
Output
Increment: 6
l unchanged: [1, 0, 1, 0, 1]
Updated p: [2, 0, 2, 0, 2]
Updated a: 2
a doesn't need to be a global and p & l should be passed as argumets -in your version you tied your implementation of your function to the implementation of the calling code - a better implementation would be :
I don't fully understand why you need a at all, but I think this code does what you need :
def Increment( initial, results ):
"""
Returns in an incrementing value ,using the formula a(n)=a(n)+l(i+1)
were a(n) starts with the starts with l[0] and then l(i+1)
,if l[i]= 0,-1 is calculated instead.
"""
last = results[-1] if results else 0
for index, value in enumerate(initial):
term = -1 if value == 0 else value
last += 2* term
results.append(last)
return sum(results)
l = [1,0,1,0,1]
p=[]
r = Increment(initial=l, results=p)
print(r)
If you do need the a value outside the function it will just be p[-1]
I think the above code replicates the functionality, without changing your l list (which you indicated you didn't need.

How to use recursion to implement "Finding the maximum value in an array" in Python?

How to use recursion to implement "Finding the maximum value in an array" in Python ?
The following is a simple test code I wrote
I want to do it by recursion
I'm learning algorithms, learning recursion.
Thanks very much!
def max(list):
if list == []:
msg = "List: ..."
return msg
max = list[0]
for item in list[1:]:
if item > max:
max = item
return max
data = [8,2,-690,4,12,-320,0, 98]
print(max(data))
If you want to use recursion, it's very important to define carefully the end cases.
The maximum of the elements of a list is, obviously, either the first element or the maximum of the rest of the list: it's the greatest of the two values. That's actually the recursion you are looking for.
But what happens when there is no first element? You have an empty list, and an undefined behaviour. Why not maximum([]) = 0? Because it would lead to some inconsistency: maximum([-1]) = greatest(-1, maximum([])) = greatest(-1, 0) = 0. (You could also try maximum([]) == -math.inf, but this won't be very intuitive!)
What if the rest of the list is empty? No problem, you have just one element and it is the maximum.
Just translate this analysis into code:
def maximum(xs):
if len(xs) == 0:
raise ValueError()
elif len(xs) == 1:
return xs[0]
else:
u = xs[0]
v = maximum(xs[1:])
return u if u >= v else v # greatest(u, v)
More on maximum([])
I will try to give a value to maximum([]). I repeat the argument above. For any given n, maximum([n]) = greatest(n, maximum([])) = n. This implies that, for every n, maximum([]) <= n. The only value that meets this condition is -math.inf. Why not define maximum([]) == -math.inf? Imagine you create a minimum function. For symetrical reasons, you will have to define minimum([]) == math.inf. Hence it exists a list l0 = [] such that minimum(l0) > maximum(l0). No one would accept such a possibility.
What should we do now? There are two main possibilities: defensive programming or use a contract. In defensive programming, the function will check the arguments it has received, and fail if one of these arguments is not correct. That's what I did:
def maximum(xs):
if len(xs) == 0:
raise ValueError()
...
If you use a contract, you will basically say: if you give this function an empty list, then the behaviour is undefined. It might return any value, crash, loop forever, .... Here, you would have something like:
def maximum(xs):
"""!!! xs must not be empty !!!"""
...
It seems the same, but there is a huge difference. You can use, for implementation reasons, -math.inf as the return value for maximum([]), because it is now clear that it doesn't have any meaning. Someone who tries to check if minimum(l0) <= maximum(l0) for l0 = [] clearly breaks the contract and won't be surprised by the result. Of course, if you want to make it robust, you will write:
def maximum(xs):
"""PRECONDITION: xs must not be empty"""
assert len(xs) != 0 # can be disabled at runtime at your own risks
_maximum(xs)
def _maximum(xs):
"""no precondition here"""
if len(xs) == 0:
return -math.inf
else:
u = xs[0]
v = _maximum(xs[1:])
return u if u >= v else v # greatest(u, v)
Try this (using recursion, as requested by the OP):
def largest(arr):
if len(arr) == 2:
return arr[1] if arr[1] > arr[0] else arr[0]
else:
return largest([arr[0], largest(arr[1:])])
No built-in functions are used (such as max) because the OP has stated that they don't wish to use any built-in functions.
The else part of the function returns either the first element of the list or the largest number in the list (excluding the first element) depending on whichever number is larger.
Each time the else part is executed, the largest(arr[1:]) bit checks which number is largest inside arr without the first element. This means that, at one point, arr will contain two elements. When it does so, a one-line if statement is used to compare the two elements and returns the larger element.
Eventually, the code recurses back to the first level and returns the largest element.
I would write max and max_all
from math import inf
def max (a, b):
if a > b:
return a
else:
return b
def max_all (x = -inf, *xs):
if not xs:
return x
else:
return max (x, max_all (*xs))
max_all can be called with any number of arguments
print (max_all (8, 2, -690, 4, 12, -320, 0, 98))
# 98
Or use * to unpack arguments
data = [ 8, 2, -690, 4, 12, -320, 0, 98 ]
print (max_all (*data))
# 98
It even works when 0 inputs are given
print (max_all ())
# -inf
def Maximum(list):
if len(list) == 1:
return list[0]
else:
m = Maximum(list[1:])
if m > list[0] else list[0]:
return m
def main():
list = eval(raw_input(" please enter a list of numbers: "))
print("the largest number is: ", Maximum(list))
main()
The simplest way
max and list are built-in functions. So you want to avoid using those identifiers yourself.
Here's a simple version that uses recursion:
#/usr/bin/python
def largest(arr):
if not arr:
return None
else:
r = largest(arr[1:])
if r > arr[0]:
return r
else:
return arr[0]
data = [8, 2, -690, 4, 12, -320, 0, 98]
print(largest(data))

i wish to find minimum element of a list whose elements first decrease then increase

I want to achieve it in O(log n) complexity.using the idea of binary search it can be achieved . I put it this way: let L be a list ;L= [12,10,9,7,6,5,8,9,11] so the expected outcome should be 5. Is there a simple algorithm in python to do it?
def binse(l,lo,hi):
n =len(l)
lo = 0
hi =n
mid =(lo+hi)//2
if (hi-lo)<2:
return lo
if l[mid]<l[mid-1] and l[mid]<l[mid+1]:
return l[mid]
elif l[mid]<l[mid-1] and l[mid]>l[mid+1]:
return binse(l,mid+1,hi)
elif l[mid]>l[mid-1] and l[mid]<l[mid+1]:
return binse(l,lo,mid)
else:
return
l = [13,11,5,6,7,8,9,11,13]
lo =0
hi =len(l)
print(binse(l,lo,hi))
def mini(lis):
s, e = 0, len(lis)-1
while True:
m = (s+e)/2
if lis[m] > lis[m+1]:
s = m
elif lis[m-1] < lis[m]:
e = m+1
else:
return m
This should work.
You said it - use binary search. At each probe, take two successive entries and determine whether the values are increasing or decreasing. Based on that, you know which region to further sub-divide.
BTW, I'm ignoring the case of equality
Update based on posted code:
The first thing binse does is overwrite the lo and hi parameters - bad!
The return lo line is clearly wrong as it is not returning an array value
Need to be a bit careful about some edge cases including getting near the endpoints and also when you have a sequence of equal values
The last "return" is also clearly wrong as it has no value.
The first item is the reason you are seeing the infinite recursion.

Categories

Resources