1

I recently wrote a program about the crazy guy waiting airplane question, which says:

A line of 100 airline passengers is waiting to board a plane. They each hold a ticket to one of the 100 seats on that flight. (For convenience, let's say that the nth passenger in line has a ticket for the seat number n.) Unfortunately, the first person in line is crazy, and will ignore the seat number on their ticket, picking a random seat to occupy. All of the other passengers are quite normal, and will go to their proper seat unless it is already occupied. If it is occupied, they will then find a free seat to sit in, at random. What is the probability that the last (100th) person to board the plane will sit in their proper seat (#100)?

I did monte carlo to get the answer, but not very efficient, since for the passengers, whose seat is sited. I first get a random number, and then checked from the first seat, if it is sited, then skip that one.

By the way the answer should be 1/2 :)

anybody has a better idea to do this one?

#include <iostream>
#include <vector>
#include <random>

using namespace std;

mt19937 generator;
uniform_real_distribution<double> ranuni(0, 1);

bool test(){
    vector<int> line(100, 0);

    int remaining(100);
    int temp = remaining * ranuni(generator);
    if (temp == 99)
    return 0;
    line[temp] = 1;
    --remaining; 

    for (int i = 1; i < 99; ++i){
        temp = remaining * ranuni(generator);

        auto itr = line.begin();
        while (temp != 0){
            ++itr;
            if (*itr == 0)
                --temp;
        }
        if (itr == line.end()-1)
            return 0;
        else
            *itr = 1;
        --remaining;
    }

    return 1;
}

int main(){
cout << "please input number of simulations" << endl;
int num;
cin >> num;

int sum(0);
for (int i = 0; i < num; ++i)
    sum += test();

cout << double(sum) / double(num) << endl;

return 0;
}
  • 1
    Fyi, unless i'm severely forgetful in my stats, the answer to the riddle is is 1/100. The only way it happens is if the crazy guy actually sat in his originally assigned seat. (been a long time, so be gentle if i missed something in the question). – WhozCraig Mar 09 '14 at 22:19
  • @WhozCraig some other passenger might pick the seat of the crazy guy, and then all remaining passengers get their assigned seat. – Marc Glisse Mar 09 '14 at 22:58
  • @MarcGlisse Only if that other passenger was the second on board. Otherwise other random seats have been occupied. – user207421 Mar 09 '14 at 23:00
  • @EJP They have been handled already. At most one unseated passenger has its seat occupied at the same time. That's true after the crazy guy. And when this passenger's turn comes, either he picks the crazy guy's seat and all remaining passengers are ok, or the seat he sits on belongs to another passenger, which becomes the new unique standing no-seat passenger. In other words, the seat permutation has a single cycle. – Marc Glisse Mar 09 '14 at 23:08
  • You don't need Monte Carlo for this, which can never prove the answer here. You just need to count the possibilities. – David Heffernan Mar 09 '14 at 23:22
  • @WhozCraig The answer is `1/2`, indeed. Still thinking of the general solution, but if you quickly check cases with `N` passengers in line equal to 2, 3 and 4, you'll see the probability does not depend on `N` and is equal `1/2` (as in obvious case with just 2 passengers in line). – lapk Mar 09 '14 at 23:48
  • @PetrBudnik that makes sense. Accumulating all those probabilities and their inverses would certainly seem to gravitate to that result. as I said, my stats are just terrible these days (not had to do it "officially" since academia, and I'm not going to talk about just how long ago *that* was). – WhozCraig Mar 09 '14 at 23:51

1 Answers1

0

I'll offer a couple of thoughts. Probably not a definitive answer, though.

First, I wondered: if you pre-computed a "shuffled" list of plane seats to use, would that help things? The idea being: when a passenger attempts to sit in his/her seat and finds it occupied, you simply pop values off the list until you find one that is unoccupied instead of calling random(). You can pop them off because you don't want later passengers to waste time considering those (occupied) seats either. This means you DO avoid the problem near the end of the line where a random number generator keeps generating occupied seats. (Although, not yours I see, since you deterministically find an unoccupied seat when the assigned seat is occupied). Given such a shuffled list of seat assignments, it is very quick and easy to evaluate the original problem.

The real problem is that generating this "shuffled" list is exactly the same problem as the original one (for ticket# in 0..99, put ticket# in slot(random). Is it occupied? etc.) So, given that generating a nicely shuffled list of seat assignments has the same complexity as the original problem, is there a way we can simplify doing this lots and lots of times?

That brings me to my second thought: once you have one such shuffled list, there are lots of ways of creating other ones, much easier than 100 additional calls to random(). For example, just swap two of the values. The resulting list represents a different run of the problem with slightly different selections by passengers. Do this lots of times and you get many different runs.

The part I can't quite answer, though, is how to ensure the samples you get have a good sampling of the problem space (which is necessary for monte carlo to give you good results). I'll have to leave that for someone else.

user3033893
  • 900
  • 11
  • 11
  • Shuffling a vector is O(N), you can use std::shuffle, see http://stackoverflow.com/questions/6926433/how-to-shuffle-a-stdvector-in-c and also http://en.wikipedia.org/wiki/Knuth_shuffle – amdn Mar 10 '14 at 00:55