How to split array but No use loop - python

Determine if it possible to divide a list (lst) at some index such that the sum of values in the first part of the list equals the sum in the latter part of the list.
No loops are used.
def split_array2(lst, all_sum=0):
first = split_array(lst[0:-1])
last = lst[-1]
def sum_(lst):
if len(lst) == 0:
return 0
return lst[0] + sum_[1:]

So something like this?
def canBeSplitted(lst,ind=1):
if ind == len(lst):
return false
return sum(lst[0:ind]) == sum(lst(ind:)) || canBeSplitted(lst,ind+1)
canBeSplitted(lst) #usage

a = [1, 2, 3, 4, 5, 7, 8]
def split_array(a, i=1): # changed to 1 to save 1 function call. AND to be sure that there is a valid split when sum(a)=0.
if i == len(a):
return False
if sum(a[:i]) == sum(a[i:]):
return i
return split_array(a, i+1)
split_array(a)
>>> 5
#sum(a[:5]) = 15
#sum(a[5:]) = 15
This is a recursive function. Recursion is in a lot of cases an alternative to loops.

There is always going to be some loops going on but you can hide them using recursion or library functions (if you're merely aiming to avoir the for/while constructs):
For example:
from itertools import accumulate
from bisect import bisect_right
def splitsum(lst):
i = bisect_right([*accumulate(lst)],sum(lst)/2)
return lst[:i],lst[i:]
L = [1,2,3,4,5,7,8]
print(*splitsum(L))
If you only need to determine if it is possible or not, you could return sum(lst[:i])==sum(lst[i:]) or better yet simply check if sum(lst)/2 is in accumulate(lst).

Related

how to Find the largest element in a list using recursion python?

i = 0
def find_max(seq):
if i == len(seq) - 1:
return seq[0]
else:
first = seq[i]
i = i + 1
max_of_rest = find_max(seq)
return max(first, max_of_rest)
I do not know what is wrong with this function? It is a infinite loop.
Please check out the following solution and follow comments:
def find_biggest(_list, max_element, first_run):
"""
_list is a list of floats or integers or both,
max element is used to store max value,
first run checks if _list is not empty
"""
if first_run and not _list: # check if _list is not empty
raise ValueError("_list should have float or integer values inside")
first_run = False
if not _list: # exit from recursion, we checked all elements
return max_element
element = _list.pop() # take one element
if type(element) not in (int, float,): # check element type
raise TypeError("_list should contain only int or float values")
if element >= max_element: # check if it is more than max
max_element = element
return find_biggest(_list, max_element, first_run) # next step of recursion
if __name__ == "__main__":
# test
print(find_biggest([-1, 4, 2, 3, 1, 0, 10, 3, 1, 7], 0, True))
# print(find_biggest([], 0, True)) # empty case
# print(find_biggest([-1, 4, 2, 3, "1", 0, 10, 3, 1, 7], 0, True)) # string in list
You can check this:
def find_max(seq):
if len(seq) == 1:
return seq[0]
else:
if seq[0] > seq[1]:
seq.pop(1)
else:
seq.pop(0)
return find_max(seq)
Your code has a lot of indentation issues, that may skip execution of some lines.
Your code should look like this:
i = 0
def find_max(seq):
global i
if i == len(seq) - 1:
return seq[0]
else:
first = seq[i]
i = i + 1
max_of_rest = find_max(seq)
return max(first, max_of_rest)
You missed the global, and thus there is no definition of i inside the function.
Your code contains an IndentationError and does not reduce its data on recursive calls - hence data never getting shorter - hence never ending recursion:
def find_max(seq):
if i == len(seq) - 1: # fixed indentation here and below
return seq[0]
else:
first = seq[i]
i = i + 1
max_of_rest = find_max(seq) # never reducing your data size, hence endless
return max(first, max_of_rest)
This would be a fixed recursive solution:
def find_max(seq):
if not seq:
return None # or raise ValueError if you want find_max([]) to crash
if len(seq) == 1:
return seq[0]
else:
return max(seq[0], find_max(seq[1:]))
The problem is inheritently bad for recursive solutions, it is far better to solve it linearly (no max(..) calls needed):
def find_max_lin(seq):
if not seq:
return None
m = seq[0]
for value in seq[1:]:
m = m if value < m else value
return m
or even better simply use the built in max(sequence):
def find_max_builtin(seq):
# no need to create your own function for that though
return max(seq)
See ternary operator for an explanation of what m = m if value < m else value does.
You are using uneeded i variable, in recursion you have base case (your first if), and recursion case, which in this case would be accessing first and second element of your list. As you already checked that the list seq has more than 1 element, you can confidently access positions 0 and 1 of the list.
In your specific case, you are not really using recursion because you never reduce your case, but instead you increment an i variable, whilst recursion is based on always calling the same function with a "simpler" or reduced problem.
With that in mind, several things can be improved in your solution.
i = 0 # Not adviced
def find_max(seq):
# Here you want to check length, making it
# depend on i = problems
if i == len(seq) - 1:
return seq[0]
else:
first = seq[i] # Remove all references to i
i = i + 1 # Remove
# Here you want to call the function with the list
# except the element you know is lower, making the problem
# smaller until you get to the base case
# Instead you are calling find_max with the same
# sequence you had (infinite loop) and returning a
# totally different result.
max_of_rest = find_max(seq)
return max(first, max_of_rest)
A complete solution based on your code would look like this
def find_max(seq):
if len(seq) == 0:
return None
if len(seq) <= 1:
return seq[0]
else:
current_max = max(seq[0], seq[1])
reduced_seq = [current_max] + seq[2:]
return find_max(reduced_seq)
i = 0
def find_max(seq):
global i
if i == len(seq) :
return seq[0]
else:
first = seq[i]
i = i + 1
max_of_rest = find_max(seq)
return max(first, max_of_rest)
print(find_max([-10,2,4,-5]))
thank me later

Strictly increasing difference between adjacent elements in a list

Write a function expanding(l) that takes as input a list of integer l and returns True if the absolute difference between each adjacent pair of elements strictly increases.
I tried to execute this code but this isn't returning correct value for some lists.
def expanding(l):
for i in range(0,len(l)-3):
if (abs(l[i+2]-l[i+1])>abs(l[i+1]-l[i])):
Answer=True
else:
Answer=False
return Answer
expanding([1,3,7,2,-3]) should be False but the output is True.
Use a temporary variable to store the difference, and exit once you reach a non-increasing difference.
def expanding(l):
dif = abs(l[1] - l[0])
for i in range(1, len(l)-1):
temp = abs(l[i+1] - l[i])
# Non-increasing difference, return
if temp < dif:
return False
else:
dif = temp
# All differences are increasing
return True
Yet another solution using iterators:
from itertools import tee, islice, starmap
from operator import lt, sub
def pairwise(x):
a, b = tee(x, 2)
return zip(a, islice(b, 1, None))
a = [1,3,7,2,-3]
pairs = pairwise(a) # this will be (a[0], a[1]), (a[1], a[2]), ...
# The next will produce the result abs(a[1]-a[0]), abs(a[2]-a[1]), ...
differences = map(abs, starmap(sub, pairs))
# This will be abs(a[2]-a[1])>abs(a[1]-a[0]), abs(a[3]-a[2])>abs(a[2]-a[1]), ...
cmp = starmap(lt, pairwise(differences))
# Differences strictly increases if all items in cmp are evaluated to True...
result = all(cmp)
print(result)
The output for such input is False
Numpy is your friend:
import numpy as np
x=np.array([1,3,7,2,-3])
(np.diff(abs(x[1:] - x[:-1])) > 0).all() # returns False
If you're fancy a function, I would do like this:
def expanding(l):
# convert list to np.array if a list was passed
if isinstance(l, list):
l = np.array(l)
return (np.diff(abs(l[1:] - l[:-1])) > 0).all()
I would recommend writing the condition in an iterator that you then pass to any so to make sure that on the first occurrence of a non-expanding difference the iteration stops and False is returned.
Here is how this would look:
def expanding(l):
return not any((abs(l[i-1]-l[i])>=abs(l[i]-l[i+1]) for i in range(1,len(l)-1)))
def expanding(L):
x=list()
for i in range(len(L)-2):
if abs(L[i+1]-L[i+2]) > abs(L[i]-L[i+1]):
x.append(True)
else:
x.append(False)
return all(x)
print(expanding([1,3,7,2,9]))
Output:
True
Explanation:
when we calculate difference list for the given list -> [2,4,5,7]
The difference list is strictly increasing.
Print(expanding([1,3,7,2,-3]))
Output:
False
Explanation:
when we calculate difference list for the given list -> [2,4,5,5]
The difference list is not increasing (i.e., 5>5 is False)
def expanding(l):
for i in range(0,len(l)-2):
if (abs(l[i+2]-l[i+1])>abs(l[i+1]-l[i])):
Answer=True
else:
Answer=False
return Answer
return Answer
expanding([1,3,7,2,-3])
As soon as you know that one item is out of order you should answer False for the whole list without waiting,so that other pairs not change the answer.
Also note the change from range(0,len(l)-3) to range(0,len(l)-2). The original implementation was missing the last pair of list elements.
Your logic is a little bit wrong. Once you know that one item is out of order you should answer False for the whole list.
def expanding(l):
for i in range(0,len(l)-3):
if (abs(l[i+2]-l[i+1])<=abs(l[i+1]-l[i])):
return False
return True
Code Written By Debkanta Mondal
Python3
def expanding(l):
dif=[]
for x,y in zip(l,l[1:]):
diff=abs(y-x)
dif.append(diff)
return all(i<j for i,j in zip(dif,dif[1:]))
print(expanding([1,3,7,2,-3]) )

How to split a list only using car, cdr, cons and other functions (python)

we need to be able to make a function that has 1 list as an input. We need to split the even numbers from the uneven numbers and put them in seperate lists. We are not permitted to make a second list and should be able to solve it only using recursion, and with car, cdr, cons, ... .
This is what I already have:
def split_list(list_a):
if null(list_a):
return []
elif not even(car(list_a)):
return cons(car(list_a), split_list(cdr(list_a)))
else:
return cons(splits_lijst(cdr(list_a)), car(list_a))
print(split_list([1, 2, 3, 4]))
I became the output: [1, 3, 4, 2]
While it should be: [1, 3][2, 4]
I really have no clue how to do this without making a secondary list.
Just to be clear, the functions in the function 'split_list' are car, cdr, cons, null and even. Here you see the contents of those functions:
def car(a_list):
return a_list[0]
def cdr(a_list):
return a_list[1:]
def null(a_list):
return True if len(a_list) == 0 else False
def cons(a, b):
new_list = []
if type(a) is list:
for item in a:
new_list.append(item)
else:
new_list.append(a)
if type(b) is list:
for item in b:
new_list.append(item)
else:
new_list.append(b)
return new_list
def even(x):
if x == 1:
return False
elif x == 0:
return True
else:
return even(x-2)
You need a way to make two lists during your iteration of one list. The best way to do that is to make a function that takes 3 arguments. one for the input and 2 for the two output lists, often called accumulators.
The logic would be to return a list of the two accumulators when you have reached the end of the list. If not you check the element for evenness and recurse by adding it to the even accumulator. If not you recurse by adding the element to the odd accumulator.
I think this would help you.
l=list(range(10))
evens=[]
odds=[]
for x in l:
if x%2==0:
evens.append(x)
else:
odds.append(x)
print(evens,odds)
the below one will use only one additional list,(in case you don't require the original one):
l=list(range(10))
odds=[]
for x in l:
if x%2==0:
continue
else:
l.remove(x)
odds.append(x)
print(l,odds)

What is the best way to fix a list index out of range exception?

I have written this recursive code in Python:
def suma(i,l):
if i == 0:
return l[i]
else:
return suma(i-1,l)+l[i]
And whenever I call the function by suma(3,[7,2,3]) and run it, I get this error message:
List index out of range on line return suma(i-1,l)+l[i]
Ok, I'm going to assume that the intent here is to recursively add the first i elements of l and return the result. If so, here's a concise way to do so:
def suma(i,l):
return 0 if i == 0 else suma(i-1,l)+l[i-1]
This is equivalent to:
def suma(i,l):
if i == 0:
return 0
else
return suma(i-1,l)+l[i-1]
It's unorthodox, but you could just call your suma() function with the first argument reduced by 1:
>>> l = [7, 2, 3]
>>> suma(len(l)-1, l)
12
But it could be better written like this:
def suma(l):
if len(l) > 1:
return suma(l[:-1]) + l[-1]
return l[0]
>>> suma([7,2,3])
12
>>> suma(range(1,11))
55
This has the advantage of not requiring the length of the list to be passed to the sum function at all - the length is always available using len().

Calling a function recursively in Python by passing a List

I know there are easier ways to create a function which gives you the largest number in a list of numbers but I wanted to use recursion. When I call the function greatest, i get none. For example greatest([1,3,2]) gives me none. If there are only two elements in the list, I get the right answer so I know the problem must be with the function calling itself. Not sure why though.
def compare(a,b):
if a==b:
return a
if a > b:
return a
if a < b:
return b
def greatest(x):
if len(x)==0:
return 0
i=0
new_list=[]
while i< len(x):
if len(x)-i>1:
c=compare(x[i],x[i+1])
else:
c=x[i]
new_list.append(c)
i=i+2
if len(new_list)>1:
greatest(new_list)
else:
return new_list[0]
print greatest([1,3,2])
This line:
if len(new_list)>1:
greatest(new_list) # <- this one here
calls greatest but doesn't do anything with the value it returns. You want
return greatest(new_list)
After fixing that, your function seems to behave (although I didn't look too closely):
>>> import itertools
>>> for i in range(1, 6):
... print i, all(max(g) == greatest(g) for g in itertools.product(range(-5, 5), repeat=i))
...
1 True
2 True
3 True
4 True
5 True
A simple recursion can be like this :
from random import *
def greatest(x,maxx=float("-inf")):
if len(x)>0:
if x[0] > maxx:
maxx=x[0]
return greatest(x[1:],maxx)
else:
return maxx
lis=range(10,50)
shuffle(lis)
print greatest(lis) #prints 49

Categories