‹ back to the board

Sunday, October 25

Mastermulti-constraint & composite logic

The Spirit-Jars of Hollenbrask Bazaar

Commission of the Binders' Lodge, Hollenbrask Bazaar

The spirit-binder Maudrey Venn walks the caravan roads with a rack of warded jars, each holding one bound spirit. The rack has room for only so many. When a new spirit must go in and the rack is full, one spirit is released back into the wild to make room. Some jars carry a seal, and a sealed spirit is never released. The Lodge wants the rack's rules made exact. Build the class SpiritRack.

Construction. The rack is created with one argument, capacity, a non-negative integer: the most spirits it can hold at once.

State. Each held spirit has a name (a non-empty string of lowercase letters), a power (a non-negative integer), a use count, a time of last use, and a sealed flag.

A use is either a successful bind of that spirit or a summon of it while it is held. Each use adds 1 to the spirit's use count and makes it the most recently used spirit.

Methods

  • bind(name, power) returns a boolean.
  • If name is already held, its power becomes power. This counts as a use. Its sealed flag is unchanged and no spirit is released. Return true.
  • Otherwise, if fewer than capacity spirits are held, add the spirit with use count 1, as the most recently used, unsealed. Return true.
  • Otherwise the rack is full. Among the unsealed held spirits, choose the one with the lowest use count. If several are tied, choose the one whose last use is earliest. Release that spirit, then add the new one as described above, and return true. If no held spirit is unsealed (this includes a capacity of 0), nothing changes and the method returns false.
  • summon(name) returns the spirit's power if it is held, and this counts as a use. If it is not held, return -1 and change nothing.
  • seal(name): if the spirit is held, mark it sealed and return true. Otherwise return false. This is not a use.
  • unseal(name): if the spirit is held, clear its sealed mark and return true. Otherwise return false. This is not a use.
  • held() returns the names of all held spirits as a list of strings, sorted in ascending alphabetical order.

A released spirit is forgotten entirely. If it is bound again later, it returns as a new spirit: use count 1 and unsealed.

  • stateful objects with eviction rules
  • Master

examples

  1. case 1capacity 2; bind a 10, bind b 20, summon a, bind c 30, then held()true, true, 10, true. b is released because it was used once and a twice. held() is ["a", "c"]
  2. case 2capacity 2; bind a 1, bind b 2, summon a, summon b, bind c 3, then held()c's bind returns true and releases a: both were used twice, and a's last use was earlier. held() is ["b", "c"]
  3. case 3capacity 2; bind a 1, bind b 2, seal a, seal b, bind c 3, then held()bind c returns false because every held spirit is sealed. Nothing changes, and held() is ["a", "b"]
  4. case 4capacity 2; bind a 1, bind b 2, bind a 9, bind c 3, then held()All four binds return true. Rebinding a releases nothing and counts as a use, so c's arrival releases b. held() is ["a", "c"]
reward
540 XP
signature
SpiritRack
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…
  • use count decides release
  • earliest last use breaks ties
  • sealed spirit is skipped
  • all sealed refuses the bind
  • capacity zero holds nothing
  • rebind updates without releasing
  • released spirit returns fresh
  • sealing is not a use
  • rebinding keeps the seal
The Spirit-Jars of Hollenbrask Bazaar · bitwick