~/problems / Coordination / Barrier

Street lamps that copy their neighbours

easy ~15 min

A street has a row of smart lamps. Every night each lamp looks at its own brightness and its two neighbours' brightness from the previous night and picks a new brightness with a shared rule(left, mine, right). The first and last lamp see 0 for the missing neighbour.

Each lamp's controller is slow (the rule call takes a while), so simulate the street with one thread per lamp, all working in parallel.

Implement simulate(start: list[int], nights: int, rule) -> list[int]:

  • Start one thread per lamp. Lamp i's thread makes all of lamp i's rule calls, one per night.
  • Night by night, every lamp must use its neighbours' values from the previous night, never a value a faster neighbour already computed for the current night.
  • Return the brightness list after nights nights.
spread = lambda l, m, r: max(l, m, r)
simulate([0, 0, 5, 0, 0], 1, spread)   # [0, 5, 5, 5, 0]
simulate([0, 0, 5, 0, 0], 2, spread)   # [5, 5, 5, 5, 5]
simulate([3, 1], 0, spread)            # [3, 1]   no nights, no rule calls

With the fast lamps racing ahead, night 1 of the first example could wrongly become [0, 5, 5, 5, 5]: lamp 3 already shows 5 when lamp 4 looks at it. That is the bug the tests look for.

Constraints: 0 <= len(start) <= 20, 0 <= nights <= 50. rule may take different amounts of time on different calls. Don't sleep or busy-wait.

Show hint

Keep the current values and a separate "next night" list. Each thread writes only its own slot of the next list, then meets the others at a threading.Barrier(len(start), action=...): the action runs once, after all have written and before any is released, which is the moment to make "next" the new "current".

Topic: Barrier. Rendezvous: n threads wait until all arrive.

0:00
Ctrl ' run · Ctrl ↵ submit
esc