The Mooring-Edicts of Corrandel Sky-Docks
High above the cliffs of Corrandel, griffin-ships tie up at the Sky-Docks, and no traveller sets foot on a gangway without the Dockwardens' leave. Their leave is written as a ledger of edicts, amended over the seasons by the Wardens' Council. The Council has posted a bounty for anyone who can read the ledger the way the Wardens do and pronounce each waiting traveller's fate.
Write mooringVerdicts(edicts, travellers).
Travellers. travellers is a list of strings. Each one has exactly three segments separated by .: kin.company.trade, for example "dwarf.ironbrand.smith". Every segment is one or more lowercase letters.
Edicts. edicts is a list of strings. Lines are numbered from 1 in list order. Each line is exactly one of: - "ADMIT p" or "BAR p", an ordinary edict. - "!ADMIT p" or "!BAR p", an absolute edict. - "REPEAL k", where k is a positive integer.
A pattern p has exactly three segments separated by .. Each segment is either lowercase letters or *. A pattern matches a traveller when, at every one of the three positions, the pattern's segment is * or is exactly equal to the traveller's segment at that position. An edict's specificity is the number of its segments that are not *, so it is 0 to 3.
Repeal. An ADMIT or BAR line (absolute or not) at line number k is struck if some "REPEAL k" line appears later in the list. A REPEAL has no effect in these cases: - its k is not the number of an earlier line, meaning it is out of range, its own number, or a later number; - line k is itself a REPEAL.
In particular, a REPEAL can never restore a struck edict. Repealing the same line more than once is the same as repealing it once. REPEAL lines never match travellers.
Verdict. For each traveller, consider only the edicts that are not struck and whose pattern matches that traveller. - If none remain, the verdict is "BAR". - Otherwise, if any of them is absolute, discard all the non-absolute ones. - Among those left, keep only the ones with the highest specificity. - Of those, the edict on the highest-numbered line decides. Its verdict is "ADMIT" or "BAR", ignoring the !.
Return a list of strings, each "ADMIT" or "BAR", with one entry per traveller in the same order as travellers. If travellers is empty, return an empty list.
examples
- case 1
edicts ["BAR elf.*.*", "ADMIT *.*.archer", "BAR *.silvan.*"]; travellers ["elf.silvan.archer", "elf.lorn.archer"]["BAR", "ADMIT"]. The first traveller matches all three edicts, each with specificity 1, so line 3 decides. The second matches lines 1 and 2, so line 2 decides. - case 2
edicts ["ADMIT human.varn.squire", "!BAR human.*.*"]; travellers ["human.varn.squire"]["BAR"]. The absolute edict outranks the more specific ordinary one. - case 3
edicts ["REPEAL 2", "ADMIT *.*.*", "BAR orc.*.*", "REPEAL 3", "REPEAL 4"]; travellers ["orc.tusk.raider"]["ADMIT"]. Line 1 points at a later line and does nothing. Line 4 strikes line 3. Line 5 points at a REPEAL and does nothing, so line 3 stays struck. - case 4
edicts []; travellers ["human.vale.merchant"]["BAR"]. No edict matches, so the traveller is barred.
- reward
- 540 XP
- signature
mooringVerdicts
TypeScript, run as ES2022 — types are stripped, not checked. If a JS engine would run it, so will we.
- specificity beats order
- later line wins on equal specificity
- absolute outranks specificity
- repeal strikes edicts and default bars
- invalid repeals are ignored and cannot restore
- empty ledger bars everyone
- no travellers
- struck absolute falls back to ordinary edicts
- duplicate patterns and double repeal
- segments match by position