a یا an؟ تشخیصش با کد سختتر از اون چیزیه که فکر میکنی
خلاصهٔ کاملتر
نویسنده (از Red Blob Games) برای تولید متن رویهای (procedural) یه تابع a_or_an میخواست. اول به نظر ساده میاد: اگه حرف اول صدادار بود an بذار. ولی قانون واقعی روی صدای اول کلمهست، نه حرف نوشتهشده. برای همین میگیم a unicorn (چون «یونیکورن» با صدای صامت شروع میشه) و an hour (چون h خونده نمیشه).
برای اینکه ببینه قانون «حرف اول» چقدر خطا داره، دیکشنری تلفظ cmudict رو دانلود کرد و مقایسه کرد. کلی مورد ناجور پیدا شد، پس چند دسته رو کنار گذاشت: اسمهای خاص (۳۱۳۳ مورد، مثل nvidia)، حروف تکی، تلفظهای دوم (مثل herb که تو انگلیسی آمریکایی و بریتانیایی فرق داره)، کلمههای دارای علامت مثل don't، اختصارها و کلمههایی که تو دیکشنری BSD نبودن. آخرش ۳۲۴۵۵ کلمه موند.
نتیجه این بود که استثناها کمان و چند الگوی مشخص دارن: کلمههایی که با eu، uni، us یا ur شروع میشن صدای «یو» دارن و a میگیرن؛ one و once با صدای «و» شروع میشن؛ و hour، honest، heir و honor هم h بیصدا دارن. نویسنده امیدوار بود با چیزی شبیه minimize کردن DFA (یعنی کوچیکترین ماشین حالتی که همین تصمیم رو بگیره) یه درخت تصمیم کوتاه دربیاره، ولی موفق نشد و قانونها رو دستی نوشت. این یه تیکهی کوتاهشده از کدشه:
VOWELS = "aeiou"
def starts_with_vowel(word):
if word.startswith("eu"): return False
if word.startswith("hour"): return True
if word.startswith("one") and not word.startswith("onerous"): return False
return word[0] in VOWELSنویسنده سراغ استثنای قدیمی «an hospital» نرفته و توضیح میده که این از گویشهایی اومده که h رو تلفظ نمیکردن. یه نکتهی جالب هم آورده: کلمهی apron در اصل napron بوده و چون مردم «a napron» رو «an apron» شنیدن، n از اول کلمه افتاد. برای کارهای بعدی هم میخواد trie رو بهتر فشرده کنه و فراوانی استفادهی کلمهها رو هم حساب کنه.
نکات کلیدی:
- قانون a/an به صدای اول کلمه بستگی داره، نه حرف اول: a unicorn ولی an hour.
- از دیکشنری تلفظ cmudict استفاده شده و بعد از حذف اسمها و موارد خاص، ۳۲۴۵۵ کلمه بررسی شده.
- بیشتر استثناها با eu، ew، uni، us، ur، one و h بیصدا (hour، honest، heir) شروع میشن.
- راهحل نهایی حدود ۲۰ قانون دستی با startswith تو Python هست، نه یه الگوریتم خودکار.
- herb تو انگلیسی آمریکایی و بریتانیایی تلفظ متفاوت داره و جواب a/an براش فرق میکنه.




