Find 3 consecutive missing integers from an array - python

below is the code to find out the missing numbers, but need to select first 3 consecutive numbers from missings
array=[0,1,4,5,9,10]
start=0
end=15
missings=[]
for i in range(start,end):
if i not in array:
missings.append(i)
output: [6,7,8]

Here you go:
array=[0,1,4,5,9,10]
start=0
end=15
missings=[]
for i in range(start,end-1):
if i not in array:
if i+1 not in array:
if i+2 not in array:
missings.append(i)
missings.append(i+1)
missings.append(i+2)
break

Sort the list in ascending order, then compare the values in the array with their neighbor to determine if there is a gap >3.
def find_missing(arr):
sorted_list = sorted(arr)
# Set our lowest value for comparing
curr_value = sorted_list[0]
for i in range(1,len(sorted_list)):
# Compare the previous value to the next value to determine if there is a difference of atleast 4 (6-3 = 3 but we are only missing numbers 4 and 5)
if (sorted_list[i] - curr_value) > 3:
# Return on the first 3 consecutive missing numbers
return [curr_value+1, curr_value+2, curr_value+3]
curr_value = sorted_list[i]
# Return an empty array if there is not 3 consecutive missing numbers
return []
This function works based on the length of the array and the largest number. If there is a need for a specified end value in case all elements in the array do not have a gap of three except for the largest element and the end value, it can be passed as a parameter with some minor modifications.
def find_missing(arr, start_val=0, end_val=0):
# Sorting a list alters the source, so make a copy to not alter the original list
sorted_list = sorted(arr)
curr_value = sorted_list[0]
last_value = sorted_list[-1]
# Make sure start val is the lowest number, otherwise use lowest number
if start_val < curr_value and (curr_value - start_val) > 3:
return [start_val, start_val+1, start_val+2]
for i in range(1,len(sorted_list)):
# Compare the previous value to the next value to determine if there is a difference of atleast 4 (6-3 = 3 but we are only missing numbers 4 and 5)
if (sorted_list[i] - curr_value) > 3:
# Return on the first 3 consecutive missing numbers
return [curr_value+1, curr_value+2, curr_value+3]
curr_value = sorted_list[i]
# If there is an end_value set that has a gap between the largest number and is larger than the last value
if end_val > last_value and (end_val - last_value) > 3:
return [last_value+1, last_value+2, last_value+3]
else:
# Return an empty array if there is not 3 consecutive missing numbers
return []

Related

Deleting matching items from a list

I have a list of values. I would like to remove values which cancel to each other (+ and -). The values are randomly in the list, so I first added a new column in excel with the absolute values. I then sorted on the absolute values so the amounts which needs to be cancelled are below each other.
I was thinking to create a for loop and sum up the ifrst row with the second row, and when this sums to zero, delete both rows and start from the top again. Please refer to the picture of an example. I have marked yellow the items which should be deleted. As I only want to delete matching items, the total sum of the amount column should not change after the operation.
Currently I have something like this
for i in df["Amount in Entity Currency"]:
if df["Amount in Entity Currency"][i] + df["Amount in Entity Currency"][i+1] == 0:
df.drop(df[df["Amount in Entity Currency"][i]])
df.drop(df[df["Amount in Entity Currency"][i + 1]])
try sth like this after you have sorted the list (as you already said):
for i,elem in enumerate(yourList):
nextElem = yourList[i+1]
if (elem + nextElem < 0.00000001):
yourList.remove(elem)
yourList.remove(nextElem)
I would base an answer off of several building blocks. First is creating two "iterable" sub-lists. One for positive numbers and the other negative numbers.
Then I would iterate over both of them using next() and as long as one of the two lists had values I would act on the current values as appropriate.
import random
full_data = [random.randint(0, 10) for _ in range(20)] + [-random.randint(0, 10) for _ in range(20)]
zeros = [i for i in full_data if i == 0]
positives = iter(sorted([i for i in full_data if i > 0]))
negatives = iter(sorted([i for i in full_data if i < 0], reverse=True))
## ------------------------------
## prime the list with zero or 1 0s where an odd number of 0s
## results in [0] as the evens cancel each other out.
## ------------------------------
result = [0] * (len(zeros) % 2)
## ------------------------------
pos = next(positives, None)
neg = next(negatives, None)
while pos is not None or neg is not None:
if pos is None:
# we ran out of positive numbers so add any remaining negatives
result.extend([neg] + list(negatives))
break
if neg is None:
# we ran out of negative numbers so add any remaining positives
result.extend([pos] + list(positives))
break
if pos == -neg:
# these results cancel each other
pos = next(positives, None)
neg = next(negatives, None)
elif pos > -neg:
# this positive is "larger" then this negative so add the negative
result.append(neg)
neg = next(negatives, None)
else:
# this positive is "smaller" than this negative so add the positive
result.append(pos)
pos = next(positives, None)
print(f"The original list has {len(full_data)} items and sums to: {sum(full_data)}")
print(f"The filtered list has {len(result)} items and sums to: {sum(result)}")

indexError: list indexing error and wrongful tracking of counters

The goal of the program is to define a procedure that takes in a string of numbers from 1-9 and outputs a list with the following parameters:
Every number in the string should be inserted into the list.
If a number x in the string is less than or equal to the preceding number y, the number x should be inserted into a sublist. Continue adding the following numbers to the sublist until reaching a number z that is greater than the number y.
Then add this number z to the normal list and continue.
#testcases
string = '543987'
numbers_in_lists(string)
result = [5,[4,3],9,[8,7]]
def numbers_in_lists(string):
# Convert the sequence of strings into an array of numbers
i = 0
conv_str_e = []
while i < len(string):
conv_str_e.append(int(string[i]))
i += 1
#official code starts here
normal_list = []
list_of_small_nums = [[]]
# This will help me keep track of elements of the normal_list.
previous_e_pos = -1
e_pos = 0
# this one will be used to decide if the element should go into the
#normal_list or list_of_small_nums
check_point = 0
for e in conv_str_e:
#The first element and every elements bigger the element with
#check_point as it's index
#will be put into the normal_list as long as the list inside
#list_of_small_nums is empty
if e_pos == 0 or e > conv_str_e[check_point]:
#If the list inside list_of_small_nums is not empty
if list_of_small_nums[0] != []:
#concatenate the normal_list and list_of_small_nums
normal_list = normal_list + list_of_small_nums[0]
#Clear the list inside list_of_small_nums
list_of_small_nums[0] = []
#Add the element in the normal_list
normal_list.append(e)
# Update my trackers
e_pos += 1
previous_e_pos += 1
# (not sure this might be the error)
check_point = e_pos
#The curent element is not bigger then the element with the
#check_point as index position
#Therefor it goes into the sublist.
list_of_small_nums[0].append(e)
e_pos += 1
previous_e_pos += 1
return list
What you were doing wrong was exactly what you pointed out in your comments. You just kept increasing e_pos and so check_point eventually was greater than the length of the list.
I took the liberty of changing some things to simplify the process. Simple programs make it easier to figure out what is going wrong with them. Make sure you always try to think about the simplest way first to solve your problem! Here, I replaced the need for e_pos and previous_e_pos by using enumerate:
string = '543987'
# Convert the sequence of strings into an array of numbers
conv_str_e = [int(i) for i in string]
#official code starts here
normal_list = []
list_of_small_nums = []
# this one will be used to decide if the element should go into the
#normal_list or list_of_small_nums
check_point = 0
for ind, e in enumerate(conv_str_e):
#The first element and every elements bigger the element with
#check_point as it's index
#will be put into the normal_list as long as the list inside
#list_of_small_nums is empty
if ind == 0 or e > conv_str_e[check_point]:
#If the list inside list_of_small_nums is not empty
if list_of_small_nums != []:
#concatenate the normal_list and list_of_small_nums
normal_list.append(list_of_small_nums)
#Clear the list inside list_of_small_nums
list_of_small_nums = []
#Add the element in the normal_list
normal_list.append(e)
# Update my trackers
check_point = ind
else:
#The curent element is not bigger then the element with the
#check_point as index position
#Therefore it goes into the sublist.
list_of_small_nums.append(e)
# If there is anything left, add it to the list
if list_of_small_nums != []:
normal_list.append(list_of_small_nums)
print(normal_list)
Result:
[5, [4, 3], 9, [8, 7]]
I am sure you can change it appropriately from here to put it back in your function.

Use pandas to count value greater than previous value

I am trying to count the number of times a value is greater than the previous value by 2.
I have tried
df['new'] = df.ms.gt(df.ms.shift())
and other similar lines but none give me what I need.
might be less than elegant but:
df['new_ms'] = df['ms'].shift(-1)
df['new'] = np.where((df['ms'] - df['new_ms']) >= 2, 1, 0)
df['new'].sum()
Are you looking for diff? Find the difference between consecutive values and check that their difference is greater than, or equal to 2, then count rows that are True:
(df.ms.diff() >= 2).sum()
If you need to check if the difference is exactly 2, then change >= to ==:
(df.ms.diff() == 2).sum()
Since you need a specific difference, gt won't work. You could simply subtract and see if the difference is bigger than 2:
(df.ms - df.ms.shift() > 2).sum()
edit: changed to get you your answer instead of creating a new column. sum works here because it converts booleans to 1 and 0.
your question was ambiguous but as you wanted to see a program where number of times a value is greater than the previous value by 2 in pandas.here it is :
import pandas as pd
lst2 = [11, 13, 15, 35, 55, 66, 68] #list of int
dataframe = pd.DataFrame(list(lst2)) #converting into dataframe
count = 0 #we will count how many time n+1 is greater than n by 2
d = dataframe[0][0] #storing first index value to d
for i in range(len(dataframe)):
#print(dataframe[0][i])
d = d+2 #incrementing d by 2 to check if it is equal to the next index value
if(d == dataframe[0][i]):
count = count+1 #if n is less than n+1 by 2 then keep counting
d = dataframe[0][i] #update index
print("total count ",count) #printing how many times n was less than n+1 by 2

Python - Storing index number of an array with comparison of the value with an integer

I'm trying to figure out how to store the index of a value or both. Steps:
Scan array (one by one)
compare each value is greater than a certain number
If it is greater, save the index number and value
Next, check next number, is it greater than certain number? move to next
if the number is less than certain number, break
y1 = [] % Is a 128 length array
flagcheck = 0 %check for when found a number greater than needed
startofindex = [] %Place to save where the 1st number was found
endofindex = [] %Place where end
for g in y1:
if (y1.count(g) > 0.001):
startofindex.append(enumerate(y1.count(g))) % I know this won't work but I can't seem to find the best sol'n
flagcheck = 1;
while (flagcheck == 1):
for g in y1:
if (y1.count(g) <= 0.001):
endofindex.append(enumerate(y1.count(g)))
break
I want to use index to format a graph's axis for particular points.

Python: find smallest missing positive integer in ordered list

I need to find the first missing number in a list. If there is no number missing, the next number should be the last +1.
It should first check to see if the first number is > 1, and if so then the new number should be 1.
Here is what I tried. The problem is here: if next_value - items > 1:
results in an error because at the end and in the beginning I have a None.
list = [1,2,5]
vlans3=list
for items in vlans3:
if items in vlans3:
index = vlans3.index(items)
previous_value = vlans3[index-1] if index -1 > -1 else None
next_value = vlans3[index+1] if index + 1 < len(vlans3) else None
first = vlans3[0]
last = vlans3[-1]
#print ("index: ", index)
print ("prev item:", previous_value)
print ("-cur item:", items)
print ("nxt item:", next_value)
#print ("_free: ", _free)
#print ("...")
if next_value - items > 1:
_free = previous_value + 1
print ("free: ",_free)
break
print ("**************")
print ("first item:", first)
print ("last item:", last)
print ("**************")
Another method:
L = vlans3
free = ([x + 1 for x, y in zip(L[:-1], L[1:]) if y - x > 1][0])
results in a correct number if there is a gap between the numbers, but if no space left error occurs: IndexError: list index out of range. However I need to specify somehow that if there is no free space it should give a new number (last +1). But with the below code it gives an error and I do not know why.
if free = []:
print ("no free")
else:
print ("free: ", free)
To get the smallest integer that is not a member of vlans3:
ints_list = range(min(vlans3), max(vlans3) + 1)
missing_list = [x for x in ints_list if x not in vlans3]
first_missing = min(missing_list)
However you want to return 1 if the smallest value in your list is greater than 1, and the last value + 1 if there are no missing values, so this becomes:
ints_list = [1] + list(range(min(vlan3), max(vlan3) + 2))
missing_list = [x for x in ints_list if x not in vlan3]
first_missing = min(missing_list)
First avoid using reserved word list for variable.
Second use try:except to quickly and neatly avoid this kind of issues.
def free(l):
if l == []: return 0
if l[0] > 1: return 1
if l[-1] - l[0] + 1 == len(l): return l[-1] + 1
for i in range(len(l)):
try:
if l[i+1] - l[i] > 1: break
except IndexError:
break
return l[i] + 1
How about a numpy solution? Below code works if your input is a sorted integer list with non-duplicating positive values (or is empty).
nekomatic's solution is a bit faster for small inputs, but it's just a fraction of a second, doesn't really matter. However, it does not work for large inputs - e.g. list(range(1,100000)) completely freezes on list comprehension with inclusion check. Below code does not have this issue.
import numpy as np
def first_free_id(array):
array = np.concatenate((np.array([-1, 0], dtype=np.int), np.array(array, dtype=np.int)))
where_sequence_breaks = np.where(np.diff(array) > 1)[0]
return where_sequence_breaks[0] if len(where_sequence_breaks)>0 else array[-1]+1
Prepend the array with -1 and 0 so np.diff works for empty and 1-element lists without breaking existing sequence's continuity.
Compute differences between consecutive values. Seeked discontinuity ("hole") is where the difference is bigger than 1.
If there ary any "holes" return the id of the first one, otherwise return the integer succeeding the last element.

Categories

Resources