Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get start point of numbers in sequence and handle errors?

Let me start with an example,

array([  1,   6,  12,  14,  16,  18,  21,  23,  24,  27,  29,  54,  55,
        56,  57,  58,  59,  60,  61,  63,  64,  65,  66,  67,  68,  69,
        70,  71,  72,  74,  75,  76,  77,  78,  79,  81,  82,  83,  84,
        85,  86,  87,  88,  89,  90,  91,  92,  93,  94,  95,  96,  97,
        98,  99, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
       112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
       125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 138,
       139, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
       153, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166,
       167, 168, 169, 170, 171, 172, 173, 174, 175, 177, 178])

Ideal Output: 54 (forward), 175 (backward)

Conditions to satisfy :

I need to find the first number from where its sequential in order for up-to 5 digits, for ex: from 54 onward the numbers are sequential in order (i.e., 54, 55, 56, 57, 58) (5 digits).

I require the same in reverse order (i., 175, 174, 173, 172, 171) (5 digits) from point 175 its sequential in order.

Update: I forgot to mention, in some cases I need a variable to assign the error that is acceptable.

For example, lets say the error_accepted = 1 and error_difference(upto) = 1, then if the values are 54, 56, 57, 58, 59 can be accepted. The output is still 54. Else, if error_accepted = 2 and error_difference (upto) = 3, then if the values are 54, 58, 59, 61, 62 can also be accepted. The output is still 54.

I tried to do something, the logic is not correct so please do excuse the code I have written.

# excuse the code, the logic ain't correct. 
start_ix_cnt = 0
start_ix_indices = None

counter_start = 0
counter = 0

for ix in matching_indexes:
    if start_ix_indices is None and start_ix_cnt == 0:
        start_ix_indices = list(range(1, 178))
        start_ix_cnt += 1
    else:
        if ix == start_ix_indices[start_ix_cnt]:
            counter += 1
            counter_start = start_ix_indices[0]
        else:
            start_ix_indices = list(range(ix, 178))
            start_ix_cnt = 0

Any help is appreciated.

like image 833
user_12 Avatar asked Mar 02 '23 15:03

user_12


2 Answers

Using Numpy you can split your array into sequential sets and find the sequence you're looking for using the length of set and/or its items:

In [96]: mask = np.diff(arr) != 1

In [97]: np.split(arr, np.where(mask)[0] + 1)
Out[97]: 
[array([1]),
 array([6]),
 array([12]),
 array([14]),
 array([16]),
 array([18]),
 array([21]),
 array([23, 24]),
 array([27]),
 array([29]),
 array([54, 55, 56, 57, 58, 59, 60, 61]),
 array([63, 64, 65, 66, 67, 68, 69, 70, 71, 72]),
 array([74, 75, 76, 77, 78, 79]),
 array([81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
        98, 99]),
 array([101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113,
        114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,
        127, 128, 129, 130, 131, 132, 133, 134, 135, 136]),
 array([138, 139]),
 array([141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153]),
 array([155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167,
        168, 169, 170, 171, 172, 173, 174, 175]),
 array([177, 178])]

You can use following function in order to handle the accepted margin error:

In [98]: def sequencer(arr, err=1):
    ...:     mask = np.diff(arr) > err
    ...:     return np.split(arr, np.where(mask)[0] + 1)
like image 77
Mazdak Avatar answered Mar 05 '23 17:03

Mazdak


# forward
for i in range(len(a)-5):
    if a[i+5] - a[i] <= 5 + upto:
        print(a[i])
        break

# reverse
for i in range(len(a)-1, 5, -1):
    if a[i] - a[i-5] <= 5 + upto:
        print(a[i])
        break
like image 40
Woodford Avatar answered Mar 05 '23 15:03

Woodford