Emil Mirzayev
Emil Mirzayev

Reputation: 252

Modify a list based on another list and additional criteria

I have deleted the previous question and rewritten it

I have 2 lists of size n (let's assume it is 5):

  1. List a which consists of non-zero random integers

  2. List b which consists of random non-negative integers falling under these criteria:

    • The elements of this list are in descending order. ith element is greater or eqaual to i+1th element
    • The sum of this list is equal to some f (let's assume 10)

Here, I want to modify the list b so that apart from the 2 conditions above, it also complies to this one:

If for some reason, it is not possible to meet all three criteria, the criterium about the sum being equal to f might be loosened and become f-a where a is also subtracted from the list bs right-furtherest element and a is minimum integer possible (see the last example)

Some examples (r is the modified list b):

a = [6, 7, 14, 16, 5]
b = [8, 2, 0, 0, 0]

r = [6, 4, 0, 0, 0]


a = [10, 1, 14, 16, 5]
b = [8, 2, 0, 0, 0]

r = [8, 1, 1, 0, 0]


a = [10, 5, 14, 16, 5]
b = [8, 2, 0, 0, 0] # here, b is already complying to all criteria and result should not change

r = [8, 2, 0, 0, 0]

# another example where this list is of size 14 with `f` being also 14
a = [7, 5, 14, 16, 5, 7, 203, 22, 10, 4, 5, 8, 12, 9]
b = [8, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

r = [7, 5, 2,  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

a = [5, 1, 1, 1, 1]
b = [8, 2, 0, 0, 0]

r = [5, 1, 1, 1, 1]

My numpy approach which is valid for the case where b does not need any editing:

a = [10, 5, 14, 16, 5]

b = [8, 2, 0, 0, 0]

def edit(a, b):
    a_ = np.array(a)
    b_ = np.array(b)
    criteria_check = (a_[:len(b_[b_>0])] >= b_[b_>0])
    if criteria_check.all():
        return b
    else:
        pass


edit(a, b)
[8, 2, 0, 0, 0]

Adding another approach which solves the last example case in numpy:

a = [5, 1, 1, 1, 1]
b = [8, 2, 0, 0, 0]

a = np.array(a)
b = np.array(b)

def edit2(f, s):
    diff = f - s
    s[(s + diff).cumsum()<sum(s)] = (s + diff)[(s + diff).cumsum()<sum(s)]
    return s

Upvotes: 4

Views: 748

Answers (1)

tivole
tivole

Reputation: 95

This solution works on all of your test cases:

def solve(a, b):
    f = 0
    for i in range(len(a) - 1):
        if (a[i] < b[i]):
            b[i+1] += (b[i] - a[i])
            b[i] = a[i]
            f += a[i]
        else:
            f += b[i]

    x = 0
    if sum(b) > sum(a):
        x = sum(b) - sum(a)

    b[-1] = sum(b) - f - x

    return b

Upvotes: 1

Related Questions