Editorial for IOI '10 P2 - Hotter Colder
Submitting an official solution before solving the problem yourself is a bannable offence.
This problem is an interesting variant of the well-known guessing game Higher-Lower, also featured in the demonstration task Guess.
Higher-Lower is efficiently solved by the, also well-known, Binary Search algorithm. Binary Search maintains an interval of still possible numbers (candidates). Initially, this interval includes all numbers in the range. By comparing to the middle candidate, the interval can be halved by a single guess. Thus, the secret number can be determined in a logarithmic (to base ) number of guesses. Or, to put it differently, if the range of allowed numbers is doubled, then the secret number can be determined with one additional guess.
Subtask 1
Doing a Linear Search, that is, successively calling Guess() for from to , yields a solution requiring calls to Guess, in the worst case. This solves Subtask 1.
Analysis
To get a better understanding of the Hotter-Colder problem, it helps to formalize the rules of this game.
Let be Jill's number, and let be the most recent guess, that is, Guess() was called last. In that situation, Guess() will return:
HOTTER if abs(G - J) < abs(P - J)
COLDER if abs(G - J) > abs(P - J)
SAME if abs(G - J) = abs(P - J)
Or in a single formula: sign(abs(P - J) - abs(G - J))
. Letting , this can be rephrased as:
if P <= G then
HOTTER if J > M
COLDER if J < M
SAME if J = M
else
HOTTER if J < M
COLDER if J > M
SAME if J = M
Or in a single formula: sign(G - P) * sign(J - M)
.
Thus, we see that each Guess() effectively provides a high-low comparison to the midpoint . In fact, sign(G - P) * Guess(G) = sign(J - M)
offers a genuine high-low comparison.
Unfortunately, due to the range restriction on , we cannot make the midpoint go wherever we want. So, a straightforward Binary Search is not going to work.
Subtask 2
Ignoring the results of all odd calls to Guess, we can extract one bit of information out of every successive pair of odd-numbered and next even-numbered call to Guess. This yields a solution that calls Guess at most times, where is the largest integer such that . That is, it makes at most calls to Guess. For (almost ), this boils down to making at most calls.
Subtask 3
By exploiting the fact that we actually do a high/low/equal comparison instead of a pure high/low (binary) comparison, we can gain almost one extra bit of information (taken over all guesses).
Explanation: a complete binary tree with leaves has internal nodes. So, the same number of high/low/equal guesses can reach twice the number of nodes minus one (compared to using just binary high/low guesses).
Subtask 4
The preceding approaches obviously throw away (ignore) valuable information. However, using this information requires careful tuning of the guesses. It helps to do some small cases by hand.
- can obviously be done in guesses, by straddling the middle, for example, Guess() followed by Guess() does a high/low/equal comparison to .
can be done in , but this already needs some care, because it does not work to set this up so that the first two guesses compare to the middle number . When, after Guess() Guess(), or Guess() Guess(), the result of the second guess is colder, you won't be able to solve the remaining problem in a single guess.
You need to start with Guess() Guess() (or symmetrically Guess() Guess()). If the result of the second guess is same, Jill's number is ; if the result is colder, only candidate remains and this must be Jill's number. If the result is hotter, candidates , , and remain. Since was the most recent guess, doing Guess() will compare to , and we are done.
In general, it turns out to be possible to determine Jill's number in no more than calls of Guess.
We explain one such algorithm. Because of the nature of the guess (being a comparison), at any moment you have an interval of remaining candidate numbers. You can distinguish two cases for the location of this interval with respect to the initial interval:
- either this interval of candidates contains or (is "against a wall");
- or it contains neither nor (is "in the middle").
Furthermore, you know what the previous guess was, say .
If the interval of candidates is "in the middle", then you are home free (provided you are a bit careful), because now each guess can be made to reduce the interval sufficiently. In more guesses, you can find Jill's number among candidates. [Details suppressed (for the time being)]
If the interval of candidates is "against a wall", then you can always arrange it so that the interval is through (or symmetrically on the other side). With two extra steps, you can grow a solution that solves for in more guesses to one that solves for in more guesses.
The base cases are and .
The construction works like this. Consider the interval:
aaaabbbbbbdddddddddd
where
aaaa
is the interval through (and we assume that if the most recent guess was at , then an additional guesses can determine Jill's number in this interval);bbbbbb
is of length ;dddddddddd
is of length ;- the most recent guess was .
Your next guess is :
aaaabbbbbbdddddddddd
1G P M R
This guess compares to , that is, the first element of the d
-labeled subinterval. Do a case distinction on the result of this guess:
- Same: Jill's number is ; done.
- Colder: the interval is reduced to through ; continue with a "middle game" on
ddddddddd
of length ; - Hotter: the interval is reduced to through :
Next, guess , which boils down to comparing to . Do a case distinction on the result:aaaabbbbbb 1G P M
- Colder: "wall game" on interval through (
aaaa
), which we assumed can be solved in more guesses; - Hotter: "middle game" on
abbbbbb
of length .
- Colder: "wall game" on interval through (
Comments