There are buckets
buckets of liquid, where exactly one of the buckets is poisonous. You have minutesToTest
minutes to determine which bucket is poisonous by feeding some number of pigs the liquid. A pig dies after minutesToDie
minutes of drinking the poisonous liquid. A pig can be fed from any number of buckets, and each bucket can be fed from by any number of pigs. You can feed multiple pigs at the same time, it takes no time to feed a pig. Return the minimum number of pigs needed to figure out which bucket is poisonous within the allotted time.
For example:
Input: buckets = 4, minutesToDie = 15, minutesToTest = 15
Output: 2
Explanation:
At time 0, feed the first pig buckets 1 and 2, and feed the second pig buckets 2 and 3.
At time 15, there are 4 possible outcomes:
Input: buckets = 4, minutesToDie = 15, minutesToTest = 30
Output: 2
Explanation:
At time 0, feed the first pig bucket 1, and feed the second pig bucket 2.
At time 15, there are 2 possible outcomes:
Let's analyze the "Poor Pigs" problem. This problem can initially seem tricky, but it boils down to a base conversion concept. Here's a breakdown:
A brute-force approach would involve trying out different numbers of pigs and simulating the feeding process to see if we can uniquely identify the poisonous bucket within the given time. This is highly inefficient and impractical for larger inputs.
The key insight is that each pig can be thought of as providing information in a certain "base". Specifically, consider the number of rounds we can perform tests. The number of rounds can be calculated as rounds = minutesToTest / minutesToDie
. If a pig dies at a certain round, this gives us a unique piece of information.
rounds + 1
outcomes (survive all rounds, die in round 1, die in round 2, etc.).(rounds + 1) ^ numPigs >= buckets
.Therefore, we need to find the smallest integer numPigs
such that (minutesToTest / minutesToDie + 1) ^ numPigs >= buckets
.
This can be solved by taking the logarithm base (minutesToTest / minutesToDie + 1)
of both sides of the equation and rounding up to the nearest integer.
import math
def poorPigs(buckets: int, minutesToDie: int, minutesToTest: int) -> int:
rounds = minutesToTest // minutesToDie
if buckets == 1:
return 0
return math.ceil(math.log(buckets, rounds + 1))
Let's take buckets = 1000
, minutesToDie = 15
, and minutesToTest = 60
.
rounds = 60 // 15 = 4
numPigs
such that (4 + 1) ^ numPigs >= 1000
i.e. 5 ^ numPigs >= 1000
5^4 = 625 < 1000
and 5^5 = 3125 >= 1000
. Thus, numPigs = 5
log
which are constant time.buckets = 1
: In this case, no pigs are needed since there is only one bucket and it must be the poisonous one. Return 0.minutesToDie > minutesToTest
: In this case, it's impossible to determine the poisonous bucket. The problem statement doesn't define behavior here, but in a real interview, you'd clarify the expected behavior. Since problem constraints don't include this, we don't need to handle this case. However, in practice, we may need to add a check if minutesToDie > minutesToTest: return -1
or throw an exception.The solution computes the minimum number of pigs by calculating the number of rounds possible (minutesToTest // minutesToDie
), adding 1 to the rounds (to account for the pig surviving), and then determining the base-rounds + 1
logarithm of the number of buckets. The ceiling of this logarithm is the minimum number of pigs needed.