Subtract list of boolean

Viewed 137

I have two lists of booleans buy_machine and broken_machine. I want to make a third list working_machines that sums the number of machines bought and subtracts the number of broken machines.

I tried the following code and the resulting list is full of 'nothing' I expected at least to see the 'plus 1' or 'minus 1', this was just to try something, I have no idea how to actually make the working_machines list to sum or subtract the booleans

years = list(range(1, 21))
buy_machine = []
broken_machine = []
working_machines = []
for year in years:
    if year <= 5:
        buy_machine.append(True)
    else:
        buy_machine.append(False)
    if 10 % year == 10 and year <= 15:
        broken_machine.append(True)
    else:
        broken_machine.append(False)
    if buy_machine == True and broken_machine == False:
        working_machines.append('plus 1')
    elif buy_machine == False and broken_machine == True:
        working_machines.append('minus 1')
    else:
        working_machines.append('nothing')
buy_machine
[True,
 True,
 True,
 True,
 True,
 False,
 False,
 False,
 False,
 False,
 False,
 False,
 False,
 False,
 False,
 False,
 False,
 False,
 False,
 False]
broken_machine
[False,
 False,
 False,
 False,
 False,
 False,
 False,
 False,
 False,
 False,
 True,
 True,
 True,
 True,
 True,
 False,
 False,
 False,
 False,
 False]
working_machines
['nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing',
 'nothing']

Wanted output

working_machines
[1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0]
2 Answers

working_machines is just the cumulative sums of the values in the following list:

>>> x = [a - b for a,b in zip(buy_machine, broken_machine)]
>>> x
[1, 1, 1, 1, 1, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0]

(This works because True and False are equal to 1 and 0, respectively, bool being a subclass of int.)

You can get that using itertools.accumulate.

>>> list(accumulate(x))
[1, 2, 3, 4, 5, 5, 5, 5, 5, 5, 4, 3, 2, 1, 0, 0, 0, 0, 0, 0]

That is, working_sums[i] = sum(x[:i]) for each index i.

The reason you get a whole bunch of nothing is that you're asking if the entire list is true, i.e. buy_machine == True. Unfortunately, a list cannot equal a boolean, so this is why you always go to the else statement. Try this instead:

years = list(range(1, 21))
buy_machine = []
broken_machine = []
working_machines = []
for year in years:
    if year <= 5:
        buy_machine.append(True)
    else:
        buy_machine.append(False)
    if 10 % year == 10 and year <= 15:
        broken_machine.append(True)
    else:
        broken_machine.append(False)
    if buy_machine[-1] == True and broken_machine[-1] == False:
        working_machines.append('plus 1')
    elif buy_machine[-1] == False and broken_machine[-1] == True:
        working_machines.append('minus 1')
    else:
        working_machines.append('nothing')
        
print(working_machines)
# Prints ['plus 1', 'plus 1', 'plus 1', 'plus 1', 'plus 1', 'nothing', 'nothing', 'nothing', 'nothing', 'nothing', 'minus 1', 'minus 1', 'minus 1', 'minus 1', 'minus 1', 'nothing', 'nothing', 'nothing', 'nothing', 'nothing']

This uses buy_machine[-1] to get the last element of the list, i.e. the element you just added.

Edit: You can change 'plus 1' to 1 and 'minus 1' to -1, then use the itertools.accumulate function as described in Chepner's answer to get what you want.

Related