Code simplifcation using iteration and recursion - python

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.

Related

How to improve efficiency and time-complexity of AIO Cloud Cover solution

Sorry for the noob question, but is there a less time expensive method to iterate through the input list, as upon submission I receive timeout errors. I tried changing the method of checking for the minimum answer by appending to a list and using min function, but as expected that didn't help at all.
Input:
6 3
3
6
4
2
5
Solution:
with open("cloudin.txt", "r") as input_file:
n, covered = map(int, input_file.readline().split())
ls = [None for i in range(100005)]
for i in range(n-1):
ls[i] = int(input_file.readline().strip())
ans = 1000000001
file = open("cloudout.txt", "w")
for i in range(n-covered):
a = 0
for j in range(covered):
a += ls[i+j]
if a < ans:
ans = a
file.write(str(ans))
output:
11
https://orac2.info/problem/aio18cloud/
Note: Blue + White indicates timeout
The core logic of your code is contained in these lines:
ans = 1000000001
for i in range(n-covered):
a = 0
for j in range(covered):
a += ls[i+j]
if a < ans:
ans = a
Let's break down what this code actually does. For each closed interval (i.e. including the endpoints) [left, right] from the list [0, covered-1], [1, covered], [2, covered+1], ..., [n-covered-1, n-2] (that is, all closed intervals containing exactly covered elements and that are subintervals of [0, n-2]), you are computing the range sum ls[left] + ls[left+1] + ... + ls[right]. Then you set ans to the minimum such range sum.
Currently, that nested loop takes O((n-covered)*covered)) steps, which is O(n^2) if covered is n/2, for example. You want a way to compute that range sum in constant time, eliminating the nested loop, to make the runtime O(n).
The easiest way to do this is with a prefix sum array. In Python, itertools.accumulate() is the standard/simplest way to generate those. To see how this helps:
Original Sum: ls[left] + ls[left+1] + ... + ls[right]
can be rewritten as the difference of prefix sums
(ls[0] + ls[1] + ... + ls[right])
- (ls[0] + ls[1] + ... + ls[left-1])
which is prefix_sum(0, right) - prefix_sum(0, left-1)
where are intervals are written in inclusive notation.
Pulling this into a separate range_sum() function, you can rewrite the original core logic block as:
prefix_sums = list(itertools.accumulate(ls, initial=0))
def range_sum(left: int, right: int) -> int:
"""Given indices left and right, returns the sum of values of
ls in the inclusive interval [left, right].
Equivalent to sum(ls[left : right+1])"""
return prefix_sums[right+1] - prefix_sums[left]
ans = 1000000001
for i in range(n - covered):
a = range_sum(left=i, right=i+covered-1)
if a < ans:
ans = a
The trickiest part of prefix sum arrays is just avoiding off-by-one errors in indexes. Notice that our prefix sum array of the length-n array ls has n+1 elements, since it starts with the empty initial prefix sum of 0, and so we add 1 to array accesses to prefix_sums compared to our formula.
Also, it's possible there may be an off-by-one error in your original code, as the value ls[n-1] is never accessed or used for anything after being set?

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))

Find the first fibonacci number above 1 million

Currently taking a programming course and got as an assignment to find the first fibonacci number above a million and I'm having a bit of trouble finding the specific number. I'm also supposed to be finding the index of the n:th number when it hits 1 million. I'm pretty new to coding but this is what I've come up with so far, just having a hard time to figure out how to actually calculate what the number is.
I guess you would switch out the for-with a while-loop but haven't figured out it how to get it all to work.
Thanks in beforehand :)
def fib_seq(n):
if n <= 2:
return 1
return fib_seq(n-1) + fib_seq(n-2)
lst = []
for i in range(1, 20):
lst.append(i)
print(fib_seq(i), lst)
Some points:
You don't need to build a list. You're only asked to return an index and the corresponding Fibonnacci number.
The recursive algorithm for Fibonnacci is not best practice, unless you would use some memoization. Otherwise the same numbers have to be recalculated over and over again. Use an iterative method instead.
Here is how that could look:
def fib(atleast):
a = 0
b = 1
i = 1
while b < atleast:
a, b = b, a+b
i += 1
return i, b
print(fib(1000000)) # (31, 1346269)
If you need to do this with some find of recursion, you should try to avoid calling the recursions twice with each iteration. This is a classic example where the complexity explodes. One way to do this is to memoize the already calculated results. Another is to maintain state with the function arguments. For example this will deliver the answer and only call the function 32 times:
def findIndex(v, prev = 0, current = 1, index = 0):
if v < prev:
return (prev, index)
return findIndex(v, current, prev+current, index + 1 )
findIndex(1000000) # (1346269, 31)

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))

recursive function in python but with strange return

I am trying to solve a primary equation with several variables. For example:11x+7y+3z=20. non-negative integer result only.
I use code below in python 3.5.1, but the result contains something like [...]. I wonder what is it?
The code I have is to test every variables from 0 to max [total value divided by corresponding variable]. Because the variables may be of a large number, I want to use recursion to solve it.
def equation (a,b,relist):
global total
if len(a)>1:
for i in range(b//a[0]+1):
corelist=relist.copy()
corelist+=[i]
testrest=equation(a[1:],b-a[0]*i,corelist)
if testrest:
total+=[testrest]
return total
else:
if b%a[0]==0:
relist+=[b//a[0]]
return relist
else:
return False
total=[]
re=equation([11,7,3],20,[])
print(re)
the result is
[[0, 2, 2], [...], [1, 0, 3], [...]]
change to a new one could get clean result, but I still need a global variable:
def equation (a,b,relist):
global total
if len(a)>1:
for i in range(b//a[0]+1):
corelist=relist.copy()
corelist+=[i]
equation(a[1:],b-a[0]*i,corelist)
return total
else:
if b%a[0]==0:
relist+=[b//a[0]]
total+=[relist]
return
else:
return
total=[]
print(equation([11,7,3],20,[]))
I see three layers of problems here.
1) There seems to be a misunderstanding about recursion.
2) There seems to be an underestimation of the complexity of the problem you are trying to solve (a modeling issue)
3) Your main question exposes some lacking skills in python itself.
I will address the questions in backward order given that your actual question is "the result contains something like [...]. I wonder what is it?"
"[]" in python designates a list.
For example:
var = [ 1, 2 ,3 ,4 ]
Creates a reference "var" to a list containing 4 integers of values 1, 2, 3 and 4 respectively.
var2 = [ "hello", ["foo", "bar"], "world" ]
var2 on the other hand is a reference to a composite list of 3 elements, a string, another list and a string. The 2nd element is a list of 2 strings.
So your results is a list of lists of integers (assuming the 2 lists with "..." are integers). If each sublists are of the same size, you could also think of it as a matrix. And the way the function is written, you could end up with a composite list of lists of integers, the value "False" (or the value "None" in the newest version)
Now to the modeling problem. The equation 11x + 7y + 3z = 20 is one equation with 3 unknowns. It is not clear at all to me what you want to acheive with this program, but unless you solve the equation by selecting 2 independent variables, you won't achieve much. It is not clear at all to me what is the relation between the program and the equation save for the list you provided as argument with the values 11, 7 and 3.
What I would do (assuming you are looking for triplets of values that solves the equation) is go for the equation: f(x,y) = (20/3) - (11/3)x - (7/3)y. Then the code I would rather write is:
def func_f(x, y):
return 20.0/3.0 - (11.0/3.0) * x - (7.0/3.0) * y
list_of_list_of_triplets = []
for (x, y) in zip(range(100),range(100)):
list_of_triplet = [x, y, func_f(x,y)]
list_of_list_of_triplets += [list_of_triplet] # or .append(list_of_triplet)
Be mindful that the number of solutions to this equation is infinite. You could think of it as a straight line in a rectangular prism if you bound the variables. If you wanted to represent the same line in an abstract number of dimensions, you could rewrite the above as:
def func_multi_f(nthc, const, coeffs, vars):
return const - sum([a*b/nth for a,b in zip(coeffs, vars)])
Where nthc is the coefficient of the Nth variable, const is an offset constant, coeffs is a list of coefficients and vars the values of the N-1 other variables. For example, we could re-write the func_f as:
def func_f(x,y):
return func_multi_f(3.0, 20.0, [11.0, 7.0], [x,y])
Now about recursion. A recursion is a formulation of a reducible input that can be called repetivitely as to achieve a final result. In pseudo code a recursive algorithm can be formulated as:
input = a reduced value or input items
if input has reached final state: return final value
operation = perform something on input and reduce it, combine with return value of this algorithm with reduced input.
For example, the fibonacci suite:
def fibonacci(val):
if val == 1:
return 1
return fibonacci(val - 1) + val
If you wanted to recusively add elements from a list:
def sum_recursive(list):
if len(list) == 1:
return list[0]
return sum_recursive(list[:-1]) + list[-1]
Hope it helps.
UPDATE
From comments and original question edits, it appears that we are rather looking for INTEGER solutions to the equation. Of non-negative values. That is quite different.
1) Step one find bounds: use the equation ax + by + cz <= 20 with a,b,c > 0 and x,y,z >= 0
2) Step two, simply do [(x, y, z) for x, y, z in zip(bounds_x, bounds_y, bounds_z) if x*11 + y*7 + z*3 - 20 == 0] and you will have a list of valid triplets.
in code:
def bounds(coeff, const):
return [val for val in range(const) if coeff * val <= const]
def combine_bounds(bounds_list):
# here you have to write your recusive function to build
# all possible combinations assuming N dimensions
def sols(coeffs, const):
bounds_lists = [bounds(a, const) for a in coeffs]
return [vals for vals in combine_bounds(bounds_lists) if sum([a*b for a,b in zip(coeff, vals)] - const == 0)
Here is a solution built from your second one, but without the global variable. Instead, each call passes back a list of solutions; the parent call appends each solution to the current element, making a new list to return.
def equation (a, b):
result = []
if len(a) > 1:
# For each valid value of the current coefficient,
# recur on the remainder of the list.
for i in range(b // a[0]+1):
soln = equation(a[1:], b-a[0]*i)
# prepend the current coefficient
# to each solution of the recursive call.
for item in soln:
result.append([i] + item)
else:
# Only one item left: is it a solution?
if b%a[0] == 0:
# Success: return a list of the one element
result = [[b // a[0]]]
else:
# Failure: return empty list
result = []
return result
print(equation([11, 7, 3], 20, []))

Categories

Resources