Hone logo
Hone
Problems

Type-Level Regular Expression Engine in TypeScript

This challenge asks you to build a rudimentary regular expression engine operating entirely at the TypeScript type level. Type-level programming allows us to perform computations and validations during compile time, leading to more robust and safer code. This exercise will explore how to leverage TypeScript's advanced type system to achieve this.

Problem Description

You are tasked with creating a type-level regular expression engine that can match a given string against a simple pattern. The pattern will consist of literal characters and the . wildcard, which matches any single character. The engine should return a type representing whether the pattern matches the input string. If the pattern matches, the engine should return true. If the pattern does not match, it should return false.

Key Requirements:

  • Pattern Representation: The pattern will be represented as a tuple of strings (e.g., ["a", "b", ".", "c"]).
  • Input String Representation: The input string will be represented as a tuple of strings of length 1 (e.g., ["a"], ["b"], ["c"]).
  • Matching Logic: The engine should compare the pattern against the input string character by character. The . wildcard should match any single character in the input string.
  • Return Type: The engine should return a conditional type that evaluates to true or false based on whether the pattern matches the input string.

Expected Behavior:

The engine should return true if the pattern matches the entire input string. It should return false otherwise. The engine should handle empty patterns and empty input strings gracefully.

Edge Cases to Consider:

  • Empty pattern: Should match an empty input string.
  • Empty input string: Should only match an empty pattern.
  • Pattern longer than input string: Should not match.
  • Pattern shorter than input string: Should not match (unless the pattern contains wildcards).
  • Wildcard usage: Ensure the wildcard . correctly matches any single character.

Examples

Example 1:

Input: pattern = ["a", "b", "c"], string = ["a", "b", "c"]
Output: true
Explanation: The pattern "abc" matches the string "abc" exactly.

Example 2:

Input: pattern = ["a", ".", "c"], string = ["a", "b", "c"]
Output: true
Explanation: The pattern "a.c" matches the string "abc" because "." matches "b".

Example 3:

Input: pattern = ["a", "b", "d"], string = ["a", "b", "c"]
Output: false
Explanation: The pattern "abd" does not match the string "abc" because "d" does not match "c".

Example 4:

Input: pattern = [], string = []
Output: true
Explanation: An empty pattern matches an empty string.

Example 5:

Input: pattern = ["a"], string = []
Output: false
Explanation: A non-empty pattern does not match an empty string.

Constraints

  • The pattern and string will be represented as tuples of strings of length 1.
  • The pattern will only contain literal characters and the . wildcard.
  • The input string will only contain single-character strings.
  • The engine should be implemented using TypeScript's type system, without runtime execution.
  • The length of the pattern and string should not exceed 100 characters. (This is a practical consideration for type complexity, though not strictly enforced).

Notes

  • Consider using conditional types and recursion to implement the matching logic.
  • Think about how to handle the base cases (empty pattern, empty string, pattern exhausted, string exhausted).
  • The infer keyword can be helpful for extracting types from tuples.
  • This is a challenging problem that requires a good understanding of TypeScript's advanced type system. Start with simpler cases and gradually build up the complexity. Focus on correctness first, then consider type complexity.
Loading editor...
typescript