• בלוג
  • היום למדתי - לא כזה פשוט לחפש מהסוף בביטוי רגולארי

היום למדתי - לא כזה פשוט לחפש מהסוף בביטוי רגולארי

02/12/2023

התחיל היום Advent Of Code ואומנם אני כנראה לא אצליח לפתור את כל החידות שלו השנה על היום הראשון אי אפשר לוותר. בחידה היומית היה צריך למצוא דברים בתוך טקסטים. לא כזה מסובך עד שנתקלים בטריק הקטן שמקלקל הכל.

1. התרגיל והטריק

הסיפור בגדול היה למצוא ספרות בתוך שורת טקסט, כשהספרות יכולות להופיע בתור ספרות ממש כמו 4, 9 או 2 או בתור שם הספרה כמו four, nine או two. אנחנו צריכים למצוא בהינתן שורת טקסט את הסיפרה הראשונה והסיפרה האחרונה בה. למשל בשורה:

24

הסיפרה הראשונה היא 2 והאחרונה היא 4.

בשורה:

abc7d

הסיפרה 7 היא גם הסיפרה הראשונה וגם האחרונה.

ובשורה:

eightwo

הסיפרה 8 היא הראשונה ו 2 היא האחרונה.

2. ניסוי 1 - חיפוש כל המופעים

רעיון ראשון שאפשר לנסות כדי למצוא את הסיפרה הראשונה והאחרונה הוא חיפוש גלובאלי, בפייתון זה יהיה:

>>> digits = [str(i) for i in range(10)] + ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine"]

>>> digits_r = '|'.join(digits)

>>> re.findall(digits_r, "1abc3")
['1', '3']

וזה עובד עד שזה מפסיק לעבוד:

>>> re.findall(digitsr, "eightwo")
['eight']

כי הבעיה שה t משותף גם ל eight וגם ל two ומנוע הביטויים הרגולאריים כבר איבד את ה t כשהוא מצא את eight.

3. פיתרון - חיפוש הפוך

בהיעדר דרך טובה לחפש מהסוף בביטוי רגולארי נדרשת יצירתיות - למשל להפוך את כל הטקסטים לפני החיפוש ואז להפוך חזרה אחרי שמוצאים כדי לדעת איזו סיפרה מצאנו. בפייתון זה קל:

>>> digits_re = '|'.join([d[::-1] for d in digits])
>>> [r[::-1] for r in re.findall(digits_re, "eightwo"[::-1])]
['two']