codejump
HardPro challengePythonJavaScriptTypeScript

State Machine with Guards

State MachinesPatterns

Extend a finite state machine with guards: a transition only fires if its guard predicate accepts the current context.

Config: { initial, transitions: { [state]: { [event]: { target, guard? } } } }.

guard is the name of a predicate in the GUARDS table provided by the starter code, e.g. 'canGo' → (ctx) => ctx.canGo === true.

solve(config, events, context) returns the list of states: the initial state, then the state after each event.

  • No transition for (state, event) → the machine stays put.
  • A transition whose guard returns false → the machine stays put.
solve(
  { initial: 'locked', transitions: { locked: { key: { target: 'unlocked', guard: 'hasKey' } } } },
  ['key'],
  { hasKey: false },
)
// → ['locked', 'locked']

Sample tests

Test #1round trip
Input: [{"initial":"idle","transitions":{"idle":{"start":{"target":"running"}},"running":{"stop":{"target":"idle"}}}},["start","stop"],{}]
Output: ["idle","running","idle"]
Test #2unguarded transition fires
Input: [{"initial":"a","transitions":{"a":{"go":{"target":"b"}}}},["go"],{}]
Output: ["a","b"]
Test #3passing guard lets the transition fire
Input: [{"initial":"a","transitions":{"a":{"go":{"guard":"canGo","target":"b"}}}},["go"],{"canGo":true}]
Output: ["a","b"]
Test #4failing guard blocks the transition
Input: [{"initial":"a","transitions":{"a":{"go":{"guard":"canGo","target":"b"}}}},["go"],{"canGo":false}]
Output: ["a","a"]
Test #5unknown event leaves the state unchanged
Input: [{"initial":"idle","transitions":{"idle":{"start":{"target":"running"}}}},["unknown"],{}]
Output: ["idle","idle"]
Test #6transitions chain
Input: [{"initial":"a","transitions":{"a":{"go":{"target":"b"}},"b":{"go":{"target":"c"}}}},["go","go"],{}]
Output: ["a","b","c"]