‹ back to the board

Sunday, September 27

Mastermulti-constraint & composite logic

The Gate of Twenty-Six Dials

The north gate of bitwick is held shut by twenty-six brass dials, lettered a through z. Every dial stands at 0 when the gate is locked. A traveller hands the gatekeeper an inscription; the gate opens to the single number the inscription reads out.

readGate(expr) takes the inscription as a string and returns its value as an integer.

Tokens. expr holds only digits, lowercase letters a-z, the characters + - * ^ = ,, round brackets, and spaces. Spaces may sit anywhere between tokens and mean nothing. A run of digits is a non-negative literal. A single letter names a dial and reads its current value.

Forms, listed from loosest-binding to tightest:

  • x , y — left-associative. Evaluate x, then y; the value is the value of y.
  • d = x — right-associative. Store the value of x in dial d; the value is that stored number.
  • x + y and x - y — left-associative sum and difference.
  • x * y — left-associative product.
  • - x — prefix negation, and it may be stacked.
  • x ^ y — right-associative. x raised to the power y.

So prefix negation binds looser than ^, and ^ binds tighter than every other form. Brackets ( ... ) may enclose any inscription, including one that contains , or =, and a bracketed inscription is an operand like any other.

Order of evaluation. Operands are evaluated left to right, and a write to a dial takes effect at once, so any operand evaluated later reads what an earlier one stored.

Guarantees. expr is non-empty and well-formed. The complete left operand of every = is a bare dial letter. Every exponent (the right operand of ^) evaluates to an integer from 0 to 12, and every value that arises stays within ±1000000000.

Return the integer value of the whole inscription.

  • recursive-descent parsing
  • Master

examples

  1. case 1expr of "-2 ^ 2"-4 (the raising happens first, then the negation)
  2. case 2expr of "a = b = 3, a + b"6
  3. case 3expr of "a = 2, a * (a = 3) + a"9 (the left factor read 2, the right factor stored 3, and the final a reads 3)
  4. case 4expr of "q"0 (a dial never written still stands at 0)
reward
540 XP
signature
readGate
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…
  • plain precedence
  • power outranks negation and leans right
  • assignment chains rightward
  • a write seen by a later operand
  • unwritten dial reads zero
  • single literal
  • stacked negation and bracketed product
  • no spaces, repeated writes
  • sequence inside brackets
  • assignment looser than arithmetic
  • zero exponent and negated factor
The Gate of Twenty-Six Dials · bitwick