תרגול מסכם: רשימות#
מימוש “בעית ניו-זילנד”#
כעת נראה כיצד לממש את הפתרון ל”בעית ניו-זילנד” בפייתון:
לנוחיותכם חלונית עם הקוד שראינו בסרטון. מוזמנים להריץ בעצמכם:
start = 10000
spend_lst = [1200, 900, 354, 1300, 550, 620, 550, 715]
total = sum(spend_lst)
print("Total:", total)
money_left = start - total
print("You have", money_left, "dollars")
average = total / len(spend_lst)
print("The average per week:", average)
weeks_left = money_left / average
print("You have approx.", weeks_left, "weeks left to travel")
Total: 6189
You have 3811 dollars
The average per week: 773.625
You have approx. 4.926159314913557 weeks left to travel
בחנו את עצמכם
בקוד שלפניכם מופיעה הרשימה grades ובה ציוני סטודנטים בקורס מסוים. אנחנו רוצים לבדוק האם יש תלמיד שציונו בקורס שווה בדיוק לממוצע הציונים (במילים אחרות - האם ממוצע הציונים מופיע ברשימה grades). עליכם לכתוב קוד שמבצע את הבדיקה הזו ומדפיס את התוצאה למסך.
הנחיות:
תחילה חשבו את סכום כל הציונים ושמרו אותו במשתנה כלשהו (תנו למשתנה זה שם כרצונכם).
חשבו את אורך הרשימה ושמרו אותו במשתנה נוסף.
חשבו את ממוצע הציונים (ע”י חלוקת סכום הציונים באורך הרשימה, כלומר, חלוקת שני המשתנים שיצרתם בסעיפים הקודמים), וגם אותו שמרו במשתנה שלישי.
לבסוף, אם הממוצע נמצא ברשימה - הדפיסו
True, ואם לא - הדפיסוFalse. תזכורת - הביטויx in Lמשוערך ל-Trueאם האיברxנמצא ברשימהL, ול-Falseאם לא).
כפי שודאי הבחנתם, זוהי גרסה מעט פשוטה יותר של “בעיית ניו זילנד” שאותה זה עתה ראינו, כך שיש לכם את כל הכלים לפתרון תרגיל זה.
לאחר שסיימתם לכתוב את הקוד, הריצו אותו (על ידי לחיצה על Run) ובדקו בחלונית הפלט האם הפתרון שלכם עובד או לא. שנו את רשימת הקלט grades כמה פעמים (לרשימות עם מספר ערכים כרצונכם) וראו אם הפתרון שלכם עובד עם כל הרשימות שאתם בודקים.
# Change this list - try different inputs
grades = [81, 70, 75, 96, 99, 100, 87, 80, 100]
# Write your solution here:
לחצו כאן כדי לצפות בפתרון
# Change this list - try different inputs
grades = [81, 70, 75, 96, 99, 100, 87, 80, 100]
print("Testing the following grades list:", grades)
print("**************************************")
# DO NOT CHANGE THIS LINE:
print("Your solution: ", end="")
# First, we compute the sum of the grades in the list
total = sum(grades)
# Next, we compute the length of the list
length = len(grades)
# Then, we compute the average value of the list
avg = total / length
# We can now check whether the average is in the list
result = avg in grades
# And finally, we can print the result we got
print(result)
העמקה בפתרון
נציג שוב את המטלה שלפנינו: בהינתן רשימה grades ובה ציוני סטודנטים בקורס מסוים, אנחנו רוצים לבדוק האם יש תלמיד שציונו בקורס שווה בדיוק לממוצע הציונים (במילים אחרות - האם ממוצע הציונים מופיע ברשימה grades).
בנוסף לתרגיל, קיבלנו גם הנחיות לפתרון – סדרת פעולות שאותה עלינו לבצע שלב-אחר-שלב כדי לפתור את התרגיל. כדי להבין את ההיגיון שמאחורי ההנחיות שקיבלנו, בואו ננסה לנסח פתרון משלנו לתרגיל.
נניח שמישהו היה מספר לנו שממוצע הרשימה grades הוא avg. במצב כזה היינו יכולים לפתור בקלות את הבעיה. אנחנו יודעים שעבור רשימה L ומשתנה x הביטוי x in L משוערך ל-True אם x ברשימה L ול-False אחרת, ולכן, אם היינו מבצעים את ההשמה:
result = avg in grades
ולאחר מכן היינו מדפיסים את המשתנה result ומקבלים את התוצאה המבוקשת.
הבעיה, כמובן, היא שאף אחד לא מספר לנו מהו ממוצע הרשימה ואנחנו צריכים לחשב אותו בעצמנו. אפשר לתאר כרגע את מצבנו באופן הבא: “אם נדע מהו ממוצע הרשימה, נדע כיצד לפתור את הבעיה”. אז מה אנחנו צריכים לעשות כדי לחשב את ממוצע הרשימה?
אנחנו יודעים כבר מה היא ההגדרה של ממוצע הרשימה – זהו הערך שמתקבל כשלוקחים את סכום הערכים ברשימה ומחלקים אותו במספר האיברים שברשימה. לכן, אם מישהו היה מספר לנו שסכום הערכים ברשימה הוא total ושאורך הרשימה הוא length, היינו יכולים לחשב בקלות את ממוצע הרשימה:
avg = total / length
וכמו שכבר אמרנו, ברגע שממוצע הרשימה בידינו, אנחנו יודעים איך להגיע לתוצאה המבוקשת.
אך שוב, הבעיה היא שאף אחד לא מספר לנו מהו סכום הערכים ברשימה ומהו אורכה. את מצבנו הנוכחי ניתן לתאר אם כך באופן הבא: “אם נדע מהו סכום הערכים ברשימה ומהו אורכה, נדע כיצד לפתור את הבעיה”. אז מה נשאר לנו לעשות?
כשפתרנו את בעיית ניו זילנד ראינו איך לחשב את סכום הערכים ברשימה:
total = sum(grades)
וראינו גם כיצד לחשב את אורך הרשימה:
length = len(grades)
ולכן, כיוון שיש בידינו כעת את סכום הערכים ברשימה ואת אורכה, אנחנו יכולים לחשב את ממוצע הרשימה ולבדוק האם הוא מופיע ברשימה.
בואו נשווה את התהליך שעשינו להנחיות שקיבלנו לפתרון הבעיה:
תחילה חשבו את סכום כל הציונים ושמרו אותו במשתנה כלשהו (תנו למשתנה זה שם כרצונכם).
חשבו את אורך הרשימה ושמרו אותו במשתנה נוסף.
חשבו את ממוצע הציונים (ע”י חלוקת סכום הציונים באורך הרשימה, כלומר, חלוקת שני המשתנים שיצרתם בסעיפים הקודמים), וגם אותו שמרו במשתנה שלישי.
לבסוף, אם הממוצע נמצא ברשימה - הדפיסו True, ואם לא - הדפיסו False. תזכורת - הביטוי x in L משוערך ל-True אם האיבר x נמצא ברשימה L (ול-False אם לא). שמים לב מה קרה? התהליך שביצענו נתן לנו סדרת צעדים זהה להנחיות, אך בסדר הפוך. הסיבה לכך היא שהתהליך שביצענו זה עתה לתיאור פתרון לבעיה התנהל באופן הבא:
ראשית, תיארנו את הבעיה שברצוננו לפתור (בדיקת המצאות של ממוצע הרשימה ברשימה)
פירקנו את הבעיה לתת-בעיות קטנות יותר (חישוב ממוצע הרשימה)
פירקנו את תתי הבעיות שלנו לבעיות קטנות יותר (חישוב סכום הערכים ברשימה, חישוב אורך הרשימה)
פתרנו את הבעיות הקטנות ביותר שלנו והרכבנו מהן בחזרה פתרון לבעיה המרכזית שלנו (חשב את הממוצע על ידי חלוקה של סכום הרשימה באורכה ולאחר מכן בדוק האם איבר זה ברשימה)
גישה זו נקראת גישת “מעלה-מטה” (באנגלית: top-down approach). היא מתחילה “מלמעלה” על ידי תיאור הבעיה הגדולה שלנו ויורדת “למטה” לתיאור בעיות קטנות יותר מהן ניתן להרכיב פתרון לבעיה הגדולה. הסתכלות בתצורת מעלה-מטה יכולה לעזור לנו להבין מהם התהליכים המרכזיים אותם עלינו לבצע כדי לפתור את בעיה מסוימת.
לאחר שניסחנו פתרון בתצורת מעלה-מטה, אנחנו יכולים לקחת את סדרת הפעולות שקיבלנו ולבחון אותן בסדר הפוך, מהקטן לגדול. גישה זו נקראת, כמובן, גישת “מטה-מעלה” (bottom-up approach). כשנרצה לתרגם את ההנחיות שניסחנו לקוד, ניישם אותן בתצורת מטה-מעלה, שכן עלינו לפתור ראשית את הבעיות הקטנות (כמו חישוב סכום הרשימה ואורכה) על מנת להשתמש בהן לפתור את הבעיות הגדולות (כמו חישוב ממוצע הרשימה ובדיקת המצאות שלו ברשימה).