The Nested Phials of the Orrinvale Alembists
The Alembists of Orrinvale brew the warding-draughts carried by parties bound for the Hollowmere Barrows. Their formulae are written in a cramped notation of reagents and nested phials. Before a draught can be brewed at a field camp, its formula must be settled into plain form, with one entry per reagent and its total measure. Formulae copied in haste are sometimes corrupt, and a corrupt formula must be refused outright. The guild pays for a settler that never errs.
Write settleFormula(formula). It takes a string formula and returns a string.
The notation
- A reagent name is one uppercase letter
A–Zfollowed by zero or more lowercase lettersa–z. The name ends at the first character that is not a lowercase letter. SoAshMossis two reagents,AshandMoss. - A phial is
(followed by a formula followed by), or[followed by a formula followed by]. A phial must close with the same kind of bracket that opened it. The formula inside a phial must be non-empty and valid, so(),[]and(())are all corrupt. - A count is a run of one or more digits
0–9placed immediately after a reagent name or after a phial's closing bracket. All consecutive digits are read as one decimal number, and that number multiplies the item they follow. A count must not begin with0, so0and05are corrupt. An explicit1is allowed. An item with no count has count 1. - A formula is a sequence of zero or more items. Each item is a reagent name or a phial, and each item may be followed by a count. The empty string is a valid formula.
The formula is corrupt if it cannot be read entirely by these rules. Examples of corrupt input include:
- a closing bracket with no matching opener
- an unclosed phial
- a closer of the wrong kind
- a digit that does not follow a name or a phial
- a lowercase letter that does not continue a name
- any other character, including spaces
What to return
- If the formula is corrupt, return the string
"INVALID". - Otherwise, compute each reagent's total measure. For every occurrence of the reagent, multiply that occurrence's own count by the count of every phial enclosing it. The total measure is the sum of these products over all occurrences.
- Return a string listing each distinct reagent exactly once, in this order:
- by total measure, largest first;
- ties broken by name in ascending character-code order (so
Ashcomes beforeAshen). - Write each reagent as its name followed by its total in decimal with no leading zeros. When the total is exactly 1, write the name alone. Entries are concatenated with no separators.
- An empty formula settles to the empty string
"".
All totals in the tests are below one billion.
examples
- case 1
formula of "Ash2(MossVex)3Ash""Ash3Moss3Vex3": Ash totals 2 + 1, Moss and Vex are 1 x 3 each, and the three-way tie is broken by name - case 2
formula of "[Fen(Gall2Rue)2]3Gall""Gall13Rue6Fen3": inside the square phial Gall is 2 x 2 = 4, then x 3 = 12, plus the loose Gall makes 13 - case 3
formula of "Ash()""INVALID": a phial may not be empty - case 4
formula of "Wolfsbane1""Wolfsbane": an explicit count of 1 is legal, but a total of 1 is written as the bare name
- reward
- 540 XP
- signature
settleFormula
TypeScript, run as ES2022 — types are stripped, not checked. If a JS engine would run it, so will we.
- three-way tie broken by name
- nested phials of both kinds
- empty formula
- mismatched bracket kind
- crossed brackets
- empty phial
- phial holding only an empty phial
- leading zero count
- zero count on a phial
- lowercase without capital
- unclosed phial
- stray closer
- digit where an item should start
- space is corrupt
- single reagent
- explicit count of one
- prefix name tie
- multi-digit nested multipliers
- settled form round-trips
- countless nested phials
- tie at twelve across loose and phial
- single-letter names and character order