proving a function's correctness - induction

1 def recmin(A):
2 if len(A) == 1:
3 return A[0]
4 else:
5 m = len(A) // 2
6 min1 = recmin(A[0..m-1])
7 min2 = recmin(A[m..len(A)-1])
8 return min(min1, min2)
I'm trying to prove the partial correctness of this function, I figured out a predicate of p(i):for the array A=[0..i], len(A)=i+1 and when recmin[A]is called,then this call terminates and returns some t such that 0<=t<=i A[t] is the min value
But I feel like this predicate is wrong and how would i prove that the postcondition where A[0] is min value

Related

Find the Highest number in O(logn) Complexity

def peak(arr,n):
l = 0
r = n-1
while(l<=r):
m = l + (r-l)//2
if m>0 and m<n-1:
if arr[m+1]<arr[m] and arr[m]>arr[m-1]:
return arr[m]
elif arr[m+1]>arr[m] and arr[m]>arr[m-1]:
l = m+1
elif arr[m+1]<arr[m] and arr[m]<arr[m-1]:
r = m-1
elif m>0 and m>=n-1:
if arr[m]>arr[m-1]:
return arr[m]
elif m<=0 and m<n-1:
if arr[m+1]<arr[m]:
return arr[m]
Question is -
Given an array in such a way that the elements stored in array are in increasing order initially and then after reaching to a peak element , elements stored are in decreasing order. Find the highest element.
Example:
Input:
11
1 2 3 4 5 6 5 4 3 2 1
5
1 2 3 4 5
Output:
6
5
Can anyone tell me what is wrong in my code?
The problem is that the conditions in your code do not account for the case where there is only one element in the array, i.e, when n is 1. When this happens none of the conditions would be true, and the while loop becomes an infinite loop.
You can solve the issue by simply returning arr[m] by default:
while(l<=r):
m = l + (r-l)//2
if m>0 and m<n-1:
... # your existing code
else:
return arr[m]

recursive solution for coin change problem

i need to write an algorithm that receives a number and a list of numbers and returns the number of possible combinations of numbers from the list that can create the sum number. for example: def coin(5,[1,2,5,6] should return the number 4 because there are 4 possible combinations from the list that can create together the number 5. below there is the code that i tried but it does not work. the output is 6 instead of 4 and i would love some help in understanding why.
def coin(n,lst):
if n<=1:
return 1
else:
total=0
for i in range(len(lst)):
change=lst[i]
if change>n:
continue
else:
result=coin(n-change,lst[i:])
if result>0:
total+=result
return total
print(coin(5,[1,2,5,6]))
The mistake is in the base case:
if n<=1:
return 1
This is only valid if 1 is one of the allowed coins. But in your recursive case, you slice the list at lst[i:], so not all coins will be allowed every time. Sometimes, 1 isn't one of the allowed coins, in which case there are zero ways to make a total of 1, not one way. To fix it, write something like:
if n <= 1:
if n == 0 or n in lst:
return 1
else:
return 0
This is correct because you can make change for n in the base case either if n is 0 (we can always make 0), or if n is 1 and 1 is one of the allowed coins.
That said, it would be simpler to let the recursive case handle 1, so the base case only needs to handle 0; this is also correct:
if n == 0:
return 1
int coinCount( int C[], int m, int n )
{
// if n is 0 return 1
if (n == 0)
return 1;
// If n is less than 0 then no solution exists
if (n < 0)
return 0;
// If there are no coins and n is greater than 0, then no solution exists
if (m <=0 && n > 0)
return 0;
return coinCount( C, m - 1, n ) + coinCount( C, m, n-C[m-1] );
}

If elif one liner

if i == len(a):
tempList.extend(b[j:])
break
elif j == len(b):
tempList.extend(a[i:])
break
I am using this in a mergesort-program in Python. Is there any way to put this into a oneliner?
Maybe, but let's give a dedicated non-answer: don't even try.
You don't write your code to be short. You write it so that:
it gets the job done in a straight forward manner
it clearly communicates its meaning to human readers
The above code does that already.
In other words: of course being precise is a valuable property of source code. So, when you have to equally readable pieces of code doing the same thing, and one version is a one-liner, and the other is way more lengthy - then you go for the short version.
But I very much doubt that the above can be expressed as readable as above - with less code.
You can use and and or boolean operations to make a pretty readable one-liner:
l = []
a = [1,2,3,4]
b = [8,9,10]
i = 4
j = 2
l.extend(i == len(a) and b[j:] or j == len(b) and a[i:] or [])
l == [10]
i = 0
j = 3
l.extend(i == len(a) and b[j:] or j == len(b) and a[i:] or [])
l == [10, 1, 2, 3, 4]
This example uses next properties:
The expression x and y first evaluates x; if x is false, its value is returned; otherwise, y is evaluated and the resulting value is returned.
The expression x or y first evaluates x; if x is true, its value is returned; otherwise, y is evaluated and the resulting value is returned.
We have to add or [] to mitigate TypeError: 'bool' object is not iterable exception raised when i == len(a) and j > len(b) (e.g. i == 4 and j == 5).
I'd still prefer an expanded version though.

Python 3 index is len(l) conditional evaluation error

I have the following merge sort code. When the line if ib is len(b) or ... is changed to use double equal ==: if ib == len(b) or ..., the code does not raise an IndexError exception.
This is very unexpected because:
len(b) is evaluated to a number and is is equivalent to == for integers. You can test it out: a python expression
(1 is len([0]) )
is evaluated to be True.
the input to the function is range(1500, -1, -1), and range objects are handled differently in python3. I was suspecting that since the input was handled as a range instance, the length evaluation might have been an instance instead of a integer primitive. This is again strange because
1 is len(range(1))
also gives you True as the result.
Is this a bug with the conditional evaluation in Python3?
Tom Caswell supplied this following useful express in our discussion, I'm copy pasting it here for your notice:
tt = [j is int(str(j)) for j in range(15000)]
only the first 256 items are True. The rest are False hahahaha.
The original script:
def merge_sort(arr):
if len(arr) >= 2:
s = int(len(arr)/2)
a = merge_sort(arr[:s])
b = merge_sort(arr[s:])
ia = 0
ib = 0
new_arr = []
while len(new_arr) < len(arr):
try:
if ib is len(b) or a[ia] <= b[ib]:
new_arr.append(a[ia])
ia += 1
else:
new_arr.append(b[ib])
ib += 1
except IndexError:
print(len(a), len(b), ia, ib)
raise IndexError
return new_arr
else:
return arr
print(merge_sort(range(1500, -1, -1)))
Python does not guarantee that two integer instances with equal value are the same instance. In the example below, the reason the first 256 comparisons return equal is because Python caches -5 to 256 in Long.
This behavior is described here: https://docs.python.org/3/c-api/long.html#c.PyLong_FromLong
example:
tt = [j is int(str(j)) for j in range(500)]
plt.plot(tt)
IIRC that any of them pass the is test is an implementation-specific optimization detail.
is checks whether 2 arguments refer to the same object, == checks whether 2 arguments have the same value. You cannot assume they mean the same thing, they have different uses, and you'll get an error thrown if you attempt to use them interchangeably.

sum even integer in a list of integer (without loop)

I have a task: create a function that takes a integer list as parameter and returns the sum of all even integer in an integer list, without using any kinds of loop. All addition must be done by + operator only. Below is my solution
def sumTest(list_Of_Integers):
return sum(list(filter(lambda x: x%2 == 0, list_Of_Integers)))
I want to ask if there is any better solution, like without using the built-in sum() of python.
Thanks
As stated above in the comments, a more pythonic way of doing this is to use a list comprehension:
def sumTest(list_Of_Integers):
return sum([x for x in list_Of_Integers where x % 2 == 0])
As #UloPe states, however, this sounds very much like a homework question, in which case a more recursive method may be expected (rather than using the sum() function):
def sumTest2(xs):
if len(xs) == 0:
return 0
total = xs[0] if xs[0] % 2 == 0 else 0
return total + sumTest2(xs[1:])
This will generate a function stack dependent on the size of the list.
If you want to generate a shallower stack, then you can do the following:
def sumTest3(xs):
if len(xs) == 0:
return 0
midpoint = len(xs) / 2
total = xs[midpoint] if xs[midpoint] % 2 == 0 else 0
return sumTest3(xs[:midpoint]) + total + sumTest3(xs[midpoint + 1:])
The stack depth of this version will be log(size of list)

Resources