user2212774
user2212774

Reputation: 215

Finding consecutive values in a multidimensional array - python

I'm completely new to python really. I need some help with multidimensional arrays. I am making a seat booking system for a theatre. (just practice). I have set up a 5 row by 10 seat matrix. And all I really need to be able to do is assign 'available' or 'unavailable' to each seat. I can do this obviously, but what I have no idea how to do is be able to search or loop through a row to see if there are 6 seats available next to each other. Any help would be great. Bear in mind I am completely new to python.

Upvotes: 4

Views: 3319

Answers (3)

Adam
Adam

Reputation: 15805

The simplest way I can think of is to iterate over the rows, keeping track of the row number as index.

Then, we count available seats until we find six in a row or until we encounter an unavailable seat (we reset the count if this happens).

seats = [[True, True, True, False, True, True, True, False, False, True],
         [True, True, True, True, True, True, True, False, False, True],
         [True, True, True, False, True, True, True, False, False, True],
         [True, True, True, False, True, True, True, False, False, True],
         [True, True, True, True, True, True, True, False, False, True]]

for index, row in enumerate(seats):
    consecutive_seats = 0
    for seat in row:
        if seat:
            consecutive_seats += 1
            if consecutive_seats >= 6:
                print('There are at least six seats available on row', index)
                break
        else:
            consecutive_seats = 0

Further explanation

  1. The python enumerate function allows you to iterate over the sequence of seats, giving you back an index and the current item at that index. Optionally, you can pass it a parameter to set the starting index (so if you want your seat rows to start from one, you could use the following instead:

    for index, row in enumerate(seats, start=1): ...
    

    In fact, the details of what's happening here are interesting: enumerate returns a two-item Tuple (think of it as an immutable – unchangeable – list) which you are unpacking to index and row. You can then use these two variables just like any others.

  2. For each pair of index and row, you iterate over the row and check if seat is True (you can, but shouldn't, write seat == True – it's redundant information). If it is True, you consider it available and increase the counter for available consecutive seats by one.

  3. Immediately thereafter, you need to check if you've found enough free seats, in which case you can break out of the loop, in other words, you're skipping the rest of the seats in the row because you already know enough of them are free, and continuing with the next iteration of the outer loop, which will yield the next row index and row.

  4. If, on the other hand, the seat is False (unavailable), you reset the count of consecutive available seats to zero but you continue checking the rest of the row.

Suggested improvements

  • Make a class Seat and give it an attribute is_available
  • Introduce constants to get rid of magic numbers

Upvotes: 3

Abhijit
Abhijit

Reputation: 63707

Assuming you have a seat arrangement similar to below

seats=[   [1, 0, 0, 0, 1, 1, 1, 0, 1, 0],
    [0, 0, 0, 1, 1, 0, 1, 1, 1, 0],
    [0, 0, 1, 1, 1, 0, 1, 0, 0, 1],
    [0, 0, 1, 0, 0, 0, 0, 0, 1, 1],
    [0, 0, 0, 0, 0, 0, 0, 1, 0, 0]]

Instead of maintaining as a nested list, my suggestion is to maintain a list of strings. Searching a pattern (here sequence of '0's or '1's or even something complex like middle seat or end seat) is faster and easier through string search. Even for complex searches you can employ regex

Suggested Data Structure

seats=[   '1000111010',
    '0001101110',
    '0011101001',
    '0010000011',
    '0000000100']

Now to search for consecutive 6 empty seats , you have to search '0'*6 something like

>>> any('0'*6 in row for row in seats)
True
>>> next((i,row.index('0'*6)) for i,row in enumerate(seats) if '0'*6 in row )
(4, 0)

Explanation

next((i,row.index('0'*6)) for i,row in enumerate(seats) if '0'*6 in row ) returns the first item from the generator expression. Assuming you know about the built-in

enumerate: Returns a list of tuples of (index , element)

The expression can be equivalently written as

for i,row in enumerate(seats):
    if '0'*6 in row
       print (i,row.index('0'*6)
       break

any('0'*6 in row for row in seats) can be equivalently written as

def search(seats):
    for row in seats:
        if '0'*6 in row:
            return True
    return False

Upvotes: 2

0x90
0x90

Reputation: 40982

you may consider to use sparse matrix.

and Iterate it like that: https://stackoverflow.com/a/4319159/1031417

Upvotes: 0

Related Questions