Exercise 2 solution import re from collections import Counter tw = re.compile(r"(?P\d+)|(?P[a-z]+)|(?P\s+)|(?P.)") s = "go 12 steps, then 7 more!" print([(m.lastgroup, m.group()) for m in tw.finditer(s) if m.lastgroup != "SP"]) # [('WORD', 'go'), ('INT', '12'), ('WORD', 'steps'), ('X', ','), ('WORD', 'then'), ('INT', '7'), ('WORD', 'more'), ('X', '!')] print(Counter(m.lastgroup for m in tw.finditer(s))) # Counter({'SP': 5, 'WORD': 4, 'INT': 2, 'X': 2}) (All lines were run and printed exactly what is shown.) Explanation: each alternative is its own named group, so m.lastgroup is the kind of token. The catch-all X comes last so that it only matches characters no earlier alternative wanted. The spaces are filtered out of the list but are still counted in the Counter, because that counts every match.