‹ back to the board

Thursday, October 1

Mastermulti-constraint & composite logic

The Reliquary Beneath the Drowned Chapel

Commission of the Warden's Guild of Bitwick

Beneath the Drowned Chapel the Warden's Guild keeps a reliquary with a fixed number of niches. Adventurers bring back relics from the wild, and when every niche is full the weakest relic is carried back out. The guild needs a ledger that decides, without fail, which relic leaves.

Implement a class Reliquary:

  • constructor `(capacity)`: capacity is a non-negative integer, the maximum number of relics stored at once. The reliquary starts empty.
  • `stow(name, power)`: name is a non-empty string, power a non-negative integer. Returns a string.
  • `invoke(name)`: returns an integer.
  • `peek(name)`: returns an integer.
  • `seal(name)`: returns a boolean.

Every stored relic has a power, an invocation count, a last-touched time, and a sealed flag. To *touch* a relic is to set its last-touched time later than every earlier touch.

`stow(name, power)` 1. If a relic named name is already stored, its power becomes power and it is touched. Its invocation count and sealed flag are unchanged. Nothing is removed. Return "". 2. Otherwise, if fewer than capacity relics are stored, store it with invocation count 0, unsealed, and touched. Return "". 3. Otherwise the reliquary is full. The contenders are every *unsealed* stored relic plus the newcomer, which counts as having power power, 0 invocations, and a last-touched time later than every stored relic. The weakest contender is the one with the lowest power; among equal power, the fewest invocations; among those, the earliest last-touched time. - If the weakest is a stored relic, remove it, store the newcomer (0 invocations, unsealed, touched), and return the removed relic's name. - If the weakest is the newcomer, nothing changes and name is returned.

With capacity 0, or when every stored relic is sealed, the newcomer is the only contender and is returned.

`invoke(name)`: if stored, its invocation count increases by 1, it is touched, and its power is returned. Otherwise return -1 and change nothing.

`peek(name)`: return the stored relic's power, or -1 if it is not stored. Changes nothing: it is neither a touch nor an invocation.

`seal(name)`: if stored, mark it sealed (permanently; sealing an already sealed relic is allowed) and return true; otherwise return false. Sealing is not a touch. Sealed relics may still be re-stowed and invoked.

  • stateful objects with eviction rules
  • Master

examples

  1. case 1capacity 2; stow Ember Crown (power 5), stow Frost Blade (power 3), stow Storm Horn (power 4)the third stow returns "Frost Blade": it is the weakest of Ember Crown, Frost Blade and the newcomer
  2. case 2capacity 1; stow Ashen Idol (power 3), invoke Ashen Idol, stow Bone Flute (power 3)the last stow returns "Bone Flute": equal power, but the newcomer has fewer invocations, so it is turned away and Ashen Idol stays
  3. case 3capacity 2; stow Wyrm Tooth (power 1), seal Wyrm Tooth, stow Lich Lantern (power 8), stow Gale Sigil (power 5)the last stow returns "Gale Sigil": the sealed Wyrm Tooth is not a contender, and Gale Sigil is weaker than Lich Lantern
  4. case 4capacity 0; stow Ember Crown (power 5)"Ember Crown": with no room at all, the newcomer is always turned away
reward
540 XP
signature
Reliquary
not yet run

TypeScript, run as ES2022 — types are stripped, not checked. If a JS engine would run it, so will we.

loading the editor…
  • weakest power is evicted
  • invocations break power ties
  • recency breaks the final tie
  • a weaker newcomer is turned away
  • equal-power newcomer loses to an invoked relic
  • equal-power newcomer displaces an uninvoked relic
  • sealed relics are never evicted
  • every stored relic sealed
  • zero capacity
  • re-stowing changes power
  • peek is not a touch
  • re-stowing keeps the invocation count
  • a long night in the vault
The Reliquary Beneath the Drowned Chapel · bitwick