תרגיל Python ל-Log Puzzle

בתרגיל Log Puzzle, משתמשים בקוד Python כדי לפתור שתי חידות. בתרגיל הזה נעשה שימוש במודול urllib, כפי שמוצג בקטע Python Utilities. הקבצים של תרגיל זה נמצאים בספרייה "logpuzzle" בתוך google-python-exercises (הורד את google-python-exercises.zip אם עדיין לא עשית זאת, לקבלת פרטים, עיין בהגדרה). הוסף את הקוד שלך לקובץ "logpuzzle.py".

תמונה של בעל חיים פוצלה לתמונות רבות עם פסים צרים ומאונכים. תמונות הפס מופיעות באינטרנט במקום כלשהו, ולכל אחת מהן כתובת URL משלה. כתובות ה-URL מוסתרות בקובץ יומן של שרת האינטרנט. המשימה היא למצוא את כתובות ה-URL ולהוריד את כל פסי התמונה כדי ליצור מחדש את התמונה המקורית.

כתובות ה-URL של הפרוסות מוסתרות בתוך קובצי היומן של Apache (שרת האינטרנט apache של הקוד הפתוח הוא השרת הנפוץ ביותר באינטרנט). כל קובץ יומן מגיע משרת כלשהו, וכתובות ה-URL לפרוסות הרצויות מוסתרות בתוך היומנים. קובץ היומן מקודד את השרת שממנו הוא מגיע, באופן הבא: קובץ היומן animal_code.google.com מגיע מהשרת code.google.com (פורמלית, נניח ששם השרת הוא כל מה שמופיע בסרגל התחתון הראשון). קובץ היומן animal_code.google.com מכיל את הנתונים לתמונת החידה 'בעל חיים'. למרות שלנתונים בקובצי היומן יש תחביר של שרת אינטרנט אמיתי של Pache, הנתונים שמעבר לאלה שדרושים לחידה הם נתונים אקראיים מקובץ יומן אמיתי.

כך נראית שורה יחידה בקובץ היומן (כך נראים קובצי היומן של Apache):

10.254.254.28 - - [06/Aug/2007:00:14:08 -0700] "GET /foo/talks/ HTTP/1.1"
200 5910 "-" "Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4"

המספרים הראשונים הם הכתובת של הדפדפן המבקש. החלק המעניין ביותר הוא "HTTP נתיב" HTTP" שמציג את הנתיב של בקשת אינטרנט שהתקבלה על ידי השרת. הנתיב עצמו אף פעם לא מכיל רווחים, והוא מופרד מה-GET ומה-HTTP באמצעות רווחים (הצעה לביטוי רגולרי: \S (באותיות רישיות S) תואמת לכל תו שאינו רווח). מצא את השורות ביומן שבהן מופיעה המחרוזת "חידה" בתוך הנתיב, תוך התעלמות משורות רבות אחרות שביומן.

חלק א' - רישום קובץ ביומן לכתובות אתרים

משלימים את הפונקציה read_urls(filename) שמחלצת את כתובות ה-URL של החידה מתוך קובץ יומן. קובץ היומן כולל את כל כתובות ה-URL של נתיב "החשיבה". משלבים את הנתיב מכל כתובת URL עם שם השרת משם הקובץ כדי ליצור כתובת URL מלאה, לדוגמה "http://www.example.com/path/puzzle/from/inside/file". מומלץ לסנן כתובות URL שמופיעות יותר מפעם אחת. הפונקציה read_urls() אמורה להחזיר רשימה של כתובות URL מלאות, ממוינות בסדר אלפביתי וללא כפילויות. אם תבוצע העברה של כתובות האתר בסדר אלפביתי, תופק פרוסות התמונה בסדר הנכון משמאל לימין כדי ליצור מחדש את תמונת בעל החיים המקורית. במקרה הפשוט ביותר, ה-main() אמורה להדפיס את כתובות ה-URL, אחת בכל שורה.

$ ./logpuzzle.py animal_code.google.com
http://code.google.com/something/puzzle-animal-baaa.jpg
http://code.google.com/something/puzzle-animal-baab.jpg
...

חלק ב – הורדת פאזל של תמונות

משלימים את הפונקציה download_images() , שמקבלת רשימה ממוינת של כתובות URL וספרייה. אם צריך, מורידים את התמונה מכל כתובת URL לספרייה הנתונה ויוצרים את הספרייה קודם (אם צריך) תן שם לקובצי התמונות המקומיים עם סכמה פשוטה, כגון "img0", "img1", "img2" וכן הלאה. כדאי להדפיס שורת פלט קטנה מהסטטוס "מאחזר..." בזמן הורדת כל תמונה מכיוון שהיא יכולה להיות איטית ונחמד לראות שהתוכנית פועלת. כל תמונה היא קטע אנכי קטן מהמקור. איך מחברים את הפרוסות כדי ליצור מחדש את הגרסה המקורית? אפשר לפתור אותה בעזרת html קטן (לא נדרש ידע ב-HTML).

הפונקציה download_images() צריכה גם ליצור קובץ index.html בספרייה עם תג *img* כדי להציג כל קובץ תמונה מקומי. כל תגי ה-img צריכים להופיע בשורה אחת, ללא הפרדה. באופן כזה, הדפדפן מציג את כל החלקים השונים ביחד בצורה חלקה. אין צורך בידע ב-HTML כדי לעשות זאת. לשם כך, פשוט יוצרים קובץ index.html שנראה כך:

<html>
<body>
<img src="img0"><img src="img1"><img src="img2">...
</body>
</html>

כך זה אמור להיראות אחרי שמורידים את החידה של בעל החיים:

$ ./logpuzzle.py --todir animaldir animal_code.google.com
$ ls animaldir
img0  img1  img2  img3  img4  img5  img6  img7  img8  img9  index.html

כשהכול פועל, פתיחת ה-index.html בדפדפן אמורה לחשוף את התמונה המקורית של בעל החיים. איזו חיה מוצגת בתמונה?

חלק ג' – ביטול ערבול של פרוסת תמונה

החידה השנייה כוללת תמונה של מקום מפורסם מאוד, אבל היא תלויה במיון מותאם אישית. לחידה הראשונה, אפשר למיין את כתובות ה-URL לפי סדר אלפביתי כדי שהתמונות יופיעו כמו שצריך. במיון, נעשה שימוש בכתובת ה-URL כולה. לעומת זאת, נניח שאם כתובת ה-URL מסתיימת בדפוס "-wordchars-wordchars.jpg", למשל "http://example.com/foo/puzzle/bar-abab-baaa.jpg", כתובת ה-URL צריכה להיות מיוצגת על ידי המילה השנייה שבמיון (למשל "baaa"). לכן מיון רשימה של כתובות אתרים שכל אחת מהן מסתיימת בתבנית word-word.jpg צריך לסדר את כתובות האתרים לפי המילה השנייה.

הרחב את הקוד שלך כדי לסדר כתובות אתרים כאלה כראוי, ואז תוכל לפענח את הפאזל הבא שבו נאמר מקום_code.google.com. איזה מקום מוצג בה?

ייחוס CC: התמונות המשמשות בפאזל הזה זמינות על ידי בעליהם במסגרת רישיון Creative Commons Attribution 2.5, המעודד בנדיבות רמיקסים של התוכן, כמו התמונה הזו. תמונת בעל החיים היא מהמשתמש zappowbang ב-fLinkr ותמונת המקום היא מפיצול המשתמש הבוליאני ב-fliker.