151

Imagine you're in a tall building with a cat. The cat can survive a fall out of a low story window, but will die if thrown from a high floor. How can you figure out the longest drop that the cat can survive, using the least number of attempts?

Obviously, if you only have one cat, then you can only search linearly. First throw the cat from the first floor. If it survives, throw it from the second. Eventually, after being thrown from floor f, the cat will die. You then know that floor f-1 was the maximal safe floor.

But what if you have more than one cat? You can now try some sort of logarithmic search. Let's say that the build has 100 floors and you have two identical cats. If you throw the first cat out of the 50th floor and it dies, then you only have to search 50 floors linearly. You can do even better if you choose a lower floor for your first attempt. Let's say that you choose to tackle the problem 20 floors at a time and that the first fatal floor is #50. In that case, your first cat will survive flights from floors 20 and 40 before dying from floor 60. You just have to check floors 41 through 49 individually. That's a total of 12 attempts, which is much better than the 50 you would need had you attempted to use binary elimination.

In general, what's the best strategy and it's worst-case complexity for an n-storied building with 2 cats? What about for n floors and m cats?

Assume that all cats are equivalent: they will all survive or die from a fall from a given window. Also, every attempt is independent: if a cat survives a fall, it is completely unharmed.

This isn't homework, although I may have solved it for school assignment once. It's just a whimsical problem that popped into my head today and I don't remember the solution. Bonus points if anyone knows the name of this problem or of the solution algorithm.

Colonel Panic
  • 132,665
  • 89
  • 401
  • 465
AndrewF
  • 6,852
  • 7
  • 29
  • 27
  • 125
    I object to the use of cats in the described manner. Can we change it to dogs? – Thilo Oct 20 '10 at 01:19
  • 53
    It's not that simple. Studies have been done (of cats accidentally falling out of skyscrapers, not being thrown). There was a certain range where they died, and a range *** higher than this *** where they survived. Something about how they tensed up their bodies. – Andrew Shepherd Oct 20 '10 at 01:21
  • 6
    I've read somewhere that 15ft or above, cats have a greater chance of surviving. This question would be better suited if we were dropping ex-girlfriends and/or nagging wives. – Anthony Forloney Oct 20 '10 at 01:23
  • 3
    @wlashell Did you read to the end where he said it is not homework? He might be lying to us but we'll see. – Robert Massaioli Oct 20 '10 at 01:23
  • 4
    If you only have one cat, and throw it from successive floors, it will also sustain non-fatal injuries from previous 'throwing out the window' events. When the cat is eventually thrown from out the window that proves fatal, we cannot determine that it was the fall or the collective injuries that killed the beast. Therefore, the cat must be allowed to fully recuperate between floors, before being chucked out the window again. – ocodo Oct 20 '10 at 01:27
  • 2
    Is there a better solution than binary search? Start from the middle, if the the cat dies discard the upper half, if the cat lives discard the lower half, recurse. – Sam Dufel Oct 20 '10 at 01:28
  • 2
    @Sam: The problem is that you have only a limited number of tries on the higher ranges. – Thilo Oct 20 '10 at 01:31
  • Oh, are we trying to preserve cats' lives? I thought we were just going for minimal attempts. For minimal casualties, you can just do a linear search starting from the bottom. – Sam Dufel Oct 20 '10 at 01:48
  • 2
    We are not going for minimal casualties, we are going for minimal attempts. But we have a hard constraint about the maximum number of casualties. – Thilo Oct 20 '10 at 01:53
  • @Sharpie: Of *course* it isn't about Microsoft, it's about glass windows... – Hello71 Oct 20 '10 at 01:57
  • 35
    You know, if you start with two cats, you COULD just wait a few months and then run a binary search. Or wait a few months after that and do a "simultaneous search," wherein you get helpers to throw cats from every floor simultaneously-- the count of surviving cats in that case is the highest floor number you can throw 'em from, of course. – mjfgates Oct 20 '10 at 02:04
  • 10
    With bunnies, change "months" to "weeks." – mjfgates Oct 20 '10 at 02:04
  • 3
    @mjfgates: unless you start with two male cats. then you are in trouble, especially after a few months. – Thilo Oct 20 '10 at 06:31
  • 3
    +1 for any question that involves the qualification "assume that all cats are equivalent". – Nick Johnson Oct 20 '10 at 07:52
  • 5
    @mjfgates: I disagree, if the cats are a breeding pair, then you will find yourself using a fibonacci search – High Performance Mark Oct 20 '10 at 08:32
  • 4
    This is a very good intellectual puzzle of the type appreciated by programmers, but I don't see how it is itself related to programming or software development. –  Oct 20 '10 at 09:15
  • 2
    I'm sure this is a dupe. But the original question used something else breakable other than cats. – Martin Smith Oct 20 '10 at 09:20
  • Aw, no more `windows` or `fatal` tags. :-( – Steve Tjoa Oct 20 '10 at 10:35
  • 1
    Can I throw out both cats simultaneously? That way the first cat could cushion the second cat's fall, therefore saving it. – Adamski Oct 20 '10 at 14:45
  • @mjfgates Kittens and cats will fall differently. My FIL's kitten went skydiving from the 27th floor. It was limping a bit afterwards. Thus you'll have to wait several months to run your binary search. – Loren Pechtel Oct 20 '10 at 15:29
  • 2
    I wish people would use this site to discuss programming. I'm sick of these posts that are seen as jokes getting so much attention and useless answers. I knw, I know, I don't have to click... – Mark Snidovich Oct 21 '10 at 18:43
  • 1
    @Mark: Whimsical it may be, but it's not a joke...It's a valid logical puzzle requiring a lot of complex algorithmic calculations in order to solve it. Sounds right up the alley of a community of devs – EvanK Oct 25 '10 at 16:33
  • I had this as an interview question with billiard balls – Adam Nov 03 '10 at 00:16
  • 1
    Cats have 9 lives. You could just throw it from the lowest window and increment the height until it dies. – Nobody Nov 05 '10 at 14:36
  • 2
    Note that this is identical to Google Code Jam's "Egg Drop problem". The O(n^3) solution below is not good enough, because the large problem set uses N = 2000000000. http://code.google.com/codejam/contest/dashboard?c=32003#s=p2 – ripper234 Jan 15 '11 at 08:28
  • 2
    Don't cats have a non-fatal terminal velocity? – Adam C Sep 05 '11 at 15:40
  • 3
    http://en.wikipedia.org/wiki/Buttered_cat_paradox – Petteri H Oct 04 '11 at 13:09
  • 4
    I'd use Schrödinger's cat for this. – Gordon Mar 19 '13 at 13:30
  • @Adamski for that you dont require a cat, just some cushioning stuff would do. that makes it not related to the current question. – nawfal May 30 '13 at 17:02
  • 2
    Question belongs on Programming Puzzles & Code Golf stack exchange site (http://codegolf.stackexchange.com/) – Doctor Jones Aug 22 '13 at 14:53
  • Thats a puzzle which is there on the internet as the one asked in google interview (don't know the veracity of that) but here is the solution [http://interviewpuzzle.blogspot.com/2010/03/google-interview-puzzle-2-egg-problem.html](http://interviewpuzzle.blogspot.com/2010/03/google-interview-puzzle-2-egg-problem.html) – Gaurav Saxena Oct 20 '10 at 01:23
  • 1
    I believe this is best solved with the well-known Defenestration Pattern, most concisely written in the [LOLCODE programming language](http://lolcode.com). – Larry Lustig Oct 20 '10 at 01:57
  • @DoctorJones (and the two people who upvoted that comment), no, it doesn't. PPCG is for *hosting* contests, not discussing them. – Peter Taylor Jul 24 '14 at 21:56
  • @PeterTaylor the OP is clearly asking for an answer, not a discussion. It's a puzzle, not a practical programming or coding problem, therefore I stand by my comment. – Doctor Jones Jul 25 '14 at 09:24
  • @DoctorJones, to the extent that your assertion is that the question is off topic on this stack, I don't argue. But SO users who know of the existence of PPCG but don't participate there often have very misguided ideas of what's on topic there, and your comment is right in that line. The OP is clearly not aiming to host a programming contest, so it's off topic for PPCG. It would probably be on topic for the very recent puzzles.stackexchange. – Peter Taylor Jul 30 '14 at 09:04
  • @Gordon : well using Schrödinger's cat is not advisable here, it just makes the problem more complicated ..:) – Chet Aug 30 '16 at 15:32

8 Answers8

93

According to a recent episode of Radiolab (about "Falling"), a cat reaches terminal velocity by the 9th floor. After that, it relaxes and is less likely to be hurt. There are completely uninjured cats after a fall from above the 30th. The riskiest floors are 5th to 9th.

Thilo
  • 257,207
  • 101
  • 511
  • 656
  • 16
    As a cat person, I would like to point out that this study was based on animal hospital reports after defenestration incidents. No additional cats were injured or inconvenienced in this inquiry. – Thilo Oct 20 '10 at 01:28
  • 19
    It's as much of an answer as the question deserves. – Mark Ransom Oct 20 '10 at 02:50
  • 2
    This just shows how it's not a case of live = 1, die = 0 as the outcome, but more of live = 1.0, die = 0.0 and everything in between is probabilities. It's also a curve, not a line, which needs to be discovered. – tadman Oct 20 '10 at 14:28
  • 1
    For cats which fell from above floor 9 there is nothing left to take to the hospital – Meh Oct 20 '10 at 15:11
  • 1
    My cat fell from the tenth floor and lived to tell the tale. Actually the only thing that happened to it was a fractured bone, and it's walking kinda funny since then, about 5 years ago. – Pop Catalin Oct 20 '10 at 15:22
  • 74
    The problem with that report is selection bias - no one takes a dead cat to the vet. – Niki Yoshiuchi Oct 20 '10 at 15:28
  • @Thilo: Defenestration? Who are you, [Dennis Miller](http://www.youtube.com/watch?v=TBeD8LmnSJw)? – BlueRaja - Danny Pflughoeft Oct 20 '10 at 19:05
  • 1
    Probably the only non programming related answer on SO. – nawfal May 30 '13 at 17:07
70

You can easily write a little DP (dynamic programming) for the general case of n floors and m cats.

The main formula, a[n][m] = min(max(a[k - 1][m - 1], a[n - k][m]) + 1) : for each k in 1..n, should be self-explanatory:

  • If first cat is thrown from k-th floor and dies, we now have k - 1 floors to check (all below k) and m - 1 cats (a[k - 1][m - 1]).
  • If cat survives, there're n - k floors left (all floors above k) and still m cats.
  • The worst case of two should be chosen, hence max.
  • + 1 comes from the fact that we've just used one attempt (regardless of whether cat has survived or not).
  • We try every possible floor to find the best result, hence min(f(k)) : for k in 1..n.

It agrees with Google result from Gaurav Saxena's link for (100, 2).

int n = 100; // number of floors
int m = 20; // number of cats
int INFINITY = 1000000;

int[][] a = new int[n + 1][m + 1];
for (int i = 1; i <= n; ++i) {
    // no cats - no game
    a[i][0] = INFINITY;
}

for (int i = 1; i <= n; ++i) {
    for (int j = 1; j <= m; ++j) {
        // i floors, j cats
        a[i][j] = INFINITY;

        for (int k = 1; k <= i; ++k) {
            // try throw first cat from k-th floor
            int result = Math.max(a[k - 1][j - 1], a[i - k][j]) + 1;
            a[i][j] = Math.min(a[i][j], result);
        }
    }
}

System.out.println(a[n][m]);

You can easily find strategy (how to throw first cat), if you save best k in another array.

There's also a faster solution, not involving O(n^3) computations, but I'm a bit sleepy already.

edit
Oh yeah, I remember where I saw this problem before.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
Nikita Rybak
  • 67,365
  • 22
  • 157
  • 181
  • Hmm, doesn't the `+ 1` need to be outside the `min()`? As you say yourself, whether the attempt is successful or not, it's still an attempt. – j_random_hacker Oct 23 '10 at 14:00
  • @j_random_hacker Does it change anything? Moving `+1` outside of `min`. Or moving it inside of `max` :) – Nikita Rybak Oct 23 '10 at 14:06
  • @Nikita: I'm sorry I somehow misread what you had written -- what you have is exactly right according to me! +1. – j_random_hacker Oct 23 '10 at 14:12
  • Note that this is identical to Google Code Jam's "Egg Drop problem". The O(n^3) solution below is not good enough, because the large problem set uses N = 2000000000. http://code.google.com/codejam/contest/dashboard?c=32003#s=p2 – ripper234 Jan 15 '11 at 08:29
  • 1
    See this new question for an O(n) algorithm. The top answer to the Google Code Jam is O(n), but I don't understand it yet. http://stackoverflow.com/questions/4699067/explain-this-on-algorithm-for-the-cat-egg-throwing-problem – ripper234 Jan 15 '11 at 10:27
  • I fail to understand the strategy that's used in throwing those cats, can anyone explain? And does "worst case" mean that the last floor is the one from which the cat, if thrown, dies? – Pavel Apr 30 '15 at 15:27
10

Imagine you're in a tall building with a cat. The cat can survive a fall out of a low story window, but will die if thrown from a high floor. How can you figure out the longest drop that the cat can survive, using the least number of attempts?

The best strategy for solving this problem is investigating, using the law of physics, the probability of your assumptions being true in the first place.

If you would have done so, you'd realize that the cat's chances of survival actually increase the higher the distance to ground is. Of course, assuming you throw it from an ever higher building, such as the petronas towers, and not an ever higher mountain, such as the mount everest.

Edit:
Actually, you'd see an unfinished camel distribution.
First, the probability of the cat dying is low (very low altitude), then it gets higher (low altitude), then again lower (higher altitude), and then again higher (very high altitude).

The graph for the probability of cat dying as a function of altitude above ground looks like this:
(finish at 3, because unfinished camel distribution)

alt text

Update:
A cat's terminal velocity is 100 km/h (60mph) [=27.7m/s = 25.4 yards/s].
Human terminal velocity is 210 km/h (130mph).[=75m/s = 68.58 yards/s]

Terminal velocity source:
http://en.wikipedia.org/wiki/Cat_righting_reflex

Credits:
Goooooogle

I need to verify later:
http://en.wikipedia.org/wiki/Terminal_velocity
http://www.grc.nasa.gov/WWW/K-12/airplane/termv.html


Stefan Steiger
  • 78,642
  • 66
  • 377
  • 442
  • 2
    Is this correct? Surely once terminal velocity is reached, chances can't change - and I was under the impression a cat can survive a terminal velocity fall. – ZoFreX Oct 20 '10 at 15:55
  • 4
    @ZoFreX: Sure they can, it's the just below terminal velocity that are the most fatal. On the other hand, drop a cat from, say a hundred thousand miles up, and the cat is more likely to burn up in the atmosphere after dying from the vacuum than fall and live. – David Thornley Oct 20 '10 at 20:33
  • 1
    Are those bunny ears in that graph? – ninjalj Oct 20 '10 at 22:40
  • 1
    @ZoFreX: Angular momentum. A cat always lands on its feet, due to angular momentum because of cat's body design and cat's turning skills. But that still means it needs time to turn. The more time there is (==>the higher the altitude), the more likely the cat will land on its feet (==> chances of survival increase dramatically, as opposed to e.g. landing on the head). But you're right, the probability stays the same after reaching terminal velocity. I'd say it's pretty likely a cat can survive a terminal velocity fall, at least mine jumped out the bathroom window (appx. 20m), without a scratch. – Stefan Steiger Oct 21 '10 at 10:43
8

I first read this problem in Steven Skiena's Algorithm Design Manual (exercise 8.15). It followed a chapter on dynamic programming, but you don't need to know dynamic programming to prove precise bounds on the strategy. First the problem statement, then the solution below.

Eggs break when dropped from great enough height. Given an n-story building, there must be a floor f such that eggs dropped from floor f break, but eggs dropped from floor f-1 survive. (If the egg breaks from any floor, we'll say f = 1. If the egg survives from any floor, we'll say f = n+1).

You seek to find the critical floor f. The only operation you can perform is to drop an egg off some floor and see what happens. You start out with k eggs, and seek to drop eggs as few times as possible. Broken eggs cannot be reused (intact eggs can). Let E(k,n) be the minimum number of egg droppings that will always suffice.

  1. Show that E(1,n) = n.
  2. Show that E(k,n) = Θ(n**(1/k)).
  3. Find a recurrence for E(k,n). What is the running time of the dynamic program to find E(k,n)?

Only 1 egg

Dropping the egg from each floor starting at the first will find the critical floor in (at-worst) n operations.

There is no faster algorithm. At any time in any algorithm, let g the highest floor from which the egg has been seen not to break. The algorithm must test floor g+1 before any higher floor h > g+1, else if the egg were to break from floor h, it could not distinguish between f=g+1 and f=h.

2 eggs

First, let's consider the k=2 eggs case, when n = r**2 is a perfect square. Here's a strategy that takes O(sqrt(n)) time. Start by dropping the first egg in increments of r floors. When the first egg breaks, say at floor ar, we know the critical floor f must be (a-1)r < f <= ar. We then drop the second egg from each floor starting at (a-1)r. When the second egg breaks, we have found the critical floor. We dropped each egg at most r time, so this algorithm takes at-worst 2r operations, which is Θ(sqrt(n)).

When n isn't a perfect square, take r = ceil(sqrt(n)) ∈ Θ(sqrt(n)). The algorithm remains Θ(sqrt(n)).

Proof that any algorithm takes at least sqrt(n) time. Suppose there is a faster algorithm. Consider the sequence of floors from which it drops the first egg (so long as it doesn't break). Since it drops fewer than sqrt(n), there must be an interval of at least n/sqrt(n) which is sqrt(n). When f is in this interval, the algorithm will have to investigate it with the second egg, and that must be done floor-by-floor recalling the 1-egg case. CONTRADICTION.

k eggs

The algorithm presented for 2 eggs can be easily extended to k eggs. Drop each egg with constant intervals, which should be taken as the powers of the kth root of n. For example, for n=1000 and k=3, search intervals of 100 floors with the first egg, 10 with the second egg, and 1 with the last egg.

Similarly, we can prove that no algorithm is faster Θ(n**(1/k)) by inducting from the k=2 proof.

Exact solution

We deduce the recurrence by optimising where to drop the first egg (floor g), presuming we know optimal solutions for smaller parameters. If the egg breaks, we have the g-1 floors below to explore with k-1 eggs. If the egg survives, we have n-g floors above to explore with k eggs. The devil chooses the worst for us. Thus for k>1 the recurrence

E(k,n) = min(max(E(k,n-g), E(k-1,g))) minimised over g in 1..n
Community
  • 1
  • 1
Colonel Panic
  • 132,665
  • 89
  • 401
  • 465
  • If I have k eggs, why isn't the runtime `O(k*n**(1/k))` for the worst case? Since in the worst case I have to go through `n**(1/k)` exactly `k` times. – Rakete1111 Dec 02 '18 at 22:13
2

Doesn't this assume you're using "The Same Cat"?

You can approach it mathematically, but that's the nice thing about math... with the right assumptions, 0 can equal 1 (for large values of 0).

From a practical stand-point, you can get 'Similar Cats", but you can't get "The Same Cat".

You could try to determine the answer empirically, but I would think that there would be enough statistical differences that the answer would be statistically meaningless.

You could try to USE "The Same Cat", but that wouldn't work, as, after the first drop, it's no longer the same cat. (Similarly to, onecan never step into the same river twice)

Or, you could aggregate the health of the cat, sampling at extremely close intervals, and find the heights for which the cat is "mostly alive" (opposed to "mostly dead" from "The Princess Bride"). The cats will survive, on average (up to the last interval).

I think I've strayed from the original intent, but if you're going the empirical route, I vote for starting as high as possible and continuing to drop cats as the height decreases until they statistically survive. And then re-test on surviving cats to be sure.

Marc
  • 778
  • 7
  • 18
0
O(m*(n^(1/m))) algorithm.

Let 'x' be the maximum number of attempts needed.  

m = 1 => linear => x=n

m = 2:  
Let the floors be split into 'k' partitions. The first cat is thrown at the end of each partition (max 'k' times). 
When it dies, the second cat is used to go up from the beginning of this partition.   
x = k + n/k.   
Minimize x by diff wrt k and setting = 0, to get k = n^(1/2) and x = 2 * n^(1/2).

m = 3:  
x = k + 2*(y^(1/2)), where y = n/k  
diff wrt x and set = 0, to get k = n^(1/3) and x = 3 * n^(1/3)

for general m:  
x = m * n^(1/m). 
tldr
  • 11,924
  • 15
  • 75
  • 120
0

I took a slightly different method to produce a solution.

I started by working out the maximum floor that could be covered using x cats and y guesses using the following method.

Start with 1 floor and keep increasing the number of guesses while keeping track of floors checked, which guess they were checked on and how many cats were remaining for each floor.
Repeat this up to y times.

This very inefficient code to compute the given answer but nonetheless useful for small number of cats / floors.

Python code:

def next_step(x, guess):
  next_x = []
  for y in x:
    if y[0] == guess:
      if y[1] != 1:
        next_x.append((guess+1, y[1] - 1))
    next_x.append(y)
    if y[0] == guess:
      next_x.append((guess+1, y[1]))
  return next_x

x = [(1, TOTAL_NUM_CATS)]
current_floor = 1
while len(x) <= TOTAL_NUM_FLOORS:
  x = next_step(x, current_floor)
  current_floor += 1
  print len(x)

For 2 cats the maximum floors that can be identified in x guesses is:
1, 3, 6, 10, 15, 21, 28...

For 3 cats:
1, 3, 7, 14, 25, 41, 63...

For 4 cats:
1, 3, 7, 15, 30, 56, 98...

After extensive research (mostly involving typing numbers sequences into OEIS) I noticed that the maximum floors for x follows a combination piecewise pattern.

For 2 cats:
n < 2 : 2^n - 1
n >= 2 : C(n, 1) + C(n, 2)

For 3 cats:
n < 3 : 2^n - 1
n >= 3 : C(n, 1) + C(n, 2) + C(n, 3)

For 4 cats:
n < 4 : 2^n - 1
n >= 4 : C(n, 1) + C(n, 2) + C(n, 3) + C(n, 4)

From here I took the easy approach of simple incrementing n until I pass the required number of floors.

Python code:

def find_smallest(floors, eggs):
  maximum_floors = 0
  n = 0
  while maximum_floors < floors:
    maximum_floors = 0
    n += 1
    if n < eggs:
      maximum_floors = 2**n - 1
    else:
      count = 0
      for x in xrange(1, eggs+1):
        maximum_floors += combination(n, x)
  print n

This gives the correct solution for (100, 2) = 14.
For anyone that wishes to check something less trivial, it gives (1 000 000, 5) = 43.

This runs in O(n) where n is the answer to the problem (the more cats the better).
However I'm sure a somebody with a higher level of mathematics could simplify the piecewise formulas to compute in O(1).

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
threenplusone
  • 2,112
  • 19
  • 28
-1

all this crazy talk about cats..and it's just a guess the number problem with minimum guesses (number of cats). there shouldn't be a need to artificially (and incorrectly) define infinity as part of the solution either. the variable should have been named upper-bound or max-try or some such. the problem definition (the cat thing) has some serious issues though, with people responding to animal cruelty potential and also the many facets of such a problem posed in real life, e.g. air-drag, gravity is acceleration, and other such real life parameters of the problem. so perhaps it should have been asked in a totally different way.

chris
  • 412
  • 6
  • 13
  • FWIW it may be a disguised real life problem. Suppose that you have an automatic test that fails at version 1234 but worked at version 42. The cat is dead at 1234 but live at version 42. What revision killed it? If updating e.g. from 42 to 43 is quick and easy but checking out and rebuilding a new version is hard, this starts to look a lot like the cat problem. – mcdowella Mar 13 '11 at 07:52