The Beast-Writs of Ivelcote Abbey
The conjurers of Ivelcote Abbey call up bands of spirit-beasts by reading a writ aloud inside the summoning ring. Before any writ is read, the Abbey posts a bounty for whoever can reckon exactly which beasts it will call and how many of each, and who can spot a writ that is miswritten. A miswritten writ is never read.
Write tallyWrit(formula). formula is a string. Return a string.
### Writ grammar
A writ is one or more parts separated by +.
- A part is an optional *coefficient* followed by one or more *units*.
- A unit is one of:
- a *beast name* followed by an optional *count*;
(, one or more units,), then an optional count;[, one or more units,], then an optional count.- A beast name is one uppercase letter
A–Zfollowed by zero or more lowercase lettersa–z. A name takes every lowercase letter that immediately follows it. SoFyOstis the two namesFyandOst, andFyostis the single nameFyost. - A coefficient or count is a run of digits
0–9that forms a positive integer with no leading zero.1,7and12are allowed.0and05are not. It takes every digit that immediately follows. An omitted count or coefficient means 1.
Brackets nest to any depth. Each ( must be closed by ), and each [ must be closed by ]. No other character is part of the grammar, and that includes spaces.
### Counting
- A beast name contributes its count.
- A bracketed group's count multiplies everything inside it.
- A part's coefficient multiplies everything in that part.
- The totals of all parts are added together. A name that appears in several places is summed.
### Return
If formula does not match the grammar exactly, return "INVALID".
Otherwise, return the canonical writ:
- It contains every beast name exactly once, sorted in ascending order by character code. A name therefore comes before any longer name that begins with it, so
Bcomes beforeBa. - Each name is written followed by its total. The total is left out when it is 1.
- The result contains no brackets, no coefficients and no
+.
examples
- case 1
formula of "Ka(Fy2[OstRu]3)2""Fy4KaOst6Ru6": the [OstRu] group triples, then the whole round group doubles, and Ka stands alone - case 2
formula of "2FyOst+3Ost2""Fy2Ost8": the first part gives Fy 2 and Ost 2, the second gives Ost 6 - case 3
formula of "BaB2""B2Ba": B sorts before Ba because it is a prefix of it - case 4
formula of "(Fy]2""INVALID": a round bracket cannot be closed by a square one
- reward
- 540 XP
- signature
tallyWrit
TypeScript, run as ES2022 — types are stripped, not checked. If a JS engine would run it, so will we.
- nested groups multiply
- coefficients and parts sum
- names are sorted
- repeated name merges
- prefix name sorts first
- long name versus short name
- multi-digit counts and coefficient
- deep nesting
- single bare name
- explicit ones are dropped
- coefficient on a later part
- mismatched bracket
- empty writ
- trailing plus
- leading plus
- double plus
- count with leading zero
- zero count
- coefficient with leading zero
- coefficient alone
- empty group
- digit inside opening bracket
- lowercase start
- unclosed bracket
- close without open
- space is not allowed