Cracking The Coding Interview Together – Problem 6.6: Blue-Eyed Island
We have all been there: sitting in an interview, confident in our coding skills, when the interviewer pivots to a brainteaser. Your heart sinks slightly. Brainteasers can feel arbitrary, like a test of whether you have heard the riddle before. But as senior engineers, we know that the best brainteasers are actually elegant abstractions of real-world system design challenges.
Enter the classic Blue-Eyed Island puzzle (Problem 6.6 in Cracking the Coding Interview). On the surface, it is a riddle about islanders, eye colors, and a mysterious visitor. Under the hood, however, it is a profound exploration of distributed consensus, state synchronization, and the transition from mutual knowledge to common knowledge. It is the exact same logical framework we use when designing fault-tolerant distributed databases or consensus protocols like Raft and Paxos.
Today, we are going to tackle this problem together. We will demystify the logic, build an inductive proof, write a clean Java simulation to model the islanders' state transitions, and discuss why this theoretical puzzle is highly relevant to modern system architecture.
Problem Statement
Let's clearly define the parameters of the challenge. We are presented with the following scenario:
- A group of people live on an island. Each person has either blue eyes or non-blue eyes (which we will refer to as brown eyes for simplicity).
- There are exactly 100 blue-eyed people on the island. The number of brown-eyed people is arbitrary.
- The islanders have a strict rule: if they discover their own eye color, they must leave the island at noon the next day.
- They cannot communicate with each other about eye color in any way. There are no mirrors, reflective surfaces, or water-gazing allowed.
- Every islander can see everyone else's eye color, but they do not know their own.
- Every islander is a perfect logician. They process information instantly and flawlessly, and they know that everyone else is also a perfect logician.
For years, life on the island is stable. Everyone knows that there are blue-eyed people (since they can see 99 or 100 of them), but no one knows their own eye color.
One day, a visitor arrives. The visitor stands before the entire island and makes a public announcement:
"At least one of you has blue eyes."
The Question: What happens next? Do people leave? If so, who leaves, and on which day?
Analyze the Problem Together
When we first read this problem, our engineering intuition might scream: "Nothing changes!"
Why? Because if there are 100 blue-eyed people, every single person on the island can already see at least 99 blue-eyed people. The visitor's announcement that "at least one person has blue eyes" seems to provide zero new information. Everyone already knew that!
This is the "Aha!" conflict of the problem. To resolve it, we must understand the difference between Mutual Knowledge (everyone knows a fact) and Common Knowledge (everyone knows that everyone knows that everyone knows... that fact). The visitor's announcement did not introduce new raw data; instead, it established a synchronization barrier. It made the fact common knowledge, allowing the islanders to align their logical clocks to a shared "Day 1."
To prove how this works, let's use the senior engineer's favorite tool for complex logic: Mathematical Induction. Let's start with small base cases and scale up.
Base Case: $C = 1$ (1 Blue-Eyed Islander)
Imagine there is only 1 blue-eyed person (let's call him Alice) and 99 brown-eyed people.
- Alice looks around and sees only brown-eyed people.
- The visitor announces: "At least one of you has blue eyes."
- Alice immediately realizes: "Since I see zero blue-eyed people, and there is at least one, it must be me!"
- Alice leaves at noon on Day 1 (the day after the announcement).
Base Case: $C = 2$ (2 Blue-Eyed Islanders)
Now, imagine there are 2 blue-eyed people (Alice and Bob).
- Alice looks around and sees exactly 1 blue-eyed person (Bob). She thinks: "If I have brown eyes, Bob is the only blue-eyed person. If so, Bob will realize this and leave on Day 1."
- Bob looks around, sees Alice, and has the exact same thought.
- Day 1 passes: Noon arrives, and no one leaves. Bob did not leave because he saw Alice and assumed Alice might be the only one.
- Day 2: Alice wakes up and sees Bob is still here. She deduces: "If Bob didn't leave on Day 1, it means Bob saw another blue-eyed person. Since I only see Bob, that other person must be me!"
- Both Alice and Bob reach this conclusion simultaneously and leave together at noon on Day 2.
The Inductive Step
We can generalize this behavior. Let C be the number of blue-eyed islanders.
- If C = 1, they leave on Day 1.
- If C = 2, they leave on Day 2.
- If C = k, they will all leave on Day k.
If there are C = 100 blue-eyed people, nothing will happen for 99 days. To a casual observer, the island looks completely unchanged. But on the 100th day, all 100 blue-eyed islanders will simultaneously realize their eye color and leave the island at noon.
Questions for the Interviewer
In a real interview, a senior engineer does not just jump into coding or solving. We ask clarifying questions to define the boundaries of the system. Here are three critical questions you should ask:
- "Is the visitor's announcement a broadcast event?"
Why this matters: We need to confirm that the announcement is received by all nodes (islanders) simultaneously, establishing a shared global clock. (Answer: Yes, it is a public broadcast). - "Do the islanders have perfect memory and logical execution?"
Why this matters: We are assuming zero packet loss and zero processing latency. Every islander must correctly register the absence of departures every single day. (Answer: Yes, they are perfect logical actors). - "What happens to the brown-eyed islanders?"
Why this matters: Do they ever leave? Since they see 100 blue-eyed people leave on Day 100, they now know there are no more blue-eyed people left. However, unless they know the exact total number of brown-eyed people on the island beforehand, they still cannot deduce their own eye color, so they remain. (Answer: They remain on the island).
Think About the Solution
How do we model this programmatically? We want to build a simulation that proves our inductive hypothesis.
Let's design a state machine. Each islander is an independent node with a state: `id`, `hasBlueEyes`, and `hasLeft`.
The simulation will run in discrete "Day" cycles. Each day has two phases:
- Observation Phase: Each islander counts the number of active (still on the island) blue-eyed people they can see.
- Deduction & Action Phase: If the current day matches the number of visible blue-eyed people $+ 1$, the islander deduces they must have blue eyes and schedules their departure for noon.
Let's write the code to make this concrete.
Write Code and Explain
Here is a complete, production-ready Java implementation of the Blue-Eyed Island simulation. We use clean object-oriented design and stream-based filtering to keep the logic readable and maintainable.
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
public class BlueEyedIslandSimulation {
// Represents an individual islander (a node in our distributed system)
public static class Islander {
private final int id;
private final boolean hasBlueEyes;
private boolean leftIsland = false;
public Islander(int id, boolean hasBlueEyes) {
this.id = id;
this.hasBlueEyes = hasBlueEyes;
}
public int getId() {
return id;
}
public boolean hasBlueEyes() {
return hasBlueEyes;
}
public boolean hasLeftIsland() {
return leftIsland;
}
public void leave() {
this.leftIsland = true;
}
}
public static void runSimulation(int blueEyedCount, int brownEyedCount) {
List<Islander> islanders = new ArrayList<>();
// Initialize the population
for (int i = 0; i < blueEyedCount; i++) {
islanders.add(new Islander(i, true));
}
for (int i = 0; i < brownEyedCount; i++) {
islanders.add(new Islander(blueEyedCount + i, false));
}
System.out.println("=== Simulation Started ===");
System.out.printf("Population: %d Blue-eyed, %d Brown-eyed.\n", blueEyedCount, brownEyedCount);
System.out.println("Visitor announces: 'At least one person has blue eyes.'\n");
int day = 1;
boolean simulationRunning = true;
while (simulationRunning) {
List<Islander> departingToday = new ArrayList<>();
// Filter active islanders
List<Islander> activeIslanders = islanders.stream()
.filter(islander -> !islander.hasLeftIsland())
.collect(Collectors.toList());
// If all blue-eyed islanders have left, the simulation stabilizes
long activeBlueEyedCount = activeIslanders.stream()
.filter(Islander::hasBlueEyes)
.count();
if (activeBlueEyedCount == 0) {
System.out.printf("Day %d: No blue-eyed islanders remain. The system has stabilized.\n", day);
break;
}
for (Islander actor : activeIslanders) {
// Count how many blue-eyed people the current actor can see
long visibleBlueEyes = activeIslanders.stream()
.filter(other -> other != actor && other.hasBlueEyes())
.count();
// Epistemic Logic Step:
// If today is Day (visibleBlueEyes + 1), and no one has left yet,
// the actor deduces that they themselves must have blue eyes.
if (day == visibleBlueEyes + 1) {
departingToday.add(actor);
}
}
// Process departures at noon
if (!departingToday.isEmpty()) {
for (Islander departing : departingToday) {
departing.leave();
System.out.printf("[DEPARTURE] Day %d: Islander %d (Blue-Eyed: %b) leaves the island.\n",
day, departing.getId(), departing.hasBlueEyes());
}
// Once the cascade occurs, we can stop the simulation
simulationRunning = false;
} else {
System.out.printf("Day %d: Noon passes. No one leaves.\n", day);
}
day++;
// Safety break to prevent infinite loops in case of logical errors
if (day > 105) {
System.out.println("Simulation exceeded safety limit.");
break;
}
}
System.out.println("=== Simulation Ended ===");
}
public static void main(String[] args) {
// Let's run it with a smaller subset first to verify, e.g., 4 blue-eyed islanders
runSimulation(4, 5);
// To run the actual problem statement:
// runSimulation(100, 100);
}
}
Code Walkthrough
Let's break down the core execution loop of our simulation:
- State Initialization: We populate our island with a mix of blue-eyed and brown-eyed islanders. Each islander is an instance of the
Islanderclass, maintaining its own state. - The Daily Loop: The
while (simulationRunning)loop represents the passage of days. Each iteration is one full day. - The Observation Step: Inside the loop, each active islander counts how many other active islanders have blue eyes (
visibleBlueEyes). - The Deduction Step: This is where the magic happens. If
day == visibleBlueEyes + 1, the islander realizes that the only way the system could have reached this day without a departure is if they themselves are blue-eyed. They add themselves to thedepartingTodaylist. - The Noon Barrier: At the end of the day, all islanders in
departingTodayleave simultaneously.
Time & Space Complexity
Let's analyze the computational complexity of our simulation code. Let $N$ be the total number of islanders on the island, and $C$ be the number of blue-eyed islanders.
| Metric | Complexity | Explanation |
|---|---|---|
| Time Complexity | O(C imes N^2) | The simulation runs for C days. On each day, we iterate through N active islanders, and each islander scans the rest of the population (O(N)) to count visible blue eyes. This results in O(C imes N^2) operations. |
| Space Complexity | O(N) | We store the state of $N$ islanders in an in-memory list. The call stack and auxiliary lists (like departures) scale linearly with the population size. |
Why This Problem Matters (The Senior Perspective)
At first glance, the Blue-Eyed Island puzzle seems like a purely academic exercise. But as senior engineers, we should look closer. This puzzle is a perfect model for distributed consensus over synchronous networks.
Consider these architectural parallels:
1. Common Knowledge vs. Mutual Knowledge
In distributed systems, we often mistake mutual knowledge for common knowledge. Suppose we have a cluster of database nodes. Every node knows that a transaction is ready to commit (mutual knowledge). However, they cannot commit until they know that every other node knows that they are ready. This is why we need protocols like Two-Phase Commit (2PC) or Raft. The visitor's announcement is the equivalent of a coordinator sending a global PREPARE broadcast, establishing the common knowledge required to safely execute a state transition.
2. The Silent Heartbeat (Failure Detection)
How did the islanders communicate? They did so through silence. Every day that passed without anyone leaving was a silent message: "I see more blue-eyed people than the current day count."
In distributed systems, we use the absence of messages (timeouts) to infer state. If a follower node does not receive a heartbeat from the leader within a specific window, it infers that the leader is dead and initiates an election. Silence is a highly informative state transition.
3. The Danger of Network Partitions
What happens if one islander falls asleep and misses the visitor's announcement? The global clock is broken. That islander will be out of sync, causing the entire logical deduction chain to collapse. This is why clock synchronization (using NTP or TrueTime in Google Spanner) is one of the hardest and most critical aspects of building distributed databases.
Final Thoughts
The Blue-Eyed Island puzzle is a beautiful reminder that communication is not just about sending data; it is about aligning state. By understanding the transition from mutual knowledge to common knowledge, we can write better code, design more robust distributed systems, and ace our technical interviews with confidence.
What did you think of this breakdown? Have you ever had to design a system that relied on implicit state synchronization like the islanders' daily noon barrier? Let's discuss in the comments below!
Until next time, keep building, keep learning, and happy coding!
Member discussion