‹ back to the board

Thursday, September 10

Mastermulti-constraint & composite logic

The Ward-Carver of the North Gate

Over the north gate of bitwick, the ward-carver recuts inscriptions before they are set into stone. A ward only holds if every operation in it is bracketed exactly once. Apprentices bring her inscriptions written flat, with the brackets left out, and she must work out the grouping and cut it herself. Sometimes what an apprentice brings is not an inscription at all, and then the stone is left blank.

expr is a string containing no whitespace. Return a string: the fully bracketed recut of expr, or the empty string "" if expr is not a well-formed inscription.

An inscription is one of:

  • a numeral: one or more of the digits 0-9 (leading zeros are allowed, and are kept as written)
  • ( followed by an inscription followed by )
  • an operator applied to inscriptions.

The operators, loosest-binding first:

1. = — binary, non-associative: at most one = may stand outside brackets in any one inscription, so a=b=c is not well-formed while (a=b)=c is 2. + and - — binary, left-associative 3. * and / — binary, left-associative 4. ^ — binary, right-associative 5. - — prefix, and may be stacked 6. ! — postfix, and may be stacked

Prefix - binds looser than ^, so -a^b groups as -(a^b). The operand to the right of ^ is read at the prefix level, so a^-b is well-formed and groups as a^(-b); the operand to the left of ^ is read at the postfix level, so a prefix - standing there always applies to the whole power.

The recut:

  • a numeral recuts to itself
  • a binary application recuts to ( + recut left operand + the operator character + recut right operand + )
  • a prefix - application recuts to (- + recut operand + )
  • a postfix ! application recuts to ( + recut operand + !)

The result contains no spaces and no brackets other than those, so brackets in expr that only restate a grouping already forced by the rules do not appear in the result.

Anything that is not an inscription — including an inscription followed by any leftover characters, and including the empty string — is not well-formed.

  • recursive-descent parsing
  • Master

examples

  1. case 1expr = "-2^3!""(-(2^(3!)))" — the postfix binds tightest, the power next, and the prefix minus takes the whole power
  2. case 2expr = "2^-3*4""((2^(-3))*4)"
  3. case 3expr = "(((7)))""7" — no operator was applied, so no bracket is cut
  4. case 4expr = "1=2=3""" — a second bare `=` is not well-formed
reward
540 XP
signature
carveWard
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…
  • star binds tighter than plus
  • prefix minus takes the whole power
  • power is right associative
  • minus on the right of a power
  • subtraction is left associative
  • the seal cannot be chained
  • a bracketed seal may be sealed again
  • seal is looser than addition
  • redundant brackets vanish
  • stacked prefix and postfix
  • postfix after a bracketed group
  • leading zeros are kept
  • blank stone
  • leftover rubble
  • dangling operator
  • empty brackets
The Ward-Carver of the North Gate · bitwick