prize18-9 Exercise 2: Reserved Names ===================================== Predictions: the naive check (exact match) catches only "admin". The key (NFKC, casefold, drop category Cf) should also catch "ADMIN", the fullwidth spelling, the trailing zero-width space, the soft hyphen in the middle and the zero-width space inside "root" (soft hyphen and zero-width space are both category Cf). It will not catch "administrator" (a different word, correctly allowed) or the Cyrillic-o "root": that is a look-alike letter, not an equivalent one. ex2.py: import unicodedata as ud def key(name): n = ud.normalize("NFKC", name).casefold() return "".join(c for c in n if ud.category(c) != "Cf") reserved = {"admin", "root"} tests = ["admin", "ADMIN", "\uff41\uff44\uff4d\uff49\uff4e", "admin\u200b", "ad\u00admin", "ro\u200bot", "administrator", "r\u043eot"] for t in tests: print(f"{ascii(t):36} naive={t in reserved!s:5} checked={key(t) in reserved}") Real output (Python 3.14): 'admin' naive=True checked=True 'ADMIN' naive=False checked=True '\uff41\uff44\uff4d\uff49\uff4e' naive=False checked=True 'admin\u200b' naive=False checked=True 'ad\xadmin' naive=False checked=True 'ro\u200bot' naive=False checked=True 'administrator' naive=False checked=False 'r\u043eot' naive=False checked=False All as predicted. The last row shows what normalization cannot do: the Cyrillic o is a different letter. Catching it needs a script check (Exercise 1) or a confusable skeleton, or restricting the field to ASCII. Real systems often combine all three.