Constraint Solver with Jest Testing
This challenge asks you to implement a simple constraint solver in TypeScript and thoroughly test it using Jest. Constraint solvers are useful for solving problems where you have a set of variables and relationships (constraints) between them, and you need to find values for the variables that satisfy all the constraints. This exercise will focus on integer constraints and basic equality/inequality relationships.
Problem Description
You need to create a ConstraintSolver class in TypeScript that can handle integer variables and constraints of the form x == y or x != y, where x and y are variable names (strings). The solver should determine if a solution exists that satisfies all constraints, and if so, return a possible assignment of values to the variables. If no solution exists, it should return null.
Key Requirements:
- Variable Management: The solver should be able to add variables (strings) and assign integer values to them.
- Constraint Handling: The solver should be able to add constraints of the form
x == yorx != y, wherexandyare variable names. - Solution Finding: The solver should attempt to find a solution that satisfies all constraints. A simple backtracking approach is acceptable for this problem.
- No Solution Indication: If no solution exists, the solver should return
null. - Integer Constraints Only: The solver should only handle integer constraints.
- Variable Names as Strings: Variable names must be strings.
Expected Behavior:
- When a solution is found, the solver should return an object where keys are variable names and values are integer assignments.
- When no solution is found, the solver should return
null. - Adding a constraint should not modify the existing variable assignments.
- The solver should handle cases where variables are not initialized before being used in a constraint.
Edge Cases to Consider:
- Empty constraint set (no constraints).
- Conflicting constraints (e.g.,
x == yandx != y). - Variables used in constraints before being added to the solver.
- Constraints involving the same variable (e.g.,
x == x). - Large number of variables and constraints (though performance is not a primary focus, avoid extremely inefficient algorithms).
Examples
Example 1:
Input:
solver.addVariable("x");
solver.addVariable("y");
solver.addConstraint("x", "y", "==");
solver.solve();
Output:
{ x: 1, y: 1 }
Explanation: Any assignment where x and y have the same value is a valid solution.
Example 2:
Input:
solver.addVariable("x");
solver.addVariable("y");
solver.addVariable("z");
solver.addConstraint("x", "y", "==");
solver.addConstraint("y", "z", "==");
solver.solve();
Output:
{ x: 1, y: 1, z: 1 }
Explanation: Any assignment where x, y, and z all have the same value is a valid solution.
Example 3:
Input:
solver.addVariable("x");
solver.addVariable("y");
solver.addConstraint("x", "y", "==");
solver.addConstraint("x", "y", "!=");
solver.solve();
Output:
null
Explanation: The constraints are contradictory, so no solution exists.
Constraints
- Variable names must be strings.
- Constraint values must be integers.
- The solver should be able to handle up to 10 variables and 20 constraints without significant performance degradation (though optimization is not the primary goal).
- The solver should return a solution within a reasonable time (e.g., less than 1 second) for typical input sizes.
Notes
- You can use a backtracking algorithm to explore possible solutions.
- Consider using a data structure (e.g., a map or object) to store variable assignments.
- The
addConstraintmethod should take three arguments: variable1, variable2, and operator (either "==" or "!="). - Focus on correctness and clarity of code. Testing is crucial.
- You are expected to write comprehensive Jest tests to cover various scenarios, including edge cases and conflicting constraints. Aim for high test coverage.
- The
solve()method should return either a solution object ornull. - Assume that the input operator will always be either "==" or "!=". No need to handle invalid operators.