At Acme Mobile, different app layers emit inconsistent error strings for the same failure. Implement a reusable error normalization function that groups similar raw error messages under a canonical error key.
Write a function group_errors(errors, rules) that takes a list of raw error strings and a list of normalization rules. Each rule is a pair [pattern, canonical]. For every error string, first normalize it by converting to lowercase and replacing every maximal sequence of digits with #. Then, if the normalized string contains one or more rule patterns, assign the error to the canonical value of the longest matching pattern. If no pattern matches, use the normalized string itself as the key. Return a dictionary mapping each final key to its frequency.
errors: list of stringsrules: list of [pattern, canonical] string pairsExample 1
errors = ["Timeout after 30 seconds", "timeout after 45 seconds"], rules = [["timeout after # seconds", "TIMEOUT"]]{"TIMEOUT": 2}Example 2
errors = ["HTTP 500 on /feed", "HTTP 404 on /feed"], rules = [["http #", "HTTP_ERROR"]]{"HTTP_ERROR": 2}#, so both messages match the same rule.1 <= len(errors) <= 10^40 <= len(rules) <= 10^31 <= len(error) <= 2001 <= len(pattern), len(canonical) <= 200