0

I am having trouble writing python code to print how many available seats there are in a row. I have a simple set of nested dictionaries - what I need to add is a test to see how many consecutive keys == available. the output needs to be something like, 'there is a block of 4 seats available together'.

seats = {'A': ['available', 'unavailable','available','available','available'],
         'B': ['unavailable', 'unavailable','available','available','available'],
         'C': ['available', 'unavailable','unavailable','available','available'],
         'D': ['available', 'unavailable','available','unavailable','unavailable']}

Is there a very simple method of counting how many items in a row have the same value? I am literally brand new to programming, so I really need explanation of how code is working as well.

4

2 回答 2

2

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')]
于 2013-04-17T14:37:40.263 回答
1

Here's a quick and dirty code block that should help get you started:

if rowChoice not in seats:  
    # Tell the user they entered a bad row and keep prompting them for input until it works

max_available = 0
available = 0  
for chair in seats[rowChoice]:  
    # When a seat is taken, update the maxium number of available seats and reset our counter  
    if chair != "available":  
        if available > max_available:  
            max_available = available  
        available = 0

    else:
        available += 1  

print "There is a maximum block of %d seats available" % (max_available)
于 2013-04-17T14:03:56.160 回答