One way -- which may seem over-powered for this problem, but it's a handy tool to learn -- is to use itertools.groupby. Its job is to group consecutive terms of a sequence together, which is exactly what you want to do here. For example, if we had a list made of up 1
and 2
:
>>> from itertools import groupby
>>> groupby([1,2,2,1,2,2,2,1,1,2])
<itertools.groupby object at 0x8ee793c>
>>> [(key, list(group)) for key, group in groupby([1,2,2,1,2,2,2,1,1,2])]
[(1, [1]), (2, [2, 2]), (1, [1]), (2, [2, 2, 2]), (1, [1, 1]), (2, [2])]
We can make a list of key-value pairs where the groups are the value. (Really they're an iterable grouper object, so we have to take the list
to materialize them to see them.)
So in your case:
>>> groupby(seats["A"])
<itertools.groupby object at 0x8ee7e64>
>>> [(k, list(g)) for k,g in groupby(seats["A"])]
[('available', ['available']), ('unavailable', ['unavailable']), ('available', ['available', 'available', 'available'])]
>>> [len(list(g)) for k,g in groupby(seats["A"]) if k == 'available']
[1, 3]
>>> max(len(list(g)) for k,g in groupby(seats["A"]) if k == 'available')
3
With a little more work we could get the locations too, if those were significant. We can use enumerate
to give the seats numbers:
>>> list(enumerate(seats["A"]))
[(0, 'available'), (1, 'unavailable'), (2, 'available'), (3, 'available'), (4, 'available')]
And then group these instead, using the key
parameter to groupby to tell it we want to group on the second term (index #1), the available/unavailable state, not the number:
>>> grouped = groupby(enumerate(seats["A"]), key=lambda x: x[1])
and then extract the contiguous available seats:
>>> avail = [list(g) for k,g in grouped if k == 'available']
>>> avail
[[(0, 'available')], [(2, 'available'), (3, 'available'), (4, 'available')]]
From this we can do all sorts of things.
>>> min(avail, key=len) # one of the smallest groups
[(0, 'available')]
>>> max(avail, key=len) # one of the largest groups
[(2, 'available'), (3, 'available'), (4, 'available')]
>>> max(avail, key=len)[0][0] # start of largest
2
>>> next(g for g in avail if len(g) >= 2)
[(2, 'available'), (3, 'available'), (4, 'available')]