Intermission

Movie theaters are difficult to manage. Lots of people need to move through limited space, all towards optimal view points, many many times a day! Striking a balance between customer convenience and sufficient revenue is most tricky. For example, right now I'm adding a new chamber to my complex, but I'm not sure how big to make it. The thing about dense seating is that, on the one hand, it generates the most revenue possible from the space I have, but on the other hand, it gets more and more inconvenient for the customers the larger it gets.

Rows in my theater are made of some number of seats, densely packed from the aisle to the wall, thus having only one exit. As such, when someone needs to get up and out, everyone between that person and the aisle is also forced to get up and out - this can get very frustrating for customers in long rows! So, I've done some analysis, and here's what I've come up with:

  • At intermissions, each person in the theater has a 1% chance of needing to get up for something, independent of all other factors. We call these 'the givens'.
  • At the start of the intermission, all of the givens get up, and anyone between a given and the aisle must also get up by proxy. We call these customers 'the forced', and one should note that a single customer may be both a given and a forced.
  • Customer satisfaction remains good so long as no more than 10% of customers have to get up at these intermissions. This includes both the givens, and the forced. (We include the givens as they may be getting up due to discomfort, or some other reason that is also the theater's fault!)
  • Thus, I want to ensure that, for any given intermission, the probability that more than 10% of customers in the theater have to get up is at most 50%.

I can fit 25 rows in my new theater. I want to make the rows as long as possible. How many seats long can I make all these rows, and still meet the customer satisfaction requirements I just outlined? All the rows must be the same size, of course.

Assume the theater is always full, don't worry about empty seats.

You should round down when computing 10% of customers. For a theater with 5 seats per row, 10% of customers = 12, not 13.


Image Credit: http://musichalloficial.blogspot.com/2014/08/cine-blog.html


The answer is 21.

This section requires Javascript.
You are seeing this because something didn't load right. We suggest you, (a) try refreshing the page, (b) enabling javascript if it is disabled on your browser and, finally, (c) loading the non-javascript version of this page . We're sorry about the hassle.

3 solutions

Brock Brown
Jul 3, 2015

Python 3.3:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from random import random
from time import time
rows = 25
def ten_got_up(seats):
    got_up = 0
    customers = seats * rows
    for row in range(rows):
        for seat in range(seats, 0, -1):
            if random() < 0.01:
                got_up += seat
                break
    return got_up/customers > 0.1
def satisfied(seats):
    goals = 0
    trials = 0
    end = time() + 1
    while time() < end:
        if not ten_got_up(seats):
            goals += 1
        trials += 1
    return goals/trials >= 0.5
seats = 1
# simulate smallest seat cases and add more seats
# until customers are unsatisfied
while satisfied(seats):
    seats += 1
seats -= 1
print("Answer:", seats)

Daniel Ploch
Aug 3, 2014

This problem has no closed form solution that I have yet discovered - if someone else finds one, please do post!


There is no shortcut to the answer here. One might be tempted to reduce the problem to a single row and find the answer there, but it turns out this doesn't work, since the distribution of how many people get up in a single row is not uniform. For instance, if we change the problem to be for 15 15 rows, the answer becomes 22 22 instead of 21 21 , and if we go up to 50 50 rows, the answer shrinks down to 20 20 !

We need to figure out, for a given number of seats per row, the probability that more than 10% of customers will be required to stand up, given the parameters of the problem. Then, we need to find the maximum parameter for this function that yields a probability < 50%. The problem statement implies that this function is monotonically increasing, which makes our job easier, and we'll see this as we ferret out our solution. (Though, unfortunately, I don't have a proof for this... proofs welcome!)


We'll use dynamic programming to compute the probability for arbitrary c c , the number of columns of seats, or seats per row, in the theatre. First, we observe that the number of people that get up in any one row is independent of all the other rows. Let p p , the probability that an arbitrary individual is a 'given', be 1 100 \frac{1}{100} , and let P ( x ) P(x) be the probability that, in an arbitrary row, exactly x x people need to get up (that is, they are 'givens', or 'forced'). Thus:

P ( 0 ) = ( 1 p ) c P(0) = (1-p)^c

P ( 1 ) = ( 1 p ) c 1 p P(1) = (1-p)^{c-1} * p

P ( 2 ) = ( 1 p ) c 2 p P(2) = (1-p)^{c-2} * p

. . . ...

P ( c 2 ) = ( 1 p ) 2 p P(c-2) = (1-p)^2 * p

P ( c 1 ) = ( 1 p ) 1 p P(c-1) = (1-p)^1 * p

P ( c ) = ( 1 p ) 0 p P(c) = (1-p)^0 * p

P ( c ) P(c) is thus trivially computable. Now, let's recurse: Define f ( r , c , m ) f(r,c,m) to be the probability that, in a theater of r r rows and c c columns, at most m m customers are forced to stand at intermission. The following python-sketch-code computes f:

def f(r,c,m):
  if r == 0:
    # No rows left, nothing to compute
    return 1
  sum = 0
  for n in [0, min(c,m)]:
    # For each possible number (n) of people that
    # got up in this row, take the probability of
    # such an event, and multiply it by the
    # probability that (m-n) people get up in
    # subsequent rows.  This covers all possible
    # eventualities without double-counting.
    sum += P(n) * f(r-1, c, m-n)
  return sum

By using ( r , c , m ) (r, c, m) as a unique key, we can cache the results of f ( r , c , m ) f(r,c,m) to turn this into a dynamic programming solution, which does O ( C ) O(C) computations for each of O ( m R ) O(mR) dynamic states, where R R is the number of rows, 25 25 in this case. For a given fixed c c , and uninitialized cache, this yields O ( c m R ) O(c * m * R) computations, which is on the order of thousands, or tens of thousands, for c c at 10 10 or 20 20 . Less efficient solutions will likely spawn far less tractible numbers.

The probability that more than 10% of customers will have to get up in a theater with c c seats per row is thus 1 f ( 25 , c , 25 c 10 ) 1 - f(25, c, \left\lfloor \frac{25c}{10} \right\rfloor) . It suffices to compute this function from c = 1 c = 1 upwards, until we observe the probability cross the 50% threshold.

1 f ( 25 , 21 , 25 21 10 ) = 0.4924951 1- f(25, 21, \left\lfloor \frac{25*21}{10} \right\rfloor) = 0.4924951

1 f ( 25 , 22 , 25 22 10 ) = 0.5200529 1 - f(25, 22, \left\lfloor \frac{25*22}{10} \right\rfloor) = 0.5200529

So, we answer 21 .

It seems somewhat unlikely that there is a closed form solution.

This is an interesting question, though I have some concerns about your approach:
1. The 10% rule should only apply to people who do not need to leave their seats. E.g. if everyone in a row wants to get up for something, then no one is inconvenience. Though, I think you are trying to avoid this through the first condition. Is that so?

  1. Note that your probabilities do not sum to 1. Are you missing a ( c k ) { c \choose k } term?

  2. Even accounting for ( c k ) { c \choose k } , P ( 1 ) P(1) should refer to the scenario where only the person in the 2nd left most seat needs to go, or the person in the 2nd right most seat needs to go.

  3. Are you modeling for "people will stand up in the most optimal manner, so as to inconvenience the fewest people". E.g. In a row of 10 seats, if person 4 needs to get up, usually persons 1, 2, 3 will get up. However, if person 4 and 6 need to get up, and persons 7, 8, 9, 10 have already gotten up, then it is "more convenient" for just person 5 to get up. Of course, in this scenario, the "most convenient" is for persons 1, 2, 3, 5 to get up.

Calvin Lin Staff - 6 years, 10 months ago

Log in to reply

Update: Reworded problem to make all this more explicit. Let me know if you encounter any other issues!


I'll see if I can reword the problem to address your concerns. It should be noted that this is a misunderstanding, though, and not mathematical error.

  1. Yes, I am intentionally avoiding this dual classification, as it yields a combinatorial explosion which is much more difficult to calculate than I intend. (I started out with this variation, but it's extremely difficult and tedious to work out, so I went with this simplified route, where the 1% people are counted as part of the 10% people).
  2. This misunderstanding stems from (1), I believe. k = 0 c P ( k ) \sum_{k=0}^{c} P(k) does in fact equal 1, and this is complete, since P ( k ) P(k) represents the probability that k k people need to get up, regardless of whether they are doing so by choice or not.
  3. Something's missing here
  4. This is covered in the beginning of the problem - the rows are set "between the aisle and the wall", so there is only one exit, not two. Thus, once the people who need to get up are decided, there is only ever one way to let them all out.

If I can get a better grasp on these nuances, I'll perhaps post a v2 of this problem that includes all the difficult parts this one glosses over. At the moment, I simply haven't solved the harder version, which I need to do first before I can post such a challenge!


UPDATE: I did! The v2 problem is here

Daniel Ploch - 6 years, 10 months ago

"It seems somewhat unlikely that there is a closed form solution."

Just curious, do you know of any proven cases in which there is no closed form solution, and you have to do an exhaustive search or random sampling?

Brock Brown - 5 years, 11 months ago

Log in to reply

Finding the roots of a quintic has no closed form solution. The proof is by abstract algebra. Exhaustive search / random sampling would likely be unable to prove if a closed form solution does not exist.

Having said that, there is a huge distinction between "finding a specific solution in this particular scenario" and "finding a closed form solution for all cases". For example, the quntic x 5 1 = 0 x^5 -1 = 0 has specific solutions that we know of.

Calvin Lin Staff - 5 years, 11 months ago
Laurent Shorts
Apr 25, 2016

A really slow python program:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
PEOPLE_PER_ROW = 22
NB_ROWS = 25

TOTAL_SEATS = NB_ROWS * PEOPLE_PER_ROW

MAX_STANDING = int(0.1 * TOTAL_SEATS)

def fact(n):
        if n < 2:
                return 1
        return reduce(lambda x,y:x*y, xrange(1,n+1))

FNB = fact(NB_ROWS)

def tabToDict(t):
        d = {}
        last = None
        for v in t:
                if v == last:
                        d[v] += 1
                else:
                        d[v] = 1 
                        last = v 
        return d

def getParts(total):
        parts = [p for p in getParts_0(total, PEOPLE_PER_ROW) if len(p) <= NB_ROWS]
        return map(tabToDict, parts)

def getParts_0(total, maxNb):
        if total == 0:
                return [ [] ]
        if total == 1:
                return [ [1] ]
        parts = []
        for first in xrange(1, min(maxNb, total) + 1): 
                for subparts in getParts_0(total - first, first):
                        parts += [ [first] + subparts ]

        return parts


percent = 0 

# p people who have to stay,
for p in xrange(0, MAX_STANDING + 1): 
        for parts in getParts(p):
                nbParts = sum(parts.values())
                percent += FNB / fact(NB_ROWS - nbParts) / reduce(lambda x,y:x*y, map(fact, parts.values()), 1) * 0.01**nbParts * 0.99**(TOTAL_SEATS - p)

print PEOPLE_PER_ROW, ":", percent

0 pending reports

×

Problem Loading...

Note Loading...

Set Loading...