<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 <img src="images/logo.jpg" style="display
Step1:  <p style="text-align
Step2:  <p style="text-align
Step3:  <p style="text-align
Step4:  <p style="text-align
Step5:  <p style="text-align
Step6:  <p style="text-align
Step7:  <p style="text-align
Step8:  <p style="text-align
Step9:  <p style="text-align
Step10:  <p style="text-align
Step11:  <span style="text-align
Step12:  <p style="text-align
Step13:  <p style="text-align
Step14:  <p style="text-align
Step15:  <p style="text-align
Step16:  <p style="text-align
Step17:  <p style="text-align
Step18:  <p style="text-align
Step19:  <p style="text-align
Step20:  <p style="text-align
Step21:  <div class="align-center" style="display
<ASSISTANT_TASK:>
Python Code:
print(9876543)
Explanation: <img src="images/logo.jpg" style="display: block; margin-left: auto; margin-right: auto;" alt="לוגו של מיזם לימוד הפייתון. נחש מצויר בצבעי צהוב וכחול, הנע בין האותיות של שם הקורס: לומדים פייתון. הסלוגן המופיע מעל לשם הקורס הוא מיזם חינמי ללימוד תכנות בעברית.">
<span style="text-align: right; direction: rtl; float: right;">Mutability</span>
<span style="text-align: right; direction: rtl; float: right; clear: both;">הגדרה</span>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
המילה <dfn>Mutable</dfn> נגזרת מהמילה <em>Mutate</em>, והמשמעות שלה היא "<em>משהו בר־שינוי</em>".<br>
אנחנו נשתמש בה כדי לתאר טיפוסי נתונים שניתן לשנותם, למשל להוסיף או להחסיר מהם איברים.<br>
משמעות המילה <dfn>Immutable</dfn> היא "<em>משהו שאינו בר־שינוי</em>", נתון שאמור להישאר קבוע אחרי יצירתו.<br>
שינוי ערך שהוא Immutable משנה את המהות שלו, ויגרום לו להיחשב ערך אחר לגמרי.
</p>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
נדמיין ארנק שבתוכו שטרות – ניתן להוסיף אליו שטרות או להוציא ממנו שטרות, אבל הארנק יישאר אותו ארנק.<br>
כיוון שניתן לשנות את המצב של הארנק בלי לפגוע במהות שלו, ניתן להגיד שארנק הוא Mutable.<br>
לעומת זאת, אם אקח את אחד השטרות שנמצאים בתוך הארנק, לא אוכל לשנות בו משהו בלי שאשנה את המהות שלו.<br>
שינוי באחד המאפיינים של השטר, כמו המספר שכתוב עליו, יגרור שינוי מהותי שיהפוך אותו לדבר אחר לחלוטין.<br>
ניתן להגיד שהשטר הוא Immutable, בלתי ניתן לשינוי.
</p>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
הערכים ה־Mutable שנכיר בקורס הם מעין "מכולות" שמכילות ערכים אחרים.<br>
כרגע אנו מכירים סוג ערך אחד שהוא Mutable – רשימה.
</p>
<span style="text-align: right; direction: rtl; float: right; clear: both;">כתובות של ערכים</span>
<span style="text-align: right; direction: rtl; float: right;">ערכים</span>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
כדי להבין טוב יותר את הנושא, נעצור לרגע כדי להבין איך ערכים עובדים מאחורי הקלעים בפייתון.
</p>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
כשאנחנו יוצרים ערך כלשהו, פייתון מקצה עבורו מקום בזיכרון המחשב ושומרת שם את הערך.<br>
מאותו רגע לאותו ערך יש כתובת, שהיא מספר שמייצג את המקום שבו אותו ערך נמצא בזיכרון המחשב.<br>
כתובת הערך נשארת זהה מרגע שהוא נוצר ועד סוף חייו.
</p>
End of explanation
name = 12345
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
בשורה למעלה הגדרנו את הערך 9,876,543.<br>
אף על פי שלא עשינו עליו פעולה מתוחכמת ולא שמרנו אותו במשתנה, פייתון תשמור את הערך הזה בזיכרון המחשב.<br>
לערך 9,876,543 יש כתובת עכשיו.
</p>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
בשורה הבאה "נקשור" את השם <var>name</var> לכתובת של הערך המספרי 12,345.<br>
המשתנה <var>name</var> לא באמת "מכיל" את הערך 12,345, אלא רק מצביע על הכתובת שבה הערך 12,345 מאוחסן.
</p>
End of explanation
number = 100000
print("ID before: " + str(id(number)))
number = 123456
print("ID after: " + str(id(number)))
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
<mark>כשאנחנו מבצעים השמה, אנחנו יוצרים קישור בין שם המשתנה לבין הכתובת של הערך שהשמנו לתוכו.</mark>
</p>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
אם ניזכר בדימוי הלייזר מהשיעורים הקודמים, עבור כל פעולת השמה בתוכנית, פייתון: 
</p>
<ol style="text-align: right; direction: rtl; float: right; clear: both;">
    <li>תיצור מצביע לייזר <em>חדש</em> שעליו מודבק שם המשתנה.</li>
    <li>תגרום ללייזר להצביע על המקום בזיכרון שבו מאוחסן הערך המדובר.</li>
</ol>
<span style="text-align: right; direction: rtl; float: right;">בדיקת כתובת של ערכים</span>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
הפונקציה <code dir="ltr" style="direction: ltr;">id</code> מקבלת כארגומנט ערך, ומחזירה מספר שמייצג את הכתובת שלו – המיקום של הערך בזיכרון.<br>
בהקבלה למטאפורת הלייזר, היא מקבלת את ראש הלייזר ומראה לנו לאן הוא מצביע.<br>
נראה דוגמה:
</p>
End of explanation
number = 100000
print("ID before: " + str(id(number)))
number = number + 1
print("ID after: " + str(id(number)))
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
בדוגמה האחרונה ניתן לראות ששם המשתנה לא משפיע על המיקום שבו הערכים נשמרים.<br>
לערכים שונים מוקצות כתובות שונות.
</p>
End of explanation
print(f"ID of number ({number}): " + str(id(number)))
number2 = 100001
print(f"ID of number2 ({number2}): " + str(id(number2)))
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
בדוגמה הגדלנו את ערך המשתנה <var>number</var> מ־100,000 ל־100,001.<br>
חשוב לזכור ש<mark>ההגדלה מ־100,000 ל־100,001 לא באמת שינתה את הערך השמור במשתנה, אלא גרמה למשתנה להצביע לכתובת אחרת של ערך אחר.</mark>
</p>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
בשורה הראשונה ביקשנו מ־<var>number</var> להצביע לערך 100,000, ולכן כשהרצנו את <code>id(number)</code> קיבלנו את הכתובת של הערך <em>100,000</em>.<br>
בשורה השנייה ביקשנו מ־<var>number</var> להצביע לערך 100,001, ולכן כשהרצנו את <code>id(number)</code> קיבלנו את הכתובת של הערך <em>100,001</em>.
</p>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
    עבור שתי השורות הראשונות מודפסת הכתובת של הערך הראשון שיצרנו, 100,000.<br>
    עבור שתי השורות האחרונות מודפסת הכתובת של הערך השני שיצרנו, 100,001.
</p>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
חשוב לדעת שהתייחסות לאותו ערך פעם נוספת עשויה ליצור מופע חדש שלו, שיאוחסן בכתובת אחרת:
</p>
End of explanation
print("ID of number: " + str(id(number)))
number3 = number
print("ID of number2: " + str(id(number3)))
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
אבל השמה של משתנה אחד למשתנה אחר תגרום לכך ששני המשתנים יפנו לאותה כתובת:
</p>
End of explanation
my_list = ['It\'s', 'never', 'enough']
print(f"id() of my_list ({my_list}) before:\n\t" + str(id(my_list)))
my_list[2] = 'lupus'
print(f"id() of my_list ({my_list}) after:\n\t" + str(id(my_list)))
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
ניתן לדמיין את המצב האחרון כמו שני ראשי לייזר שמצביעים לאותה כתובת בזיכרון המחשב.<br>
</p>
<span style="text-align: right; direction: rtl; float: right;">רשימה</span>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
נבדוק אם שינוי של ערך שנמצא בתוך הרשימה יגרום לפייתון לבנות רשימה חדשה.<br>
אם פייתון תבנה רשימה חדשה אחרי שינוי הערך, נוכל לראות זאת בקלות לפי השינוי במיקום של הרשימה בזיכרון.
</p>
End of explanation
str1 = "Puns are the highest form of literature."
str2 = str1
str2 = str2 + "\n\t - Alfred Hitchcock"
print(str1)
print('-' * len(str1))
print(str2)
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
בדוגמה שינינו ערך ברשימה ששמה <var>my_list</var>, וראינו שהמיקום שלה לא משתנה.<br>
זו ההתנהגות שאנחנו מצפים לה מערך שהסוג שלו הוא Mutable – ניתן לשנות אותו מבלי להשפיע על מיקומו בזיכרון המחשב.<br>
</p>
<span style="text-align: right; direction: rtl; float: right;">סיכום ביניים</span>
<ul style="text-align: right; direction: rtl; float: right; clear: both;">
    <li>כל ערך שניצור מאוחסן בכתובת, שלא תשתנה במשך כל חייו של הערך.</li>
    <li>אם ניצור ערך פעמיים, יכול להיות שיהיו שני מופעים שלו בכתובות שונות.</li>
    <li>משתנה הוא לא יותר מ"קשירה" בין שם לכתובת של ערך מסוים.</li>
    <li>השמה היא הפעולה שקושרת בין שם המשתנה לבין הכתובת של הערך.</li>
    <li>ייתכן שיותר משם משתנה אחד יצביע לאותה כתובת.</li>
    <li>ערכים שהסוג שלהם הוא <em>mutable</em> יכולים להשתנות בלי שהכתובת שלהם תשתנה.</li>
    <li>ערכים שהסוג שלהם הוא <em>immutable</em> לא יכולים להשתנות בלי שהכתובת שלהם תשתנה.</li>
</ul>
<span style="text-align: right; direction: rtl; float: right;">השלכות</span>
<span style="text-align: right; direction: rtl; float: right;">רשימות</span>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
נעשה את הניסיון הבא:</p>
End of explanation
list1 = [2, 8, 20, 28, 50, 82]
list2 = list1
list2.append(126)
print(list1)
print('-' * len(str(list1)))
print(list2)
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
עם הידע החדש שצברנו, נוכל להגיד ש־<var>str1</var> ו־<var>str2</var> מצביעים למקומות שונים, בגלל ההשמה בשורה 3.
</p>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
אבל ברשימות אפשר לשנות את הערכים גם בלי לבצע השמה. מה קורה אז?
</p>
End of explanation
print(id(list1))
print(id(list2))
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
במקרה הזה, גרמנו ל־<var>list2</var> להצביע לאותו מקום ש־<var>list1</var> מצביעה עליו.<br>
מהסיבה הזו, שינוי של <var>list2</var> ישפיע גם על <var>list1</var>, ושינוי של <var>list1</var> ישפיע גם על <var>list2</var>.
</p>
End of explanation
list1 = [2, 8, 20, 28, 50, 82]
list2 = list1.copy()
list2.append(126)
print(list1)
print('-' * len(str(list1)))
print(list2)
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
    כדי לבקש מפייתון לא להתנהג כך, צריך להגיד לה במפורש שאנחנו מעוניינים ביצירת רשימה חדשה.<br>
    ניתן לעשות את זה בקריאה לפעולה <code dir="ltr" style="direction: ltr;">list.copy()</code>:
</p>
End of explanation
def append_to_string(my_string):
    print('\t--- Inside the function now ---')
    print(f'\tFunction got value: {my_string}, with id: {id(my_string)}.')
    my_string = my_string + 'Z'
    print(f'\tChanged my_string to be {my_string}, with id: {id(my_string)}.')
    print('\t--- Finished to run the function now ---')
s = 'Hello'
print(f'Before calling the function: s = {s}, with id: {id(s)}.')
append_to_string(s)
print(f'After calling the function: s = {s}, with id: {id(s)}.')
Explanation: <span style="text-align: right; direction: rtl; float: right;">פרמטרים של פונקציה</span>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
נגדיר פונקציה שמקבלת מחרוזת ומשרשרת לסופה את האות <i>Z</i>:
</p>
End of explanation
def append_to_list(my_list):
    print('\t--- Inside the function now ---')
    print(f'\tFunction got value: {my_list}, with id: {id(my_list)}.')
    my_list = my_list + [126]
    print(f'\tChanged my_string to be {my_list}, with id: {id(my_list)}.')
    print('\t--- Finished to run the function now ---')
l = [2, 8, 20, 28, 50, 82]
print(f'Before calling the function: l = {l}, with id: {id(l)}.')
append_to_list(l)
print(f'After calling the function: l = {l}, with id: {id(l)}.')
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
מה קרה בפועל? למה המחרוזת לא השתנתה גם מחוץ לפונקציה?
</p>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
הערך שהועבר לפרמטר של הפונקציה היה הכתובת של <var>s</var>, שעכשיו גם <var>my_string</var> מצביע עליו.<br>
ברגע שביצענו את ההשמה <code dir="ltr" style="direction: ltr;">my_string = my_string + 'Z'</code>, יצרנו באגף הימני של ההשמה ערך חדש, וביקשנו מלייזר חדש ששמו <var>my_string</var> להצביע לכתובת שלו.<br>
המשתנה ששמו <var>my_string</var> מצביע כרגע לכתובת של ערך אחר, בזמן שהמשתנה <var>s</var> עדיין מצביע על הערך המקורי.
</p>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
במקרה הזה, הפונקציה לא שינתה את הערך של המחרוזת שהעברנו לה כארגומנט.<br>
גם אם היינו רוצים מאוד לעשות את זה – זה לא אפשרי, כיוון שמחרוזות הן immutable.<br>
</p>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
ננסה לעשות אותו דבר עם רשימה:
</p>
End of explanation
def append_to_list(my_list):
    print('\t--- Inside the function now ---')
    print(f'\tFunction got value: {my_list}, with id: {id(my_list)}.')
    my_list.append(126)
    print(f'\tChanged my_string to be {my_list}, with id: {id(my_list)}.')
    print('\t--- Finished to run the function now ---')
l = [2, 8, 20, 28, 50, 82]
print(f'Before calling the function: l = {l}, with id: {id(l)}.')
append_to_list(l)
print(f'After calling the function: l = {l}, with id: {id(l)}.')
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
ההתרחשות הייתה זהה למה שקרה עם מחרוזות!<br>
זה קרה כיוון שגם פה דרסנו את <var>my_list</var> כך שיצביע לרשימה חדשה שיצרנו.<br>
בצד ימין של ההשמה, יצרנו רשימה חדשה שמכילה את האיברים <span dir="ltr" style="direction: ltr">2, 8, 20, 28, 50, 82, 126</span>.<br>בעצם ההשמה ביקשנו מ־<var>my_list</var> שבתוך הפונקציה להפנות לכתובת של הרשימה החדשה.<br>
ננסה להשתמש בפעולה של צירוף איבר חדש לרשימה, <code dir="ltr" style="direction: ltr;">list.append(item)</code>, שעליה למדנו השבוע:
</p>
End of explanation
def append_to_list(my_list):
    my_list.append(126)
l = [2, 8, 20, 28, 50, 82]
append_to_list(l)
print(l)
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
הצלחנו!<br>
הרשימה השתנתה גם בתוך הפונקציה וגם מחוצה לה.<br>
אפשר ללמוד מהדוגמה הזו שכשאנחנו מבצעים השמה לשם משתנה מסוים, אנחנו משנים את הכתובת שאליה הצביע שם המשתנה לכתובת חדשה, ולא עורכים את תוכן משתנה.<br>
</p>
<span style="text-align: right; direction: rtl; float: right;">כתיבת פונקציה כראוי</span>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
כשלמדנו פונקציות, הדגשנו את העובדה שפונקציה היא <em>קטע קוד עצמאי</em>.<br>
ככזו, <mark>פונקציה בדרך כלל לא תשנה ערכים של משתנים שלא היא הגדירה.</mark><br>
לדוגמה, קטע הקוד שמופיע למעלה ועורך את המשתנה <code>l</code> שהוגדר מחוץ לפונקציה, נחשב להרגל רע.
</p>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
    הנה קטע הקוד מלמעלה בלי ההדפסות המסרבלות:
</p>
End of explanation
def append_to_list(my_list):
    list_copy = my_list.copy()  # גם יעבוד my_list = my_list.copy()
    list_copy.append(126)
    return list_copy
l = [2, 8, 20, 28, 50, 82]
new_l = append_to_list(l)  # l גם יעבוד, אבל יאבד את הערך של l = append_to_list(l)
print(l)
print(new_l)
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
    ננסה לרשום קוד זהה, רק שהפעם הפונקציה לא תערוך את המשתנה <code dir="ltr" style="direction: ltr;">l</code>:
</p>
End of explanation
animals = ('dog', 'fish', 'horse')
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
    לצורת כתיבה זו כמה יתרונות:
</p>
<ul style="text-align: right; direction: rtl; float: right; clear: both;"></ol>
    <li>קל יותר להבין מה הפונקציה עושה, גם אם אין לקורא ידע מוקדם בנוגע לשאר הקוד.</li>
    <li>קל יותר למשתמש חיצוני להשתמש בפונקציה מבלי לפחד שיאבד מידע.</li>
    <li>קל יותר לבנות פונקציות נוספות שיסתמכו על ההתנהגות של הפונקציה הזו.</li>
</ul>
<span style="text-align: right; direction: rtl; float: right;">Tuple</span>
<span style="text-align: right; direction: rtl; float: right;">הגדרה</span>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
    ברוח השיעור על העובדה שרשימות הן Mutable, הגיע הזמן להכיר את "האח דל התקציב" שלהן: <code>tuple</code>.<br>
    סוג הנתונים tuple לא מרגש במיוחד – הוא למעשה סוג של רשימה שאי־אפשר לשנות. רשימה שהיא immutable, אם תרצו.
</p>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
    נגדיר משתנה מסוג tuple באמצעות סוגריים עגולים:
</p>
End of explanation
first_animal = animals[0]
print(f"The first animal is {first_animal}")
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
 כמו ברשימה, ניתן לקבל איברים שנמצאים ב־tuple אם נפנה למיקום שלהם:
</p>
End of explanation
animals[1] = 'pig'
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
    ניסיון לשנות את ה־tuple לא יצליח, מן הסתם. Immutable, זוכרים?
</p>
End of explanation
my_tuple = tuple()
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
    יצירת tuple ריק תיכתב כך:
</p>
End of explanation
my_tuple = (4, )
Explanation: <p style="text-align: right; direction: rtl; float: right; clear: both;">
    ועבור יצירת tuple עם איבר אחד בלבד, נכתוב את האיבר ואז פסיק אחריו, כדי שפייתון לא תפרש את הביטוי כסוגריים רגילים:
</p>
End of explanation
my_home = (35.027185, -111.022388)  # x, y
traingle_sides_length = (4, 5, 6)
possible_directions = ('UP', 'DOWN', 'LEFT', 'RIGHT')
students_and_age = [('Itamar', 50), ('Yam', '27'), ('David', 16)]  # רשימה של טאפלים
Explanation: <div class="align-center" style="display: flex; text-align: right; direction: rtl; clear: both;">
    <div style="display: flex; width: 10%; float: right; clear: both;">
        <img src="images/exercise.svg" style="height: 50px !important;" alt="תרגול"> 
    </div>
    <div style="width: 90%">
        <p style="text-align: right; direction: rtl; float: right; clear: both;">
        <strong>תרגול</strong>:
            כתבו פונקצייה שמשתמשת ב־<code dir="ltr" style="direction: ltr;">dir()</code>, ומחזירה את כל הפעולות שיש ב־list ואין ב־tuple.<br>
            בדקו גם אילו פעולות יש ב־tuple ואין ב־list.<br>
            בשתי ההשוואות, התעלמו מפעולות ששמן מתחיל בתו קו תחתון.
        </p>
    </div>
</div>
<span style="text-align: right; direction: rtl; float: right;">שימושים</span>
<p style="text-align: right; direction: rtl; float: right; clear: both;">
    אם tuple מעניק לי פחות חופש פעולה, למה להשתמש בו מלכתחילה?
</p>
<ul style="text-align: right; direction: rtl; float: right; clear: both;"></ol>
    <li><strong>מהירות</strong> – עבודה עם ערכים מסוג tuple היא מהירה פי כמה וכמה מאשר עם רשימות.</li>
    <li><strong>סמנטיקה</strong> – עבור ערך קבוע שאין צורך לשנות, נעדיף להשתמש ב־tuple כדי להדגיש את זה וכדי לא לאפשר הוספה או הסרה של ערכים בטעות.</li>
</ul>
<span style="text-align: right; direction: rtl; float: right;">דוגמאות</span>
End of explanation
<END_TASK>