Strictly increasing difference between adjacent elements in a list - python

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

Related

How to check if a number in a list range

I have a float number x and a list range list_ = [[a, b], [c,d], [e,f]]
How can check if the number x is in the list. It means the function will return True in case of
a<=x <=b
or
c<=x <=d
or
e<=x <=f
Otherwise, the function will return False. Could you help me to write a Python code for the function
function (x, list_)--> True/False
Clean solution:
def function(x, list_):
return any([l[0] < x < l[1] for l in list_])
Optimized solution:
def function(x, list_):
for l in list_:
if l[0] < x < l[1]:
return True
return False
The idiomatic solution would be this:
def f(x: int, ls: List[Tuple[float, float]]) -> bool:
return any(a <= x <=b for (a, b) in ls)
Take specific note of the following:
Naming a function function is a super poor idea.
It is abnormal and therefore a poor idea to name a variable list_ just to avoid overriding a keyword.
Using the form any ensures that you quickly quit when you find a valid solution.
You can quickly destructure your tuple (or list, if you happen to pass a list) using the for (a, b) in ls clause.
This solution is as quick as if you use a for clause, but all of that is premature optimization anyway.
Using an explicit destructing ensures you have two and only two elements for your sublist.
It was requested that I check certain inputs:
>>> f(10.1, [[8.1, 12.1], [110, 120]])
True
Seems to work!
If you're running into NameError, the issue is simply one of the importation of types. You can either define f like so:
def f(x, ls):
... // As you would otherwise
Or import the required types to make the type-hinting work properly:
from typing import List, Tuple
def f(x: int, ls: List[Tuple[float, float]]) -> bool:
... // As you would otherwise
This has little to do with the original question or solution - it's just standard for type hinting in python.
def function(x,list__):
for [a,b] in list_data:
if a<=x<=b:
return True
return False
You can simply iterate through the list and find whether it's in range or not.
I'm generating the variable and the list randomly and calling a function that iterates and checks whether the variable lies within the range of any of the members of the list.
import numpy as np
def find_if_in_range(list_, var) -> bool:
for i in list_:
if i[0] <= var <= i[-1]:
return True
return False
var = np.random.randint(10)
list_ = np.random.randint(10, size=(3,2), dtype=np.uint8)
print(f"var: {var}")
print(f"list: {list_}")
res = find_if_in_range(list_, var)
print(res)
Output:
var: 0
list: [[0 6]
[2 7]
[7 9]]
True
Hope this helps.
Cheers.

how to check if a list is a consecutive number in python?

How to write python code that let the computer know if the list is a right sequence and the position doesn't matter, it will return true, otherwise it return false.
below are some of my example, I really don't know how to start
b=[1,2,3,4,5] #return true
b=[1,2,2,1,3] # return false
b=[2,3,1,5,4] #return true
b=[2,4,6,4,3] # return false
sort function is O(nlogn), we can use for loop which is O(n):
def check_seq(in_list):
now_ele = set()
min_ele = max_ele = in_list[0]
for i in in_list:
if i in now_ele:
return False
min_ele = min(i, min_ele)
max_ele = max(i, max_ele)
now_ele.add(i)
if max_ele-min_ele+1 == len(in_list):
return True
return False
Create a set and one to compare with -- based on minimum and maximum:
isRightSequence = set(range(min(b), max(b)+1)) == set(b)
This question is quite simple and can be solved a few ways.
The conditional approach - if there is a number that is bigger than the length of the list, it automatically cannot be a sequence because there can only be numbers from 1-n where n is the size of the list. Also, you have to check if there are any duplicates in the list as this cannot be possible either. If none of these conditions occur, it should return true
Using dictionary - go through the entire list and add it as a key to a dictionary. Afterwards, simply loop through numbers 1-n where n is the length of the list and check if they are keys in the dictionary, if one of them isn't, return false. If all of them are, return true.
Both of these are quite simply approaches and you should be able to implement them yourselves. However, this is one implementation for both.
1.
def solve(list1):
seen = {}
for i in list1:
if i > len(list1):
return False
if i in seen:
return False
seen[i] = True
return False
def solve(list1):
seen = {}
for i in list1:
seen[i] = True
for i in range (1, len(list1)+1):
if i not in seen:
return False
return True
This solution needs O(n) runtime and O(n) space
def is_consecutive(l: list[int]):
if not l:
return False
low = min(l)
high = max(l)
# Bounds Check
if high - low != len(l) - 1:
return False
# Test all indices exist
test_vec = [False] * len(l) # O(n)
for i in range(len(l)):
test_vec[l[i] - low] = True
return all(test_vec)
assert is_consecutive(range(10))
assert is_consecutive([-1, 1,0])
assert not is_consecutive([1,1])
assert not is_consecutive([1,2,4,6,5])

Loop through int array, return True if following int is equal to current

Given a list of ints, return True if the array contains a 3 next to a 3 somewhere.
has_33([1, 3, 3]) → True
has_33([1, 3, 1, 3]) → False
has_33([3, 1, 3]) → False
First Approch:
def has_33(nums):
for i in range(0,len(nums)):
return nums[i] == nums[i+1] ==3
Could someone explain me what's wrong with this approach, I see that this code is returning True only if all the elements in a list are true.
Second Approach:
def has_33(nums):
for i in range(0,len(nums)):
if(nums[i] == nums[i+1] ==3):
return True
The second approach satisfies my question.
What is the difference between these two approaches?
Well, the difference is rather obvious. In the first case, you inconditionnaly return the result of expression nums[i] == nums[i+1] ==3, whatever the value of this expression is. This actually means that you always return on the very first iteration, so your code could as well be written as
def has_33(nums):
if len(nums):
return nums[0] == nums[1] ==3
In the second case, you only return if the expression is true, so the iteration goes on until either you explicitely return (found a match) or the iteration naturally terminates and you've found nothing (in which case the function will implicitely return None).
Unrelated, but your code (second version) can be improved in quite a few ways. First point: Python "for" loop are of the "foreach" kind - you iterate on the sequence elements, not indices. If you don't need the indice, the proper way is
for item in iterable:
do_something_with(item)
no need for range(len(xxx)) and indexed access here.
If you do need both the item and the index, then enumerate() is your friend - it yields (index, item) tuples:
for index, item in enumerate(sequence):
print("item at {} is {}".format(index, item))
Now for your current need - geting (item, nextitem) pairs -, there's still another solution: zip(seq1, seq2) + slicing:
for item, nextitem in zip(sequence, sequence[1:]):
print("item: {} - nextitem : {}".format(item, nextitem))
and finally, if what you want is to check if at least one item in a sequence satisfies a condition, you can use any() with a predicate:
def has_33(nums):
return any((item == nextitem == 3) for item, nextitem in zip(nums, nums[1:]))
Another solution could be to turn nums into a string and look for the literal string "33" in it:
def has_33(nums):
return "33" in "".join(str(x) for x in nums)
but I'm not sure this will be more efficient (you can use timeit to find out by yourself).
In your first approach, you will return the value of
return nums[i] == nums[i+1] == 3 #Where i = 0 since it returns
first iteration.
return nums[0]==nums[1] == 3 #If nums = [0,3,3]
return false # would be your result. But it would never check the next pair of values.
In your second approach, you will return the value
return true #If the if-statement is satisfied
The return function, will end the function call when called. Therefore, if being called in a for-loop without an if-statement, it will be called for the first iteration. If there is an if-statement and the iteration passes through the if-statement, it will return and end the loop at that iteration. Basically, the return function ends the function call and returns the value given.

Python Function with Lists and Sets

So I'm trying to figure out this problem and I can't figure out why it isn't working.
The premise is that you're given an input list and you have to find the second-lowest value. The list can have any number of integers and can repeat values; you can't change the list.
My code:
def second_min(x):
input_list = list(x)
print input_list
list_copy = list(input_list)
list_set = set(list_copy)
if len(list_set) > 1:
list_copy2 = list(list_set)
list_copy2 = list_copy2.sort()
return list_copy2[1]
else:
return None
print second_min([4,3,1,5,1])
print second_min([1,1,1])
The outputs for those two inputs are:
3
None
It's giving me errors on lines 9 and 13.
TypeError: 'NoneType' object has no attribute '__getitem__'
Thanks!
list_copy2 = list_copy2.sort()
.sort() sorts the list in place and returns None. So you're sorting the list, then throwing it away. You want just:
list_copy2.sort()
Or:
list_copy2 = sorted(list_set)
sorted always returns a list, so you can use it to sort the set and convert it to a list in one step!
You need to use sorted instead of sort. sorted returns a new list, that is a sorted version of the original. sort will sort the list in-place, and returns None upon doing so.
def second_min(x):
if len(x) > 1:
return sorted(x)[1]
else:
return None
>>> second_min([4,3,1,5,1])
1
Help, I can't use sorted! It's not allowed!
def second_min(li):
if len(li) < 2:
return None
it = iter(li)
a, b = next(it), next(it)
next_lowest, lowest = max(a, b), min(a, b)
for x in it:
if x < next_lowest:
if x < lowest:
lowest, next_lowest = x, lowest
else:
next_lowest = x
return next_lowest

How can I return false if more than one number while ignoring "0"'s?

This is a function in a greater a program that solves a sudoku puzzle. At this point, I would like the function to return false if there is more then 1 occurrence of a number unless the number is zero. What do am I missing to achieve this?
L is a list of numbers
l =[1,0,0,2,3,0,0,8,0]
def alldifferent1D(l):
for i in range(len(l)):
if l.count(l[i])>1 and l[i] != 0: #does this do it?
return False
return True
Assuming the list is length 9, you can ignore the inefficiency of using count here (Using a helper datastructure - Counter etc probably takes longer than running .count() a few times). You can write the expression to say they are all different more naturally as:
def alldifferent1D(L):
return all(L.count(x) <= 1 for x in L if x != 0)
This also saves calling count() for all the 0's
>>> from collections import counter
>>> def all_different(xs):
... return len(set(Counter(filter(None, xs)).values()) - set([1])) == 0
Tests:
>>> all_different([])
True
>>> all_different([0,0,0])
True
>>> all_different([0,0,1,2,3])
True
>>> all_different([1])
True
>>> all_different([1,2])
True
>>> all_different([0,2,0,1,2,3])
False
>>> all_different([2,2])
False
>>> all_different([1,2,3,2,2,3])
False
So we can break this down into two problems:
Getting rid of the zeros, since we don't care about them.
Checking if there are any duplicate numbers.
Striping the zeros is easy enough:
filter(lambda a: a != 0, x)
And we can check for differences in a set (which has only one of each element) and a list
if len(x) == len(set(x)):
return True
return False
Making these into functions we have:
def remove_zeros(x):
return filter(lambda a: a != 0, x)
def duplicates(x):
if len(x) == len(set(x)):
return True
return False
def alldifferent1D(x):
return duplicates(remove_zeros(x))
One way to avoid searching for every entry in every position is to:
flags = (len(l)+1)*[False];
for cell in l:
if cell>0:
if flags[cell]:
return False
flags[cell] = True
return True
The flags list has a True at index k if the value k has been seen before in the list.
I'm sure you could speed this up with list comprehension and an all() or any() test, but this worked well enough for me.
PS: The first intro didn't survive my edit, but this is from a Sudoku solver I wrote years ago. (Python 2.4 or 2.5 iirc)

Categories