Hacker News new | ask | show | jobs
by cafeinux 473 days ago
We can think of the goblins as functions that return either the truth, the inverse of the truth, or a random answer.

  // Knight, tells the truth
  K(a) { return a }
  // Knave, lies
  k(a) { return !a }
  // Joker, flips a coin
  J(a) { return random(true, false) }
We can craft a question that will make the Knights and Knaves always return the truth. This could be "What would you answer if you were asked if $goblin is the $role?". This question will be noted Q(recipient,goblin,role), and here's what it returns depending if the recipient is a Knight, Knave or Joker.

     $goblin is $role   | K | K(K) | k | k(k) | J | J(J) |
            T           | T |   T  | F |  T   |T/F| T/F  |
            F           | F |   F  | T |  F   |T/F| T/F  |
If we didn't have the Joker and wanted to determine the two goblins roles, it would be as easy as asking this question to one of the two goblins.

Now we add the Joker, but we also can ask two more questions. We need to use those two questions to determine who is the joker, so we can discard him and use our last question to discriminate the two remaining goblins.

The 3 goblins will be noted G1, G2, and G3.

Let's ask Q(G1,G2,J).

Two possibilities:

1. The answer is "Yes" (true), either G1 is the Joker or G2 is the Joker. -> G3 is not the Joker.

2. The answer is "No" (false), either G1 is the Joker or G2 is not the Joker. -> G2 is not the Joker.

Now that we know at least one goblin who is not the Joker (whether they are G2 or G3, I'll call them ¬J), we can ask them the question, this time about the first goblin. Q(¬J,G1,J) 1. The answer is "Yes", G1 is the Joker, the other two are not. 2. The answer is "No", the remaining goblin is the Joker.

I now know who is the Joker, meaning the other two goblins are either a Knight or a Knave.

Ask Q(¬J1,¬J2,K) and you'll know who is the Knight and who is the Knave.

In summary, the scenarios are as follows:

       Q1     |      Q2      |      Q3      | G1 | G2 | G3 |
   Q(G1,G2,J) |  Q(G3,G1,J)  |  Q(G3,G2,K)  | J  | K  | k  |
   Q(G1,G2,J) |  Q(G3,G1,J)  | ¬Q(G3,G2,K)  | J  | k  | K  |
   Q(G1,G2,J) | ¬Q(G3,G1,J)  |  Q(G3,G1,K)  | K  | J  | k  |
   Q(G1,G2,J) | ¬Q(G3,G1,J)  | ¬Q(G3,G1,K)  | k  | J  | K  |
  ¬Q(G1,G2,J) |  Q(G2,G1,J)  |  Q(G2,G3,K)  | J  | k  | K  |
  ¬Q(G1,G2,J) |  Q(G2,G1,J)  | ¬Q(G2,G3,K)  | J  | K  | k  |
  ¬Q(G1,G2,J) | ¬Q(G2,G1,J)  |  Q(G2,G1,K)  | K  | k  | J  |
  ¬Q(G1,G2,J) | ¬Q(G2,G1,J)  | ¬Q(G2,G1,K)  | k  | K  | J  |
PS: If we assume that "What would you answer if you were asked if $goblin is the $role?" is forbidden because the Joker cannot know in advance what he would answer if they were asked if any goblin is any role, since it depends on their coin-flip, meaning that they wouldn't know what is the truth and what is the lie, and thus they cannot lie or tell the truth reliably, we can switch the question for "If you were asked if you were the truth-teller, or if you were asked if $goblin was the $role, would your answer to both questions be the same and always the same?".