The Moonfair Compacts of Iskelmere Glade
Once a month the fey market rises in Iskelmere Glade, and no mortal trades there except as the old Compacts allow. The Glade-Wardens of Bitwick pay well for anyone who can read the Compacts as the fey do and judge each traveler before they set foot among the stalls. This contract asks for that judgement.
Write moonfairVerdicts(compacts, travelers).
Compacts. compacts is a list. Each compact is a list [kind, goods, start, end, rank, verdict]: - kind is a string naming a kind of traveler, or "*", which matches any kind. - goods is a string naming a kind of goods, or "*", which matches any goods. - start and end are integers from 0 to 23 giving an hour window: - if start < end, the window covers every hour h with start <= h < end; - if start > end, the window runs past midnight and covers every hour h with h >= start or h < end; - if start == end, the window covers all 24 hours. - rank is an integer (it may be zero or negative). - verdict is the string "allow" or "forbid".
Travelers. travelers is a list. Each traveler is a list [kind, goods, hour]: two lowercase strings (never "*") and an integer hour from 0 to 23.
A compact matches a traveler when its kind is "*" or equal to the traveler's kind, its goods is "*" or equal to the traveler's goods, and its window covers the traveler's hour.
A compact's specificity is the number of these that are true: its kind is not "*"; its goods is not "*"; its start differs from its end. Specificity is therefore 0, 1, 2 or 3.
Judgement. For each traveler, consider only the compacts that match it. The deciding compact is chosen as follows: 1. The compact with the highest rank wins. 2. Among compacts tied on rank, the one with the highest specificity wins. 3. If compacts are still tied, and any of them has verdict "forbid", the result is "forbid"; otherwise it is "allow".
If no compact matches a traveler, the result for that traveler is "forbid".
Return a list of strings, one per traveler in the same order as travelers, each "allow" or "forbid". An empty travelers list gives an empty list.
examples
- case 1
compacts: anyone may trade anything at any hour (rank 0, allow); goblins are forbidden everything (rank 1); goblins may trade moonsilk from hour 20 until hour 4 (rank 1, allow). Traveler: a goblin with moonsilk at hour 22"allow" - both rank-1 compacts match, but the moonsilk compact names kind, goods and a window (specificity 3) and beats the specificity-1 ban - case 2
the same compacts; a goblin with moonsilk at hour 4"forbid" - the window 20 to 4 stops before hour 4, so only the goblin ban and the rank-0 welcome match, and rank 1 wins - case 3
compacts: honey may be traded by anyone (rank 3, allow); hobs are forbidden everything (rank 3). Traveler: a hob with honey at hour 5"forbid" - same rank, same specificity, so forbid wins the tie - case 4
no compacts at all; a troll with iron at hour 3"forbid" - nothing matches
- reward
- 540 XP
- signature
moonfairVerdicts
TypeScript, run as ES2022 — types are stripped, not checked. If a JS engine would run it, so will we.
- goblin_moonsilk_example
- no_compacts_forbids
- no_travelers
- rank_beats_specificity
- forbid_wins_full_tie
- window_counts_as_specificity
- midnight_wrap_boundaries
- equal_start_end_is_whole_day
- negative_ranks
- three_way_specificity_tie
- layered_compacts