📥 Download raw
{-# OPTIONS --cubical-compatible #-}

open import Padova2025.ProgrammingBasics.Lists
open import Padova2025.ProgrammingBasics.HigherOrder
open import Padova2025.ProvingBasics.Equality.Base
open import Padova2025.ProvingBasics.Equality.General
open import Padova2025.ProvingBasics.Connectives.Existential
open import Padova2025.ProvingBasics.Connectives.Disjunction
open import Padova2025.ProvingBasics.Connectives.Conjunction
open import Padova2025.ProvingBasics.Connectives.More

module Padova2025.Recreational.Choice.Hats
  (Player : Set)
  (Color  : Set)
  (dummy  : Color)
  (_≡?_   : (p q : Player)  p  q  p  q)
  where

The infinite hats problem

An evil monster puts hats of various colors on infinitely many dwarves. Each dwarf can see (and cognitively process) the hat colors of every other dwarf, but is strictly forbidden from peeking at their own color. Instead, the monster will ask every one of them to privately venture a guess regarding the color of their hat.

Is there a strategy which, if followed by the dwarves, ensures that only finitely many of them guess their color incorrectly? The strategy should be applicable regardless of the specific colors assigned by the monster.

Communication among the dwarves is allowed only before the hats have been placed. The type of colors is known (Color, fixed at the top of this module), and so is the type of dwarves (Player), but nothing is known about the distribution of colors chosen by the monster. Also note that infinitely many dwarves being right does not necessarily mean that only finitely many guess incorrectly. We assume that the type of colors is inhabited (dummy).

Obviously no successful strategy?

The challenge posed by the monster seems impossible to satisfy: The monster is free to distribute the colors however it pleases; observing the hat colors of all the other dwarves does not restrict the number of possibilities for your own hat color in any way.

Surprisingly, despite appearances, there does exist a successful strategy—if and only if (a certain instance of) the axiom of choice holds. We will explore this below. (Whether the dwarves have access to this strategy is a different question.)

Formalizing the problem

A configuration is a possible distribution of hat colors to players:

Config : Set
Config = Player  Color

A blinded configuration (for a specific player p) is a function which maps every player, with the exception of p, to a color:

BlindedConfig : Player  Set
BlindedConfig p = (q : Player)  q  p  Color

Given a configuration, we can restrict its domain to obtain a blinded configuration.

blind : (p : Player)  Config  BlindedConfig p
blind p c = λ q _  c q

A player strategy (for a player p) tells p which color to submit as their guess, given knowledge of the colors of all other players:

PlayerStrategy : Player  Set
PlayerStrategy p = BlindedConfig p  Color

A team strategy tells every player which player strategy to use:

TeamStrategy : Set
TeamStrategy = (p : Player)  PlayerStrategy p

Given a configuration and a team strategy, we can solicit every player for their guess, thereby obtaining a configuration of guesses:

run : TeamStrategy  Config  Config
run s c p = s p (blind p c)

Finally, we can formalize the notion of a successful team strategy. The relation _≗*_ used in the following definition is defined in Padova2025.ProvingBasics.Connectives.More and expresses that two configurations differ only on finitely many players.

isSuccessful : TeamStrategy  Set
isSuccessful s = (c : Config)  run s c ≗* c

Some observations

Given a blinded configuration and a color, we obtain a full configuration:

unblind : (p : Player)  BlindedConfig p  Color  Config
unblind p c x q with q ≡? p
... | left  _   = x
... | right p≢q = c q p≢q

Unblinding a blinded configuration with an arbitrary color will result in an almost identical configuration:

unblind-blind : (c : Config) (x : Color) (p : Player)  unblind p (blind p c) x ≗* c
unblind-blind = {!!}

A successful strategy

Spoiler alert.

Let us partition the type of configurations into equivalence classes according to _≗*_. By the axiom of choice, there is a choice function picking representatives for each class. Reformulating this without explicitly referring to equivalence classes, the axiom of choice concocts a value of the type Normalizer Player Color.

With a shared such choice function at hand, we can assemble a successful strategy for the players as follows. Even though each player is in the dark about which configuration precisely the evil monster has picked, each player can with certainty determine the equivalence class of the true configuration. When asked for a guess for their own color, each player should answer with whatever their color is in the chosen representative of this class. Since the representative is guaranteed to differ from the true configuration only on finitely many players, only finitely many players guess incorrectly.

Let us implement this idea in Agda.

assembleStrategy : (Config  Config)  TeamStrategy
assembleStrategy = {!!}
correct : (r : Normalizer Player Color)  isSuccessful (assembleStrategy (Normalizer.rep r))
correct = {!!}

And here we leave the dwarves at their campfire, in the long night that awaits them: How many evenings—how many lifetimes—will pass before they have agreed on a single representative for each of the uncountably many equivalence classes?