diff --git a/week2/3_Functions.ipynb b/week2/3_Functions.ipynb index a55b742..de75bee 100644 --- a/week2/3_Functions.ipynb +++ b/week2/3_Functions.ipynb @@ -1082,7 +1082,7 @@ "

\n", "הצופן לכספת הביתית שלכם הוא 4812. בנו משחק בול־פגיעה שמאפשר למשתמש לנסות לנחש את הצופן.
\n", "למשתמש יש 3 ניסיונות לנחש נכונה את המספר שלכם לפני שמתחילה אזעקה.
\n", - "כחלק ממנגנון איבוד הסיסמה של הכספת, היא מציגה כמה ספרות נכונות המשתמש הזין אחרי כל ניחוש.
\n", + "כחלק ממנגנון ההגנה מאיבוד הסיסמה של הכספת, היא מציגה כמה ספרות נכונות המשתמש הזין אחרי כל ניחוש.
\n", "אפשרו למשתמש להזין קוד 3 פעמים, וכתבו לו בכל ניסיון כמה מתוך הספרות שהזין באמת קיימות בקוד הנכון, לאו־דווקא בסדר שהקיש.
\n", "אם לא הצליח אחרי 3 ניסיונות, הדפיסו שהאזעקה הופעלה וסיימו את התוכנית.
\n", "

\n", diff --git a/week2/5_String_Methods.ipynb b/week2/5_String_Methods.ipynb index 0c60670..2093cfe 100644 --- a/week2/5_String_Methods.ipynb +++ b/week2/5_String_Methods.ipynb @@ -142,7 +142,7 @@ " \n", "
\n", "

\n", - " פייתון, בניגוד לבני אדם, מסתכל על תווים מיוחדים כמו \\n או \\t כתו אחד.
\n", + " פייתון, בניגוד לבני אדם, מסתכל על תווים מיוחדים כמו \\n ו־\\t כתו אחד.
\n", " נסו לבדוק מה ה־len שלהם כדי להיווכח בעצמכם.\n", "

\n", "
\n", diff --git a/week3/1_While_Loops.ipynb b/week3/1_While_Loops.ipynb new file mode 100644 index 0000000..ff9d71e --- /dev/null +++ b/week3/1_While_Loops.ipynb @@ -0,0 +1,1076 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"לוגו" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#

לולאות

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##

הקדמה

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " זהו בוקר אפלולי וגשום של יום ראשון. השמיים אפורים, ואתם במיטה מתחת לפוך המפנק שלכם, מתפללים שאתם עדיין בתוך החלום המתוק ההוא.
\n", + " השעה היא 7:30. השעון המעורר מנגן שוב את השיר שפעם היה האהוב עליכם, והיום מעלה בכם אסוציאציות קשות שמערבות את הטלפון החכם שלכם ופטיש כבד מאוד.
\n", + " הפגישה שלכם בשעה 9:00, ואתם יודעים שתספיקו בוודאות להגיע אם תתעוררו בשעה 8:00 ותמהרו מאוד.
\n", + " היד מושטת לכפתור ה\"נודניק\" שיפעיל את השעון המעורר שוב עוד 10 דקות. ועוד פעם. ושוב.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " אם נתאר את האלגוריתם שלפיו פעלתם, נוכל להגיד:
\n", + " כל עוד השעון מצלצל, והשעה היא לפני 8:00, לחץ על כפתור הנודניק בשעון.
\n", + " נצייר את דרך הפעולה שלכם:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + " \"התרשים\n", + "
\n", + " תרשים הזרימה של שעון מעורר בבוקר מדכא.\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " נסו לשרטט אלגוריתם להטלת 6 בקובייה.
\n", + " כל עוד לא יצא 6 בקובייה, הטל את הקובייה מחדש.
\n", + " כשקיבלת 6 בקובייה, עשה צהלולים בקול גדול.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##

הגדרה

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "המבנה ששרטטנו זה עתה נקרא לולאה.
\n", + "נשתמש בלולאה כשנרצה לבצע פעולה מסויימת מספר פעמים שאנחנו לאו־דווקא יודעים מראש.
\n", + "אם ננסה לפרק את הלולאה כרעיון, נגלה שכל לולאה מורכבת מ־4 חלקים מרכזיים:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
    \n", + "
  1. אתחול הסביבה - הגדרת ערכים בהם נשתמש בלולאה.
  2. \n", + "
  3. תנאי הלולאה – ביטוי בוליאני. כל עוד הביטוי הזה שקול ל־True, גוף הלולאה ימשיך להתבצע.
  4. \n", + "
  5. גוף הלולאה – הפעולות שיקרו כל פעם שתנאי הלולאה מתקיים.
  6. \n", + "
  7. צעד לקראת סוף הלולאה – נתון שמבטיח שהלולאה תסתיים.
  8. \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "במקרה שלנו:\n", + "

\n", + "
    \n", + "
  1. שלב אתחול הסביבה כולל:\n", + "
      \n", + "
    1. הגדרת הצלצול הראשוני ל־7:30.
    2. \n", + "
    3. הגדרת שעת ההשקמה הסופית ל־8:00.
    4. \n", + "
    5. הגדרת ה\"נודניק\" לתת לנו 10 דקות.
    6. \n", + "
    \n", + "
  2. \n", + "
  3. תנאי הלולאה יכול להיות השעון המעורר פועל וגם השעה היא לפני שעת ההשכמה הסופית.
  4. \n", + "
  5. גוף הלולאה יכול להיות לחיצה על הנודניק וחזרה לישון.
  6. \n", + "
  7. צעד לקראת סוף הלולאה הוא הזמן שעבר בין צלצול לצלצול, שמקרבות אותנו לשעה 8:00.
  8. \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " נסו לחשוב על דוגמה משלכם ללולאה כלשהי, ופרקו אותה ל־4 הרעיונות המרכזיים עליהם דנו.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##

דוגמאות

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "קל לחשוב על דוגמאות ללולאות מחיי היום־יום.
\n", + "כמעט כל פעם שאנחנו אומרים \"עד ש־\" או \"כל עוד־\", אנחנו בונים לולאה במציאות.
\n", + "כל פעם שאנחנו חוזרים על משהו שוב ושוב, אנחנו פועלים לפי לולאה מסוימת שמניעה אותנו.
\n", + "רוב חיי היום־יום שלנו מתנהלים בלולאות, וזו הסיבה שלולאות הן כלי כל כך חזק בתכנות.
\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הנה כמה דוגמאות ללולאות:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " מצאו את 4 הרעיונות המרכזיים שדיברנו עליהם בכל אחת מהדוגמאות.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##

כתיבת לולאה

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "בסרט המוזיקלי Hans Christian Andersen מ־1952, מופיע השיר Inchworm, ושרים בו כך:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + " Two and two are four
\n", + " Four and four are eight
\n", + " Eight and eight are sixteen
\n", + " Sixteen and sixteen are thirty-two
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "זה הזמן לכתוב Inchworm משלנו.
\n", + "נשרטט איך שיר כתיבת לולאה עבור שיר שכזה תראה:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + " \"מתחילים\n", + "
\n", + " איך שיר נולד\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "במקרה שלנו:\n", + "

\n", + "
    \n", + "
  1. שלב אתחול הסביבה הוא השלב שבו נגדיר משתנה עם הערך הראשון להדפסה: 2.
  2. \n", + "
  3. תנאי הלולאה יכול לבדוק האם אנחנו בשורה האחרונה או לפניה.
  4. \n", + "
  5. גוף הלולאה כולל:\n", + "
      \n", + "
    1. הגדרת משתנה שמכיל את סכום שני המספרים.
    2. \n", + "
    3. הדפסת שורה בשיר לפי הערכים שחישבנו.
    4. \n", + "
    \n", + "
  6. \n", + "
  7. הצעד לקראת סוף הלולאה במקרה שלנו הוא קידום המשתנה שמכיל את המספר הנוכחי.
  8. \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "טוב, זה הזמן לקצת קוד, לא?\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "current_number = 2\n", + "while current_number <= 16:\n", + " twice_number = current_number + current_number\n", + " print(f\"{current_number} and {current_number} are {twice_number}\")\n", + " current_number = twice_number" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הקוד הזה משתמש במילת המפתח while כדי ליצור לולאה.
\n", + "הלולאה מקבילה לחלוטין לפירוט המילולי שנמצא מעליה.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "ננסה להזכר איך נראית השורה הראשונה של השיר, וננסה להבין מה הקוד שנכתב למעלה אומר.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "2 and 2 are 4" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "דבר ראשון, עלינו להכין את הסביבה לפני השימוש בלולאה.
\n", + "נשתמש במשתנה שישמור לנו מה המספר שיתחיל את השורה הנוכחית:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "current_number = 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "המספר שפותח את השורה האחרונה בשיר הוא 16, ולכן אנחנו רוצים שהלולאה תרוץ כל עוד המספר הנוכחי ששמרנו קטן או שווה ל־16.
\n", + "נרשום את מילת המפתח while, ומיד לאחריה נוסיף את הביטוי הבוליאני שכשהוא מתקיים אנחנו רוצים שתוכן הלולאה ירוץ. נסיים בנקודותיים.
\n", + "כל פעם שהביטוי הבוליאני יהיה שווה ל־True, גוף הלולאה ירוץ ויבצע את מה שרצינו ממנו.
\n", + "בפעם הראשונה (והיחידה) שהביטוי הבוליאני יהיה שווה ל־False, גוף הלולאה לא יתבצע והתוכנית תמשיך לבצע את הקוד אחרי הלולאה.
\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "while current_number <= 16:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "אחרי שכתבנו את התנאי, זה הזמן לכתוב מה אנחנו רוצים שיתבצע כל פעם שהתנאי יתקיים.
\n", + "החלק הזה נקרא \"גוף הלולאה\", וכל ריצה שלו נקראת \"אִיטֶרַצְיָה\", או בעברית, \"חִזְרוּר\".\n", + "

\n", + "

\n", + "נתחיל בלהגדיר את המספר שיודפס בסוף השורה, שהוא המספר בתחילת השורה ועוד עצמו.
\n", + "שימו לב להזחה, שמציינת שחלק הקוד הזה \"שייך\" ללולאת ה־while ויתבצע כל פעם שהביטוי הבוליאני בה יתקיים.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + " twice_number = current_number + current_number" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נדפיס את השורה עם הפרטים שיצרנו:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + " print(f\"{current_number} and {current_number} are {twice_number}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "ולסיום, לקראת הדפסת השורה הבאה, נקדם את המשתנה שמכיל את הערך שמודפס בתחילת שורה בשיר.
\n", + "הפעולה הזו תכין את המשתנה לשורה הבאה, וגם תקדם את הלולאה לסופה.
\n", + "מכיוון שתחילת כל שורה חדשה בשיר זהה לסוף השורה הקודמת, נוכל פשוט לרשום:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + " current_number = twice_number" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

סיכום ביניים

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "כפי שראינו, לולאת while משתמשת בביטוי בוליאני כדי להחליט האם להריץ קוד מסוים.
\n", + "היא בודקת האם הביטוי שקול ל־True, ואם כן, היא מריצה את קטע הקוד שכתוב בגוף הלולאה.
\n", + "כל עוד הביטוי הבוליאני המופיע ליד המילה while שקול ל־True, גוף הלולאה ימשיך לרוץ.
\n", + "כשהביטוי הופך להיות שקול ל־False, הלולאה מפסיקה מיידית את הריצה שלה והקוד שאחרי הלולאה ממשיך לרוץ.\n", + "

\n", + "

\n", + "הרעיון של while מקביל ל־if שרץ וחוזר לראש התנאי פעם אחר פעם, עד שהביטוי הבוליאני שבראש התנאי שקול ל־False.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " כתבו קוד שמקבל מספר שלם מהמשתמש, ומדפיס את כל המספרים מ־1 ועד המספר שהמשתמש הכניס.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

דוגמאות נוספות

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "####

תרגילים חשבוניים

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "לפניכם דוגמה של קוד שמחשב את סכום המספרים כל המספרים הטבעיים, מ־1 ועד למספר שהוזן על־ידי המשתמש.
\n", + "\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def sum_positive_numbers(max_number):\n", + " total = 0\n", + " first_number = 1\n", + " while first_number <= max_number:\n", + " total = total + first_number\n", + " first_number = first_number + 1\n", + " return total\n", + " \n", + "user_number = int(input(\"Please enter a number: \"))\n", + "print(sum_positive_numbers(user_number))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " הגדירו את 4 החלקים המופיעים בלולאה המופיעה בקוד מעלה.
\n", + " שרטטו כיצד היא עובדת.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "####

מיקומים ברשימה

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "לפניכם קוד שמקבל את כמות החניכים בכתה.
\n", + "לאחר מכן, הוא קולט את הציון של כל תלמיד במבחן האחרון.
\n", + "לבסוף, הקוד יחזיר את הציון הגבוה ביותר בכתה.\n", + "

\n", + "

\n", + "שימו לב לשימוש שנעשה כאן בלולאות כדי לגשת למיקומים של ערכים ברשימה.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def get_grades(number_of_grades):\n", + " grades = []\n", + " while len(grades) < number_of_grades:\n", + " current_grade = int(input(\"Please enter a student grade: \"))\n", + " grades = grades + [current_grade]\n", + " return grades\n", + "\n", + "\n", + "def get_maximum(grades):\n", + " maximum_grade = grades[0]\n", + " current_grade_index = 1\n", + " while current_grade_index < len(grades):\n", + " if grades[current_grade_index] > maximum_grade:\n", + " maximum_grade = grades[current_grade_index]\n", + " current_grade_index = current_grade_index + 1\n", + " return maximum_grade\n", + "\n", + "\n", + "number_of_grades = int(input(\"How many students are there?: \"))\n", + "grades = get_grades(number_of_grades)\n", + "maximum_grade = get_maximum(grades)\n", + "print(f\"The maximum grade is {maximum_grade}\") " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " חשבו על דרך לממש את הקוד הזה עם לולאה אחת בלבד.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "####

לולאה בתוך לולאה

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "i = 1\n", + "j = 1\n", + "while i <= 10:\n", + " line = ''\n", + " while j <= 10:\n", + " line = line + str(i * j) + '\\t'\n", + " j = j + 1\n", + " print(line)\n", + " j = 1\n", + " i = i + 1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " אל תתקדמו הלאה עד שהצלחתם להסביר לעצמכם איך הקוד הזה עובד.
\n", + " במידת הצורך, השתמשו ב־PythonTutor כדי להזין את הקוד ולראות מה הוא עושה.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##
ניפוי שגיאות
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

לולאה אינסופית

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " אם אתם חדשים ללולאות והתנסיתם בפתירת התרגילים, יש סיכוי לא רע שנתקעה לכם המחברת.
\n", + " כשאנחנו מתעסקים עם לולאת while, יש סיכון ממשי שניצור בטעות לולאה שלא תסתיים לעולם.
\n", + " המצב שבו לולאה לא תסתיים נקרא \"לולאה אינסופית\", והוא נובע מכך שתנאי הלולאה שקול תמיד ל־True.\n", + "

\n", + "

\n", + " ישנם שני מקרים מאוד נפוצים שגורמים ללולאות אינסופיות.
\n", + " טיפול במקרה הרלוונטי יגרום ללולאה שלכם לעבוד כראוי:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " אם ליד תא במחברת שלכם מופיעה כוכבית ותאים אחרים לא יכולים לרוץ, סימן שהתא המדובר עדיין רץ.
\n", + " אם הוא רץ זמן רב מדי, יש סיכוי שמדובר בלולאה אינסופית. במידה וזה המצב, בחרו בסרגל הכלים של המחברת \"Kernel\" ואז \"Restart\".
\n", + " זה אמור לעצור את הריצה של המחברת שלכם, ולאפשר לכם לתקן ולהריץ מחדש את הקוד הבעייתי.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " הנה דוגמה ללולאה אינסופית, בתוכנה שאמורה לספור מ־1 עד 10:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "i = 1\n", + "while i < 10:\n", + " print(i)\n", + "print(\"End of the program\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " למה הלולאה הזו אינסופית? עשו מה שצריך על־מנת לתקן אותה.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

הלולאה לא רצה

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "המקרה ההפוך מלולאה אינסופית הוא לולאה שפשוט לא רצה. במילים אחרות – לולאה שתנאי הכניסה שלה שקול ל־False בהרצתה הראשונה.
\n", + "במקרה הזה, ראוי לבדוק איך איתחלנו את הסביבה, והאם התנאי שכתבנו אכן עובד.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "i = 8\n", + "while i <= 0:\n", + " print(i)\n", + "print(\"End of the program\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " את הלולאה הזו כתב מתכנת מפוזר במיוחד, ויש בה יותר מבעיה אחת.
\n", + " מצאו את הבעיות, תקנו אותן והריצו את התוכנית.
\n", + " הפלט הרצוי הוא, משמאל לימין: 8, 4, 2, 1.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

סטייה ב־1

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " זו טעות כל־כך נפוצה שיש לה שם ואפילו ערך בוויקיפדיה!
\n", + " בשגיאה מסוג \"סטייה ב־1\" (באנגלית: \"Off By One\") מתכנת שוכח לטפל במקרה האחרון, או מטפל במקרה אחד יותר מדי.\n", + "

\n", + "

\n", + " נראה דוגמה:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numbers = [1, 2, 3, 4]\n", + "index = 0\n", + "total = 0\n", + "\n", + "while index <= len(numbers):\n", + " total = total + numbers[index]\n", + " index = index + 1\n", + "\n", + "print(total)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " מה הבעיה פה? איך ניתן לפתור אותה?\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

טיפול בבאגים של לולאות

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "לולאות הן כלי חזק שמוסיף עניין רב לקוד.
\n", + "יחד עם זאת, לולאות מוסיפות מקרים מיוחדים שגורמים לבאגים שקשה לפענח בהתחלה.
\n", + "הדרך הכי טובה למצוא בעיות, היא להדפיס את הערכים שנמצאים בלולאה ובאתחול המשתנים שלפניה, ולבדוק מה מצבם.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
    \n", + "
  1. הדפסות לפני תחילת הלולאה – בדקו מה הערך של תנאי הלולאה, והערכים של כל אחד מהביטויים שמרכיבים אותו.
  2. \n", + "
  3. הדפסות בתוך הלולאה – בדקו מה קורה בתוך גוף הלולאה בכל חזרור. הערכים של המשתנים הם מה שציפיתם שהם יהיו?
  4. \n", + "
  5. הדפסות אחרי הלולאה – מה ערכם של המשתנים בסיום הלולאה? מה הערכים של המשתנים בתנאי הבוליאני? האם הלולאה סיימה את עבודה מוקדם מדי?
  6. \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##

מונחים

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
אתחול
לא רק בלולאות – הגדרת משתנים לערכים התחלתיים לפני ביצוע פעולה כלשהי.
\n", + "
תנאי הלולאה
ביטוי בוליאני שכל עוד הוא שקול ל־True, גוף הלולאה ירוץ.
\n", + "
גוף הלולאה
השורות שירוצו אם תנאי הלולאה מתקיים. כולל את הקידום.
\n", + "
קידום
התקדמות של צעד לקראת סוף הלולאה.
\n", + "
חזרור
או איטרציה – הרצה של גוף הלולאה פעם אחת.
\n", + "
לולאה אינסופית
לולאה שלעולם לא תפסיק לרוץ.
\n", + "
סטייה באחד
מצב בו המתכנת שוכח לטפל במקרה האחרון, או מטפל במקרה אחד יותר מהדרוש שלעיתים מקריס את התוכנית.
\n", + "
מבנה לבקרת זרימה
שם כולל למבנים בקוד שמאפשרים לנו לגרום לקוד \"לקפוץ\" משורה אחת למקום אחר. לולאה היא סוג של מבנה לבקרת זרימה.
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##

תרגולים

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

It's the final...

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נתקעתם במסיבה שבה סופרים את השניות לאחור עד השנה החדשה.
\n", + "עזרו למשתתפים המבולבלים שהתחילו לספור הרבה יותר מדי לפני הזמן –
\n", + "קבלו את מספר השניות שנותרו עד חצות, והדפיסו עבורם את הספירה לאחור.
\n", + "בסוף הספירה, הדפיסו \"Happy new year!\"\n", + "

\n", + "

\n", + "לדוגמה, עבור 4, הדפיסו:
\n", + " \n", + " 4\n", + " 3\n", + " 2\n", + " 1\n", + " Happy new year!\n", + " \n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

Play

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "ציירו פירמידה הפוכה, כך שראשה יהיה בצד ימין.
\n", + "במהלך הקוד, קבלו מהמשתמש את אורך השורה שבה מצויר קודקוד הפירמידה.
\n", + "לדוגמה: בפירמידה שלפניכם, המשתמש הכניס 5 כאורך השורה שבה מצויר קודקוד הפירמידה.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "*\n", + "* * \n", + "* * * \n", + "* * * * \n", + "* * * * * \n", + "* * * * \n", + "* * * \n", + "* * \n", + "*\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

מפענח הצפנים 2

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הצופן לכספת הביתית שלכם הוא 4812. בנו משחק בול־פגיעה שמאפשר למשתמש לנסות לנחש את הצופן.
\n", + "למשתמש יש 3 ניסיונות לנחש נכונה את המספר שלכם לפני שמתחילה אזעקה.
\n", + "כחלק ממנגנון ההגנה מאיבוד הסיסמה של הכספת, היא מציגה כמה ספרות נכונות המשתמש הזין אחרי כל ניחוש.
\n", + "אפשרו למשתמש להזין קוד 3 פעמים, וכתבו לו בכל ניסיון כמה מתוך הספרות שהזין באמת קיימות בקוד הנכון, לאו־דווקא בסדר שהקיש.
\n", + "אם לא הצליח אחרי 3 ניסיונות, הדפיסו שהאזעקה הופעלה וסיימו את התוכנית.
\n", + "

\n", + "

\n", + "לדוגמה, אם המשתמש הקיש בניסיון הראשון 0634, הדפיסו לו שרק אחת הספרות שניחש נכונה.
\n", + "אם המשתמש הקיש בסיבוב השני 1234, הדפיסו לו ש־3 ספרות תואמות את הקוד המקורי.
\n", + "אם המשתמש הקיש בסיבוב השלישי 1284, הדפיסו לו ש־4 ספרות תואמות את הקוד המקורי, ואז הדפיסו לו שהופעלה האזעקה.
\n", + "אם המשתמש הקיש באחד הסיבובים 4812, הדפיסו שהכספת נפתחה בהצלחה וסיימו את התוכנית מיד.\n", + "

\n", + "

\n", + "השתמשו בלולאות.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

כמו קולץ בישבן

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נגדיר כלל: אם מספר הוא זוגי, נחלק אותו ב־2. אם המספר אי־זוגי, נכפיל אותו ב־3 ונוסיף לו 1.
\n", + "השערת קולץ טוענת שאם ניקח מספר חיובי שלם ונשתמש עליו פעמים רבות בכלל הזה, תמיד נסיים במספר 1.
\n", + "לדוגמה, אם ניקח את 52, נקבל את שרשרת הפעולות הבאה:\n", + "

\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$\\ 52 \\rightarrow 26 \\rightarrow 13 \\rightarrow 40 \\rightarrow 20 \\rightarrow 10 \\rightarrow 5 \\rightarrow 16 \\rightarrow 8 \\rightarrow 4 \\rightarrow 2 \\rightarrow 1$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "כתבו פונקציה שמקבלת מספר, ומחזירה את מספר הפעולות שצריך לעשות עליו לפי השערת קולץ כדי להגיע ל־1.
\n", + "לדוגמה: עבור המספר 52 היינו צריכים לבצע 11 פעולות כדי להגיע ל־1, ולכן הפונקציה תחזיר 1.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

ממש קולץ בישבן

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " מצאו עבור איזה מספר בין 1 ל־1,000, צריך לעשות את הכי הרבה צעדים לפי השערת קולץ כדי להגיע ל־1.
\n", + "לדוגמה, הנה הצעדים שצריך לעשות עבור כל מספר עד 5:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- $1$\n", + "- $2 \\rightarrow 1$\n", + "- $3 \\rightarrow 10 \\rightarrow 5 \\rightarrow 16 \\rightarrow 8 \\rightarrow 4 \\rightarrow 2 \\rightarrow 1$\n", + "- $4 \\rightarrow 2 \\rightarrow 1$\n", + "- $5 \\rightarrow 16 \\rightarrow 8 \\rightarrow 4 \\rightarrow 2 \\rightarrow 1$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "מכאן שהמספר בין 1 ל־5 שעליו יש לעשות הכי הרבה צעדים לפי השערת קולץ עד שמגיעים לאחד, הוא 3.\n", + "

" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/week3/2_Slicing.ipynb b/week3/2_Slicing.ipynb new file mode 100644 index 0000000..ca6781c --- /dev/null +++ b/week3/2_Slicing.ipynb @@ -0,0 +1,1053 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"לוגו" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#

חיתוך / Slicing

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##

הקדמה

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " בשבוע שעבר למדנו כיצד ניגשים לרשימה או למחרוזת במיקום מסוים:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "great_quote = \"Accept who you are. Unless you're a serial killer.\"\n", + "print(\"The 1st character is: \" + great_quote[0])\n", + "print(\"The 6th character is: \" + great_quote[5])\n", + "print(\"The last character is: \" + great_quote[-1])\n", + "great_quote_by_words = great_quote.split()\n", + "print(\"great_quote_by_words = \" + str(great_quote_by_words))\n", + "print(\"The 1st word is: \" + great_quote_by_words[0])" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " זוהי יכולת שימושית מאוד, אך לעיתים ישנו צורך לקחת חלק מהאיברים של המשתנה שהגדרנו, ולבנות מהם רשימה או מחרוזת חדשה.
\n", + " לדוגמה במקרה הבא, שבו התגנב למחרוזת שלנו מספר מיותר שהיינו שמחים להעלים משם:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "word = \"Avoc42ado\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " ממשו דרך לקבל את המחרוזת ללא המספר.
\n", + " חשבו על דרך אחת נוספת.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##

הגדרה

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "חיתוך (או Slicing) היא שיטה שמטרתה לקבל כמה איברים מתוך ערך מסוים.
\n", + "במחרוזת, חיתוך יעזור לנו לקבל תת־מחרוזת מתוך המחרוזת השלמה.
\n", + "ברשימה, חיתוך יעזור לנו לקבל תת־רשימה מתוך המחרוזת השלמה.
\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##

חיתוך בפייתון

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

חיתוך לפי טווח

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נבחן את המחרוזת הבאה:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "word = 'Avoc42ado'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "מטרתנו תהיה להשיג את החלק הראשון של המחרוזת, זה שנמצא לפני ה־42, באמצעות חיתוך.
\n", + "לשם כך, נביט על המיקומים של כל אות:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
012345678
\"A\"\"v\"\"o\"\"c\"\"4\"\"2\"\"a\"\"d\"\"o\"
-9-8-7-6-5-4-3-2-1
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "לפי השרטוט, אנחנו רוצים לחתוך ממיקום 0 ועד מיקום 3.
\n", + "נבקש מפייתון את המיקומים בצורה הבאה:
\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
    \n", + "
  1. נפתח סוגריים מרובעים.
  2. \n", + "
  3. מיד אחריהם, נציין את המיקום שממנו נתחיל לקחת איברים.
  4. \n", + "
  5. נשים נקודותיים.
  6. \n", + "
  7. מיד אחריהן, נציין מיקום הגדול באחד מהמקום שנסיים בו. פייתון לא יתחשב באיבר שבמיקום הזה.
  8. \n", + "
  9. נסגור סוגריים מרובעים.
  10. \n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# 0 to 4 - Not 0 to 3\n", + "word[0:4]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
012345678
\"A\"\"v\"\"o\"\"c\"\"4\"\"2\"\"a\"\"d\"\"o\"
-9-8-7-6-5-4-3-2-1
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"טיפ!\" \n", + "
\n", + "
\n", + "

\n", + " קל לזכור שפייתון לא לוקח את האיבר האחרון:
\n", + " אם ניקח את המיקום של האיבר האחרון, ונחסר ממנו את המיקום של האיבר הראשון – נקבל את מספר האיברים שחזרו.
\n", + " במקרה שלנו – 4 פחות 0 יוצא 4, שזה בדיוק מספר האיברים שקיבלנו בחזרה.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"אזהרה!\" \n", + "
\n", + "
\n", + "

\n", + " אנשים רבים נוטים להתבלבל בין חיתוך לבין לקריאה לפונקציה.
\n", + " טעות זו גורמת לשימוש בסוגריים עגולים במקום מרובעים, או בפסיק במקום נקודותיים.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"אזהרה!\" \n", + "
\n", + "
\n", + "

\n", + " חיתוכים לא משנים את המחרוזת המקורית, אלא אם נבצע השמה.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "אם אנחנו מעוניינים להתחיל את החיתוך מההתחלה, נוכל להשמיט את החלק שלפני הנקודותיים:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# We can use slicing with implicit starting index\n", + "word[:4]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נשתמש בטריק דומה כדי לחלץ את החלק השני של המחרוזת – מתא 6 ועד סוף המחרוזת:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "word[6:]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
012345678
\"A\"\"v\"\"o\"\"c\"\"4\"\"2\"\"a\"\"d\"\"o\"
-9-8-7-6-5-4-3-2-1
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "אחרי שחתכנו כל־כך יפה את המחרוזת של האבוקדו, הגיע הזמן להינות מהפירות:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "word[:4] + word[6:]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " כתבו שורה שמשיגה רק את תת המחרוזת \"42\" מתוך המחרוזת.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

חיתוך בקפיצות

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "אגף כוח האדם הנהדר של צה\"ל ביקש מכם להשיג את האותיות A, c, a מתוך המחרוזת שהוצגה למעלה.
\n", + "אם נבדוק היטב, נגלה שהאותיות מופיעות החל מהתא ה־0, בקפיצות של 3 כל פעם.
\n", + "למזלנו, בפייתון יש דרך פשוטה להפליא לחתוך תוך כדי קפיצות בין אות לאות – להוסיף נקודותיים, ואז את גודל הקפיצה!\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "word[0:6:3]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "למה זה לא הצליח?
\n", + "נזכר שפייתון לא אוהב לקחת את המקום האחרון:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
012345678
\"A\"\"v\"\"o\"\"c\"\"4\"\"2\"\"a\"\"d\"\"o\"
-9-8-7-6-5-4-3-2-1
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " נתקן, ועל הדרך ניזכר שלא באמת צריך את ה־0 שם בהתחלה:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "word[:7:3]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
012345678
\"A\"\"v\"\"o\"\"c\"\"4\"\"2\"\"a\"\"d\"\"o\"
-9-8-7-6-5-4-3-2-1
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

חיתוך הפוך

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " כחובבים גדולים של שירה לירית, הפעם המטרה שלנו תהיה להשיג את המחרוזת \"oda\".
\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " נשים לב שמדובר בתאים 6, 7 ו־8 בסדר הפוך.
\n", + " נוכל לנסות להפוך את הסדר של הפרמטרים:
\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "word[8:5]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " אך מהר מאוד נגלה שישנה בעיה בהתקדמות נגד כיוון החץ –
\n", + " אי אפשר להגיע מתא 8 לתא 5 אם אנחנו מתקדמים ימינה.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
012345678
\"A\"\"v\"\"o\"\"c\"\"4\"\"2\"\"a\"\"d\"\"o\"
-9-8-7-6-5-4-3-2-1
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " כל מה שנצטרך זה לבקש לקפוץ בצעדים של -1.
\n", + " כשכמות הצעדים (הקפיצות) שלנו תכיל מספר שלילי, כיוון החץ תמיד יהיה מימין לשמאל:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "word[8:5:-1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
012345678
\"A\"\"v\"\"o\"\"c\"\"4\"\"2\"\"a\"\"d\"\"o\"
-9-8-7-6-5-4-3-2-1
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " ובמקרה כזה, סוף המחרוזת שאנחנו חותכים נחשבת התחלת המחרוזת (כי החיתוך מתחיל מימין):\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "word[:5:-1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " חיתכו מהמחרוזת את תת־המחרוזת \"covA\".
\n", + " בשורה נפרדת, מצאו דרך לקבל את תת־המחרוזת \"oda24covA\" בעזרת חיתוך.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

דוגמאות נוספות

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " חיתוך עובד בצורה זהה על רשימה:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# 0 1 2 3 4 5\n", + "animals = ['duck', 'pig', 'cow', 'cat', 'dog', 'shark']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals[2:4]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals[1:4]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals[5:1:-2]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals[:1:-2]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals[5::-2]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals[::-1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "אפשר לעבוד גם עם מיקומים שליליים.
\n", + "עבור פייתון זה אותו דבר:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Index: 0 1 2 3 4 5\n", + "animals = ['duck', 'pig', 'cow', 'cat', 'dog', 'shark']\n", + "# -6 -5 -4 -3 -2 -1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals[-1:-5:-2]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##

תרגולים

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

איזה עולם

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "hello = \"Hello World\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "שרשרו את המחרוזות הבאות יחד, לפי הסדר שהן מוצגות בתרגיל.
\n", + "לצורך התרגיל, התייחסו ל־H כתו הראשון במחרוזת. כמו כן, התייחסו לרווח כתו לכל דבר.\n", + "

\n", + "
    \n", + "
  1. המחרוזת שהוגדרה מהתו השביעי והלאה.
  2. \n", + "
  3. המחרוזת שהוגדרה מהתו השישי ועד התו החמישי, כולל, מימין לשמאל.
  4. \n", + "
  5. המחרוזת \"f \" (התו f ואז רווח).
  6. \n", + "
  7. ארבעת התווים הראשונים במחרוזת שהוגדרה.
  8. \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "###

מסר סודי ביותר

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "ארפכשד העביר לכדרלעומר מסר סודי ומוצפן.
\n", + "במחזורת הבאה, אם תקפצו כל פעם מספר מסוים של אותיות, תקבלו מסר חשוב הכולל את סיסמתו של ארפכשד.
\n", + "מצאו את מספר האותיות שצריך לדלג כל פעם כדי להשיג את המסר הסודי שנשלח לארפכשד.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "רמז: במחרוזת יש את המילה password.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [], + "source": [ + "secret_message = 'TzH?!xC7zAhSH[n[m$_;e>?6: YiT< 8)4=5Kv\\r>p4/{b2vw>fa}^~HNH}sms<_y{`KuK!s9Nt\\'Ckl]{wlEMsmP&,uoDx\\rW zVvvr%M+RXNzE d/cH#hq;}) BR`eBp|;BirGX\\x0cK%Su,s(\"BX6sMa. 1MZ|*\\x0b\\x0bsvA9~:%=p;y^v#l.\\n\\r)63\\noLz]{,|q|!cxd\\'Eik;VVa.vj\\x0c;>c\\t-dw8Fr0TRUro|(\"The very best\"[-3:]*2)[2:6]

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "לפניכם דוגמה של קובץ טקסט שמסודר בצורה שמזכירה טבלה.
\n", + "הקובץ מכיל את עשרים הפוקימונים הראשונים. העמודות מופרדות אחת מהשנייה בפסיקים.
\n", + "החזירו רשימה של רשימות, כאשר כל רשימה מייצגת שורה בטבלה, וכל תא ברשימה הזו מייצג את הערך שנמצא בעמודה באותה רשימה.
\n", + "מחקו מהרשימות את עמדות Generation (הרי שכולם מדור ראשון), ואת עמודת Legendary (אף אחד מהם אינו אגדי).
\n", + "מחקו גם את עמודת Total.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " דוגמה לפלט שאמור לצאת לכם עבור 3 השורות הראשונות:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "[\n", + " ['#', 'Name', 'Type 1', 'Type 2', 'HP', 'Attack', 'Defense', 'Sp. Atk', 'Sp. Def', 'Speed'],\n", + " ['1', 'Bulbasaur', 'Grass', 'Poison', '45', '49', '49', '65', '65', '45'],\n", + " ['2', 'Ivysaur', 'Grass', 'Poison', '60', '62', '63', '80', '80', '60'],\n", + "]\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "בונוס: המירו את המקומות ברשימה שמכילים מספרים לטיפוסים מסוג int.
\n", + "זהו לא תרגיל פשוט. הרגישו בנוח לפתוח מחברות משבוע קודם ולהעזר במדריכים.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": {}, + "outputs": [], + "source": [ + "pokemons = \"\"\"\n", + "#,Name,Type 1,Type 2,Total,HP,Attack,Defense,Sp. Atk,Sp. Def,Speed,Generation,Legendary\n", + "1,Bulbasaur,Grass,Poison,318,45,49,49,65,65,45,1,False\n", + "2,Ivysaur,Grass,Poison,405,60,62,63,80,80,60,1,False\n", + "3,Venusaur,Grass,Poison,525,80,82,83,100,100,80,1,False\n", + "4,Charmander,Fire,,309,39,52,43,60,50,65,1,False\n", + "5,Charmeleon,Fire,,405,58,64,58,80,65,80,1,False\n", + "6,Charizard,Fire,Flying,534,78,84,78,109,85,100,1,False\n", + "7,Squirtle,Water,,314,44,48,65,50,64,43,1,False\n", + "8,Wartortle,Water,,405,59,63,80,65,80,58,1,False\n", + "9,Blastoise,Water,,530,79,83,100,85,105,78,1,False\n", + "10,Caterpie,Bug,,195,45,30,35,20,20,45,1,False\n", + "11,Metapod,Bug,,205,50,20,55,25,25,30,1,False\n", + "12,Butterfree,Bug,Flying,395,60,45,50,90,80,70,1,False\n", + "13,Weedle,Bug,Poison,195,40,35,30,20,20,50,1,False\n", + "14,Kakuna,Bug,Poison,205,45,25,50,25,25,35,1,False\n", + "15,Beedrill,Bug,Poison,395,65,90,40,45,80,75,1,False\n", + "16,Pidgey,Normal,Flying,251,40,45,40,35,35,56,1,False\n", + "17,Pidgeotto,Normal,Flying,349,63,60,55,50,50,71,1,False\n", + "18,Pidgeot,Normal,Flying,479,83,80,75,70,70,101,1,False\n", + "19,Rattata,Normal,,253,30,56,35,25,35,72,1,False\n", + "20,Raticate,Normal,,413,55,81,60,50,70,97,1,False\n", + "\"\"\"" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/week3/3_Files.ipynb b/week3/3_Files.ipynb new file mode 100644 index 0000000..140c6a3 --- /dev/null +++ b/week3/3_Files.ipynb @@ -0,0 +1,1240 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"לוגו" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# קבצים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## הגדרה" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " קובץ הוא מבנה שמאגד בתוכו נתונים השמורים במחשב שלכם.
\n", + " לקובץ יש שם וכתובת (נתיב, או באנגלית path), והוא מכיל כמות מסוימת של מידע שמשפיעה על גודלו.
\n", + " התוכן של כל קובץ מגדיר את הסוג שלו. סוגי קבצים שונים משמשים למטרות שונות, לדוגמה:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
סוג הקובץמטרת הקובץדוגמאות לסיומות
טקסטמכיל מלל בלבד, ללא עיצוב כלשהו (הדגשות, גדלים וכדומה)txt
תמונהייצוג של תמונה דיגיטלית למטרת הצגה חזותית שלהpng, jpg, gif, bmp
וידאוייצוג של סרט או כל תצלום חוזי (וידאו) אחרmp4, avi, flv
פייתוןמכיל קוד שהתוכנה של פייתון יודעת לקרוא ולהפעילpy, pyc, pyd
הרצהמכיל סדרת הוראות המיועדות לקריאה ולהרצה על־ידי המחשבexe, dmg
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## הקדמה" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### מהברזל ועד הקובץ\n", + "\n", + "

\n", + "קבצים הם דרך נהדרת לקבל מבט חטוף לעומק ולמורכבות של המכונה המדהימה שנקראת מחשב.
\n", + "ננסה לצייר לכם תמונה מלאה – נתחיל מהשכבה הנמוכה ביותר, הכונן הקשיח שלכם, ולבסוף נגיע לקבצים.\n", + "

\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### הכונן הקשיח\n", + "\n", + "

\n", + "כונן קשיח הוא אחד מהרכיבים הנמצאים בקופסת המחשב שעליו אתם עובדים כרגע.
\n", + "זהו הרכיב שמאחסן לטווח ארוך את המידע במחשב שלכם – קבצים, תוכנות, מערכת ההפעלה והגדרות כמו העדפות השפה שלכם.
\n", + "היתרון המובהק של כוננים קשיחים הוא שהם יודעים לשמור על המידע שלכם לאורך זמן, גם אם הם לא מוזנים בחשמל באותו רגע.\n", + "

\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### ביט\n", + "\n", + "

\n", + "כוננים קשיחים מכילים הרבה יחידות קטנטנות בשם \"ביט\".
\n", + "ביט הוא ערך שיכול להיות 0 (אין זרם חשמלי) או 1 (יש זרם חשמלי).
\n", + "בכל כונן קשיח פשוט שנמכר היום יש מקום למאות מיליארדי(!) ביטים כאלו.
\n", + "כך נשמר כל המידע שדיברנו עליו בפסקה הקודמת.\n", + "

\n", + "\n", + "

\n", + "אם נסתכל בעיניים אנושיות על רצפי התאים הקטנטנים, הביטים, שנמצאים בכונן הקשיח, כנראה שלא נבין מהם כלום.
\n", + "הנה דוגמה לרצף שכזה: 0100100001100101011011000110110001101111001000000101011101101111011100100110110001100100.
\n", + "איך יוצקים משמעות לתוך דבר כזה? מה רצף המספרים הזה אומר בכלל?\n", + "

\n", + "\n", + "

\n", + "נדמיין לרגע שאנחנו הממציאים של המחשב, והמטרה שלנו היא לייצג טקסט בצורה שיהיה קל לשמור אותו ולקרוא אותו לאחר־מכן.
\n", + "תוכלו לחשוב על דרך לעשות זאת רק באמצעות רצפים של 0 ו־1?\n", + "

\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### יצוג תווים\n", + "\n", + "

\n", + "בעיה דומה, של ייצוג טקסט באמצעות אפסים ואחדים בלבד, עלתה אי שם ב־1960.
\n", + "אני אחסוך לכם הרבה מעשיות בדרך, אבל מפה לשם הוחלט על תקן בשם ASCII, שקובע שכל סידור של 8 ביטים שכאלו (\"בייט\") ייצגו תו.
\n", + "אז האות A קיבלה את הייצוג 01000001, האות Z, למשל, קיבלה את הייצוג 01011010, הספרה 7 את הייצוג 00110111 והתו רווח את הייצוג 00100000.
\n", + "כך אפשר לקרוא מסר ארוך מאוד, ולהמיר כל 8 ביטים רצופים לאות. אם ננסה לקרוא בשיטה הזו 80 ביטים, נקבל 10 תווים.\n", + "

\n", + "\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### יצוג קבצים אחרים\n", + "\n", + "

\n", + "אבל רגע! מה קורה אם אני רוצה לייצג תמונה של חתול? או סירטון של חתול? או סאונד של... ובכן, חתול?
\n", + "כמו שאנשים חכמים חשבו על דרך לייצג ASCII, חכמים אחרים חשבו, עבור כל סוג של קובץ – מתמונה ועד תוכנה שרצה על המחשב, על איך מייצגים אותם באמצעות ביטים.
\n", + "גם בימים אלו, אנשים מוכשרים רבים יושבים וחושבים על דרכים טובות יותר לייצג מידע בעזרת ביטים, ויוצרים עבורינו סוגי קבצים חדשים.
\n", + "

\n", + "\n", + "

\n", + "כשאנחנו רוצים לפתוח תמונה של חתול, למשל, אנחנו מפעילים תוכנה ייעודית שיודעת לקרוא ייצוג של תמונות.
\n", + "מה שקורה באותו רגע מאחורי הקלעים הוא שהתוכנה קוראת רצפים של 0 ו־1 מהדיסק הקשיח, אותם ביטים שדיברנו עליהם.
\n", + "מי שצילם את התמונה השתמש בתוכנה שיודעת להמיר את מה שקרה על מסך המצלמה לביטים שנשמרו על כרטיס הזכרון שלו.
\n", + "מי שתכנת את התוכנה שמציגה לנו כרגע את החתול ידע להגיד לה כיצד לתרגם את אותם ביטים לתמונה שמוצגת לכם על המסך.
\n", + "שניהם פעלו לפי תקן מסוים (יש כמה כאלו, אולי אתם מכירים: JPG, PNG, GIF ועוד), שאומר איך מייצגים תמונה בעזרת ביטים.
\n", + "בסופו של דבר, עבור התוכנה החתול שלכם הוא בסך־הכל משבצות קטנטנות בצבעים שונים שמצוירות זו על־יד זו.\n", + "

\n", + "\n", + "

\n", + " כשמתפתח ייצוג מסוים של קובץ, הוא נקרא \"פורמט\", או בעברית \"תַּסְדִיר\".\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### קבצים טקסטואלים וקבצים בינאריים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "חלק מהקבצים, כמו מסמכי טקסט או תוכניות פייתון, יכולים להיות קבצים טקסטואליים.
\n", + "ישנם סוגי קבצים טקטואליים נוספים, כמו CSV שמייצג מידע טבלאי באמצעות טקסט, או HTML שמייצג קוד שבעזרתו המחשב יודע להציג דף אינטרנט.
\n", + "המשותף לקבצים אלו שאם ממירים את הבייטים שמהם הם מורכבים לתווים, מקבלים תוצאה שנוח לבני־אדם לקרוא, ולא רק למחשב.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + " \"שני\n", + "
מימין ניתן לראות קובץ CSV פתוח באקסל, ומשמאל את הייצוג הטקסטואלי שלו.
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "ישנם גם סוגי קבצים אחרים שלא נועדו לקריאה על־ידי עין אנושית.
\n", + "קבצים כאלו נקראים \"קבצים בינאריים\", ונלמד לטפל בחלק מהם בשלב מתקדם יותר בקורס.
\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " ניתן דוגמה לכמה סוגי קבצים בינאריים:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + " \"שני\n", + "
מימין ניתן לראות קובץ PNG פתוח בתוכנה להצגת תמונות, ומשמאל את הייצוג הבינארי שלו כשמנסים להמיר אותו לטקסט.
\n", + " קל לראות ש־PNG אינו תסדיר טקסטואלי.
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " במהלך החוברת הזו, אנו נלמד לטפל בקבצים טקסטואליים.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## טיפול בקבצים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " אם בעבר היינו משתמשים בפנקס כדי לשמור דברים, הרי שהיום שימוש בקבצים ממוחשבים הופך את הכל לקל ומהיר.
\n", + " מעבר לזה – על קבצים ממוחשבים אפשר לבצע חישובים מסובכים תוך חלקיק שנייה, מה שנותן לנו יכולות מופתיות שלא היו לנו בעבר.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " קבצים הם מקור מצויין לקלט ולפלט עבור התוכניות שאנחנו בונים.
\n", + " כמקור קלט, הם יכולים לכלול בקלות שורות רבות או מידע מורכב.
\n", + " כפלט, הם מאפשרים לנו לשמור מידע בין הרצה להרצה, להעביר את המידע ממקום למקום בקלות ולייצג את המידע שלנו בצורה מורכבת.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "בקובץ passwords.txt שנמצא בתוך תיקיית resources, אספנו לכם את 25 הסיסמאות הנפוצות ביותר בעולם.
\n", + "בתור התחלה, בואו ננסה להציץ במה כתוב בתוך הקובץ בעזרת פייתון. \n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### פתיחת קובץ" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הפונקציה open יודעת לפתוח קובץ ולהחזיר לנו ערך שמצביע עליו, מה שיאפשר לנו לכתוב קוד שעושה בקובץ שימוש.
\n", + "הערך הזה שמצביע על הקובץ נקרא File handler, סוג חדש של ערך שעליו נוכל לבצע שלל פעולות.
\n", + "הפונקציה open מקבלת 2 פרמטרים: הראשון הוא הנתיב לקובץ, והשני הוא צורת הגישה לקובץ.
\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"אזהרה!\" \n", + "
\n", + "
\n", + "

\n", + " הפרמטר השני, צורת הגישה לקובץ, הוא מחרוזת.
\n", + " טעות נפוצה היא לשים שם r, w או a בלי גרשיים מסביב.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נתחיל בפתיחת הקובץ, והשמה של ה־file handler למשתנה:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "common_passwords_file = open('resources/passwords.txt', 'r')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "כך נראה הסוג של file handler המצביע לקובץ טקסטואלי:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(common_passwords_file)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### קריאת קובץ" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "עכשיו, כשהקובץ פתוח, נוכל להשתמש בו.
\n", + "נבקש מפייתון לקרוא את תוכן הקובץ באמצעות הפעולה read, ונשמור את התוכן שחוזר מהפעולה על משתנה:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "common_passwords = common_passwords_file.read()\n", + "print(common_passwords)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נשים לב שמה שחזר לנו מפעולת הקריאה הוא מחרוזת לכל דבר:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "type(common_passwords)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "זיכרו ששורות חדשות מיוצגות על־ידי התו \\n, וכך גם ב־common_passwords:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "common_passwords" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " פתחו וקראו את הקובץ בעצמכם, קבלו מהמשתמש את הסיסמה שלו, והדפיסו האם היא בין 25 הסיסמאות הנפוצות ביותר.
\n", + " בונוס: אם היא בין 25 הסיסמאות הנפוצות, החזירו את המיקום שלה ברשימה.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### הסמן" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "אם ננסה לקרוא שוב את הקובץ, נגלה תופעה מעט מוזרה:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "common_passwords_again = common_passwords_file.read()\n", + "print(common_passwords_again)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# ???\n", + "common_passwords_again == ''" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "קריאה נוספת של הקובץ החזירה לנו הפעם שהוא ריק!
\n", + "אתם ודאי תשמחו לגלות שזו התנהגות צפויה – וזה הכל באשמתו של הסמן.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "כאשר אנחנו פותחים קובץ לקריאה, הסמן (באנגלית: cursor) מצביע לתחילת הקובץ.
\n", + "ודאי תופתעו לדעת שאתם כבר מכירים את הרעיון של סמן!
\n", + "דמיינו שאתם פותחים מסמך לעריכה, או אפילו פותרים תרגיל במחברת, ותיזכרו בקו המהבהב שמראה לכם את המיקום שאליו האות שתכתבו תתווסף.
\n", + "ברגע שאתם מבקשים מפייתון לקרוא את הקובץ בעזרת read, היא קוראת מהמקום בו נמצא הסמן ועד סוף הקובץ.
\n", + "בזמן הקריאה, פייתון תעביר את הסמן לסוף הקובץ, ולכן כשתנסו לקרוא אותו שוב – תקבלו מחרוזת ריקה.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### seek" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "כדי להחזיר את הסמן לתחילת הקובץ, נשתמש בפעולה seek ונבקש ממנה להחזיר את הסמן כך שיצביע למקום 0 – לפני התו הראשון:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "common_passwords_file.seek(0)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(common_passwords_file.read())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### tell" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "ניתן לראות איפה הסמן נמצא באמצעות הפעולה tell:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "common_passwords_file.tell()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "מכאן ניתן להסיק, שאם נעשה seek ונספק כארגומנט 224, נעביר את הסמן כך שיצביע לסוף הקובץ. \n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### קריאה בצורות נוספות" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "לעיתים, במיוחד כשיש קובץ גדול במיוחד, נעדיף לקרוא כל פעם רק חלק מהקובץ.
\n", + "נוכל לבחור לקרוא מספר מסוים של תווים באמצעות הפעולה read שאנחנו כבר מכירים,
\n", + "אלא שהפעם נעביר לה ארגומנט שיגיד לה כמה תווים לקרוא:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "common_passwords_file.seek(0)\n", + "common_passwords_file.read(10)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "כדאי לזכור שהסמן יהיה עכשיו במקום 10, והפעלה נוספת של פעולת הקריאה תמשיך מהמקום הזה:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "common_passwords_file.read(5)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "פייתון מאפשר לנו לקרוא גם עד סוף השורה הנוכחית, שעליה נמצא הסמן, באמצעות הפעולה readline.
\n", + "שימו לב שהשורה תסתיים בתווים המייצגים שורה חדשה:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "common_passwords_file.seek(0)\n", + "common_passwords_file.readline()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "לקריאת כל השורות בקובץ, ניתן להשתמש בפעולה readlines, שתחזיר לנו רשימת מחרוזות.
\n", + "כל מחרוזת ברשימה מייצגת שורה אחת בקובץ:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "common_passwords_file.seek(0)\n", + "passwords = common_passwords_file.readlines()\n", + "print(\"The passwords variable looks like: \" + str(passwords))\n", + "print(\"The type of 'passwords' is: \" + str(type(passwords)))\n", + "# אם נרצה להפטר מתו השורה החדשה עבור אחת השורות, נוכל להשתמש בפעולה שלמדנו על מחרוזות:\n", + "# strip\n", + "print(\"The most common password is: \" + passwords[0].strip())\n", + "print(\"The least common password in the list is: \" + passwords[-1].strip())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " כתבו פונקציה שמקבלת נתיב לקובץ, ומחזירה רשימה בה כל איבר הוא שורה בקובץ.
\n", + " בניגוד לפעולה readlines, המחרוזות ברשימה לא יסתיימו בתו שמייצג ירידת שורה.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### סגירת קובץ" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "כמו שלהשאיר דלת פתוחה נחשב מנהג גס־רוח, במחשבים אנחנו נוהגים לסגור קבצים לאחר שסיימנו להשתמש בהם.
\n", + "קובץ פתוח תופס משאבי מערכת (כמו זכרון), ולעיתים יגרום לכך שתוכנות אחרות לא יוכלו לגשת אליו.
\n", + "השארת קבצים פתוחים הוא מנהג מגונה שיגרום להאטה בביצועים, ואפילו לקריסות בלתי צפויות במידה ויש יותר מדי file handlers פתוחים.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "לא מדובר בפעולה מסובכת מדי. כל מה שתצטרכו לעשות הוא להשתמש בפעולה close:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "common_passwords_file.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "שימו לב שניסיון לעשות כל שימוש בקובץ אחרי סגירתו, יכשל:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "common_passwords_file.read()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### כתיבה לקובץ" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נסתכל שוב על המידע שראינו בתרגיל על הפוקימונים:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pokemons = \"\"\"\n", + "#,Name,Type 1,Type 2,Total,HP,Attack,Defense,Sp. Atk,Sp. Def,Speed,Generation,Legendary\n", + "1,Bulbasaur,Grass,Poison,318,45,49,49,65,65,45,1,False\n", + "2,Ivysaur,Grass,Poison,405,60,62,63,80,80,60,1,False\n", + "3,Venusaur,Grass,Poison,525,80,82,83,100,100,80,1,False\n", + "4,Charmander,Fire,,309,39,52,43,60,50,65,1,False\n", + "5,Charmeleon,Fire,,405,58,64,58,80,65,80,1,False\n", + "6,Charizard,Fire,Flying,534,78,84,78,109,85,100,1,False\n", + "7,Squirtle,Water,,314,44,48,65,50,64,43,1,False\n", + "8,Wartortle,Water,,405,59,63,80,65,80,58,1,False\n", + "9,Blastoise,Water,,530,79,83,100,85,105,78,1,False\n", + "10,Caterpie,Bug,,195,45,30,35,20,20,45,1,False\n", + "11,Metapod,Bug,,205,50,20,55,25,25,30,1,False\n", + "12,Butterfree,Bug,Flying,395,60,45,50,90,80,70,1,False\n", + "13,Weedle,Bug,Poison,195,40,35,30,20,20,50,1,False\n", + "14,Kakuna,Bug,Poison,205,45,25,50,25,25,35,1,False\n", + "15,Beedrill,Bug,Poison,395,65,90,40,45,80,75,1,False\n", + "16,Pidgey,Normal,Flying,251,40,45,40,35,35,56,1,False\n", + "17,Pidgeotto,Normal,Flying,349,63,60,55,50,50,71,1,False\n", + "18,Pidgeot,Normal,Flying,479,83,80,75,70,70,101,1,False\n", + "19,Rattata,Normal,,253,30,56,35,25,35,72,1,False\n", + "\"\"\"" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הפעם, נכתוב אותו לתוך קובץ מתסדיר CSV.
\n", + "כדי לכתוב לקובץ נשתמש בפעולה write, לאחר שנפתח את הקובץ במצב כתיבה (w).\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"אזהרה!\" \n", + "
\n", + "
\n", + "

\n", + " זהירות! פתיחת קובץ קיים במצב w תמחק את התוכן שלו מיידית.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"טיפ\" \n", + "
\n", + "
\n", + "

\n", + " במידה ופתחנו קובץ לכתיבה והקובץ לא קיים במערכת שלנו, פייתון יבדוק האם התיקייה שמעליו קיימת.
\n", + " אם כן – פייתון יצור את הקובץ בשבילנו.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pokemons_file = open('pokemon.csv', 'w')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# נסיר את השורות הריקות והרווחים מהצדדים\n", + "clear_pokemon = pokemons.strip()\n", + "# ונכתוב לקובץ\n", + "pokemons_file.write(clear_pokemon)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "המספר שפייתון מחזיר הוא כמות התווים שייכתבו לקובץ.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "אם תחפשו את הקובץ במחשב ותפתחו אותו, אתם תגלו שפייתון עדיין לא כתב אליו את הנתונים.
\n", + "פייתון שומר את הנתונים שביקשתם לכתוב בצד במעין מנגנון זיכרון זמני שנקרא buffer, ויכתוב אותם לקובץ כשתסגרו אותו.
\n", + "תוכלו להכריח את פייתון לכתוב לקובץ עוד לפני שסגרתם אותו באמצעות הפעולה flush:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pokemons_file.flush()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "לסיום, לא נשכח לסגור את הקובץ כשאנחנו יודעים שכבר לא נשתמש בו:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pokemons_file.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"טיפ\" \n", + "
\n", + "
\n", + "

\n", + " כשאתם בתוך המחברת, ניתן להשתמש בסימן קריאה כדי להריץ דברים שלא קשורים לפייתון.
\n", + " לדוגמה: !pokemon.csv יריץ את הקובץ שכתבנו.
\n", + " שימו לב שלא תוכלו להריץ שום דבר אחר במחברת עד שתסגרו את הקובץ.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "!pokemon.csv" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### הוספה לקובץ" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "ניתן לפתוח קובץ במצב 'w' אם נרצה לכתוב לקובץ חדש, או לדרוס קובץ קיים.
\n", + "אם נרצה להוסיף שורות לקובץ קיים, נפתח את הקובץ במצב ההוספה 'a' שמסמן append.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נוסיף את פוקימון מספר 20, רטיקייט, לקובץ הפוקימונים:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "new_line = \"\\n20,Raticate,Normal,,413,55,81,60,50,70,97,1,False\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pokemons_table = open('pokemon.csv', 'a')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הוספת התוכן לקובץ במצב הוספה תתבצע באמצעות הפעולה write, בדיוק כמו בכתיבת קובץ חדש:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pokemons_table.write(new_line)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "pokemons_table.close()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## with" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "מילת המפתח with מאפשרת לנו לאגד כמה שורות תחת אותו הקשר.
\n", + "במקרה של קבצים, היא מאפשרת לנו לאגד תחתיה שורות שמטרתן טיפול בקובץ מסוים.
\n", + "לדוגמה, השורות הבאות:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "passwords_file = open('resources/passwords.txt', 'r')\n", + "most_used_password = passwords_file.readline()\n", + "other_common_passwords = passwords_file.read()\n", + "passwords_file.close()\n", + "\n", + "print(most_used_password.strip())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " יכולות להכתב אחרת בעזרת מילת המפתח with:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "with open('resources/passwords.txt', 'r') as passwords_file:\n", + " most_used_password = passwords_file.readline()\n", + " other_common_passwords = passwords_file.read()\n", + "\n", + "print(most_used_password.strip())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " שימו לב לצורת השימוש ב־with:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
    \n", + "
  1. כתבנו את מילת המפתח, with.
  2. \n", + "
  3. מיד לאחר מכן השתמשנו בפונקציה open כדי לפתוח את הקובץ עם הארגומנטים שרצינו.
  4. \n", + "
  5. השתמשנו במילת המפתח as.
  6. \n", + "
  7. הכנסנו את שם המשתנה שרצינו שבו ישמר ה־file handler.
  8. \n", + "
  9. כתבנו נקודותיים כדי לסיים את השורה.
  10. \n", + "
  11. השתמשנו בהזחה, ואז כתבנו את הפעולות שאנחנו רוצים לעשות וקשורות לקובץ.
  12. \n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " בתור מתכנתים, זו בחירה שלכם איך לכתוב את הקוד שלכם.
\n", + " ובכל זאת, קל לראות את היתרונות של שימוש ב־with:
\n", + " הקוד הופך להיות קריא ומסודר יותר, והקובץ נסגר לבד כשמסתיימת ההזחה.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " כתיבת קוד עם with היא יותר פשוטה ממה שהיא נראית בהתחלה –
\n", + " 5 הסעיפים הראשונים התייחסו לשורה הראשונה, ששקולה לשורה הראשונה והרביעית בקוד בלי ה־with.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## מונחים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
קובץ טקסטואלי
קובץ שאם ממירים את הבייטים ממנו הוא מורכב לתווים, מקבלים קובץ שקריא על־ידי בני אדם.
\n", + "
קובץ בינארי
קובץ שהתוכן שלו לא נועד לקריאה על־ידי עין אנושית.
\n", + "
סמן
מצביע על המקום הנוכחי בקובץ, ממנו הפעולות יתבצעו (קריאה, כתיבה וכדומה).
\n", + "
ASCII
שיטה מוסכמת לייצוג תווים בזיכרון ובקבצים.
\n", + "
תסדיר
פורמט, מוסכמה על הדרך שבה ייצגו קובץ מסויים.
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## תרגולים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### מי דגנים בריאים?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " בקובץ cereal.csv שנמצא בתיקיית resources, ישנו מידע תזונתי על מִדְגַּנִּים שונים (יענו, דגני בוקר).
\n", + " ככל שהמדגנים שמופיעים בשורה מסויימת בריאים יותר, כך המספר שמופיע לידם תחת העמודה rating גבוה יותר.
\n", + " נמצאו את המדגנים הבריאים ביותר והדפיסו את שמם לצד הציון שקיבלו.
\n", + " קרדיט: את הקובץ הבאנו מכאן.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### תקווה מארחת" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "בקובץ hope.txt שנמצא בתיקיית resources, נמצאת אחת הפואמות המהממות של אמילי דיקנסון, תִּקְוָה הִיא בַּעֲלַת-הַנוֹצָה.
\n", + "אך אבוי! הפואמה התבלגנה, וכעת סדר המילים בכל שורה הוא הפוך.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "במקום:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + " תִּקְוָה הִיא בַּעֲלַת-הַנוֹצָה
\n", + " זוּ בַּנְּשָׁמָה תִשְׁכֹּן –\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "מופיע:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + " בַּעֲלַת-הַנוֹצָה הִיא תִּקְוָה
\n", + " – תִשְׁכֹּן בַּנְּשָׁמָה זוּ\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "שמרו גיבוי של הקובץ בצד, וכתבו קוד שמסדר את הפואמה המבולגנת.
\n", + "שמרו את הפואמה המסודרת בקובץ חדש ששמו hope2.txt.\n", + "

" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/week3/4_List_Methods.ipynb b/week3/4_List_Methods.ipynb new file mode 100644 index 0000000..689eaa9 --- /dev/null +++ b/week3/4_List_Methods.ipynb @@ -0,0 +1,734 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"לוגו" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# פעולות על רשימות" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## הקדמה" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " עד כה למדנו שישנם שני אופרטורים חשבוניים שעובדים על רשימות: חיבור וכפל.
\n", + " חיבור משרשר רשימה אחת לאחרת, וכפל משרשר רשימה לעצמה מספר פעמים.
\n", + " ניזכר בדוגמאות:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numbers = [1, 2]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numbers = numbers + [3, 4]\n", + "print(numbers)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numbers = numbers * 2\n", + "print(numbers)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " למדנו גם שאפשר להשוות בין רשימות בעזרת אופרטורי השוואה, עליהם למדנו בשיעור על ביטויים בוליאניים.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "numbers == [1, 2, 3, 4]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "1 in numbers" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "[1, 2] in numbers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " השבוע כבר הספקנו ללמוד על חיתוכים (Slicing), כך שאנחנו כבר מחזיקים בדי הרבה ידע לגבי איך מתפעלים רשימות.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(numbers)\n", + "print(\"Flip the order: \" + str(numbers[::-1]))\n", + "print(\"Only first 4 items: \" + str(numbers[:4]))\n", + "print(\"Only first 4 items, in reversed order:: \" + str(numbers[3::-1]))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " למרות כל הידע המועיל שצברנו עד עכשיו, טרם נגענו בפעולות השייכות לנתונים מסוג רשימה.
\n", + " הפעולות האלו יתווספו לארגז הכלים שלנו, יקלו על כתיבת הקוד ויהפכו את הקוד שלנו לקריא יותר.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## פעולות על רשימה" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נגדיר רשימה שתשמש אותנו לדוגמאות:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals = ['pig', 'shark', 'lion']" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "במהלך המעבר על הדוגמאות, נשים לב שפעולות על רשימה מתבצעות על הרשימה עצמה.
\n", + "זה אומר שלא נצטרך להשתמש בהשמה כדי לשנות את הרשימה שעליה אנחנו עובדים.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### הוספת איבר" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "רשימה היא סוג נתונים נוח מאוד, בין היתר מכיוון שניתן להוסיף לה כמה איברים שנרצה.
\n", + "נוכל להוסיף איבר לסוף הרשימה באמצעות הפעולה append:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals.append('duck')\n", + "print(animals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הפעולה הזו תשיג תוצאה זהה לקוד שכתבנו עד היום בדרך טיפה פחות אלגנטית:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals = animals + ['duck']\n", + "print(animals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "שימו לב שבניגוד לשורה שמופיעה למעלה, append מאפשרת להוסיף כל פעם איבר אחד בלבד.
\n", + "ניסיון להעביר לפעולה append רשימה, נניח, יוסיף את הרשימה כולה כאיבר אחד ברשימה:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals.append(['duck', 'zebra'])\n", + "print(animals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " כתבו פונקציה שמקבלת מספר, ומחזירה רשימה של כל המספרים החיוביים הזוגיים עד אותו מספר.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### הסרת איבר" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נוכל להסיר איבר מסוף הרשימה באמצעות קריאה פשוטה לפעולה pop:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals.pop()\n", + "print(animals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הפעולה הזו תשיג תוצאה זהה למה שעשינו השבוע בצורה המסורבלת הבאה:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals = animals[:-1]\n", + "print(animals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הפעולה pop מחזירה את הערך שהוציאה, כך שאפשר לשמור אותו בצד:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "last_animal = animals.pop()\n", + "print(last_animal)\n", + "print(animals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הפעולה גם מאפשרת לנו לבחור את המקום שממנו אנחנו מעוניינים להוציא את הערך.
\n", + "נעשה זאת בעזרת העברת ארגומנט עם מיקום הערך שאנחנו רוצים להוציא מהרשימה:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "first_animal = animals.pop(0)\n", + "print(first_animal)\n", + "print(animals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "כדי להסיר יותר מאיבר אחד, יתכן שעדיין תעדיפו להשתמש בחיתוך רשימות.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " כתבו פונקציה שמקבלת רשימה, ומחזירה רשימה עם סדר איברים הפוך.
\n", + " השתמשו בפעולה pop.
\n", + " לדוגמה: אם תועבר לפונקציה הרשימה [3, 2, 1], הפונקציה תחזיר [1, 2, 3].\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### הוספת מספר איברים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נוכל להוסיף יותר מאיבר אחד במכה בעזרת הפעולה extend:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals_to_add = ['duck', 'pig', 'zebra']\n", + "animals.extend(animals_to_add)\n", + "print(animals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "במבט ראשון, הפעולה תשיג את אותה תוצאה כמו שרשור רשימות:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals_to_add = ['duck', 'pig', 'zebra']\n", + "animals = animals + animals_to_add\n", + "print(animals)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "אבל אחד היתרונות המשמעותיים ב־extend הוא שניתן להעביר לה כל iterable שהוא.
\n", + "הפעולה extend תפרק את ה־iterable ותוסיף כל איבר בנפרד לרשימה המקורית: \n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "string_numbers = ['1', '2', '3', '4', '5']\n", + "string_numbers.extend('6789') # string as argument\n", + "string_numbers.extend(['10', '11']) # list as argument\n", + "print(string_numbers)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " כתבו פונקציה שמקבלת רשימה, ומחזירה רשימה המכילה את הרשימה המקורית, ומיד אחריה את אותה רשימה בסדר הפוך.
\n", + " לדוגמה: עבור הרשימה [1, 2, 3] תוחזר הרשימה: [1, 2, 3, 3, 2, 1]\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ספירת איברים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "כאן לא תמצאו הפתעות מיוחדות. הפעולה count סופרת את כמות האיברים שזהים לאיבר שהעברתם לה כארגומנט.
\n", + "נשמע לכם מוכר? נכון! למחרוזות יש פעולה עם אותו שם שעושה בדיוק אותו דבר.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(animals)\n", + "zebra_counter = animals.count('zebra')\n", + "print(f\"I've found {zebra_counter} zebras in your zoo!\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### מציאת איבר" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "גם הפעולה הזו אמורה לצלצל לכם מוכר.
\n", + "הפעולה index מוצאת את המופע הראשון של האיבר שהעברתם לה כארגומנט.
\n", + "וכן, גם הפעם למחרוזות יש פעולה עם אותו שם שעושה בדיוק אותו דבר.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(animals)\n", + "zebra_finder = animals.index('zebra')\n", + "print(f\"The first zebra in your zoo hides in park number {zebra_finder}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"אזהרה!\" \n", + "
\n", + "
\n", + "

\n", + " כמו בפעולת index במחרוזת, גם כאן הפעולה תקפיץ שגיאה במידה והערך לא נמצא.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " כתבו פונקציה שמקבלת רשימה, ומחזירה את המיקום של המופע האחרון של האיבר שמופיע במקום 0 ברשימה.
\n", + " לדוגמה, עבור הרשימה [1, 2, 3, 5, 1, 2] החזירו 4, מכיוון ש־1 מופיע פעם אחרונה במקום 4 ברשימה.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### מחיקת איבר (שוב?)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הפעם נשתמש בפעולה remove, שבניגוד לפעולה pop מוחקת איבר לפי הערך שלו ולא לפי המיקום שלו.
\n", + "שימו לב שהפעולה תמחק את האיבר הראשון שהיא תמצא, ולא את כל המופעים שלו.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(f\"Animals: {animals}\")\n", + "while 'pig' in animals:\n", + " animals.remove('pig')\n", + "print(f\"Kosher Zoo: {animals}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " קבלו פונקציה שמקבלת רשימה של חיות, ומחזירה רשימה ללא מופעים של החיות camel, rabbit או pig.
\n", + " לדוגמה, עבור הרשימה: ['camel', 'camel', 'dove', 'pig', 'camel'] תוחזר הרשימה: ['dove']\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### סידור רשימה" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "אחת הפעולות הנוחות ביותר שאפשר למצוא בפייתון היא sort, שמסדרת לנו את האיברים ברשימה.
\n", + "אם האיברים הם מחרוזות, הסדר יהיה סדר לקסיקוגרפי (לפי א\"ב).
\n", + "אם האיברים ברשימה הם מספרים (שלמים, עשרוניים או גם וגם), הסדר יהיה סדר עולה מתמטית.
\n", + "אם הרשימה מורכבת מסוגים שונים של איברים שאין ביניהם הגדרת שיוויון ברורה (כמו מספרים ומחרוזות), פעולת המיון תכשל ותזרוק שגיאה.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(animals)\n", + "animals.sort()\n", + "print(animals)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "strange_list = [1, 2, 3, 'dag maluah']\n", + "strange_list.sort()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"אזהרה!\" \n", + "
\n", + "
\n", + "

\n", + " טעות נפוצה היא להכניס את התוצאה של sort חזרה למשתנה.
\n", + " מכיוון שהפעולה sort משנה את ערך המשתנה במקום ולא מחזירה ערך, השמה חזרה למשתנה תמחק את ערכו.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " קבלו מהמשתמש 10 מספרים. מצאו מה הערך השלישי הכי גדול.
\n", + " לדוגמה, עבור הקלט הבא: 5, 1, 6, 2, 3, 4, 8, 7, 10, 9, החזירו 8.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### הוספת איבר במקום מסוים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " קראו בתיעוד של פייתון על הפעולה insert השייכת לרשימה.
\n", + " הוסיפו דג מימין לכריש (shark) שברשימת animals.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## תרגולים נוספים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### חוטש" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " כתבו פונקציה שמקבלת רשימה של רשימות, ומחזירה רשימה שטוחה והפוכה של כל האיברים.
\n", + " לדוגמה: עבור הרשימה [[1, 2, 3], [4, 5, 6]] החזירו [6, 5, 4, 3, 2, 1].\n", + "

" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/week3/5_Mutability_and_Tuples.ipynb b/week3/5_Mutability_and_Tuples.ipynb new file mode 100644 index 0000000..1dccd2a --- /dev/null +++ b/week3/5_Mutability_and_Tuples.ipynb @@ -0,0 +1,883 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\"לוגו" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Mutability" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## הגדרה" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "המילה Mutable נגזרת מהמילה Mutate, והמשמעות שלה היא \"משהו שאפשר לשנות\".
\n", + "אנחנו נשתמש בה עבור סוגי נתונים שמיועדים לכך שישנו אותם, למשל יוסיפו אליהם איברים או יחסירו מהם איברים.
\n", + "משמעות המילה Immutable היא \"משהו שאי אפשר לשנות\", נתון שאמור להיות קבוע אחרי יצירתו.
\n", + "שינוי ערך שהוא Immutable משנה את המהות שלו, ויגרום לו להחשב ערך אחר לגמרי.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נדמיין ארנק שבתוכו שטרות – ניתן להוסיף אליו שטרות או להוציא ממנו שטרות, אבל הארנק יישאר אותו ארנק.
\n", + "מכיוון שניתן לשנות את המצב של הארנק בלי לפגוע במהות שלו, ניתן להגיד שארנק הוא Mutable.
\n", + "לעומת זאת, אם אקח את אחד השטרות שנמצאים בתוך הארנק, לא אוכל לשנות בו משהו בלי שהוא יאבד את המהות שלו.
\n", + "שינוי באחד המאפיינים של השטר, כמו המספר שכתוב עליו, יגרור שינוי מהותי שיהפוך אותו לדבר אחר לחלוטין.
\n", + "ניתן להגיד שהשטר הוא Immutable, בלתי ניתן לשינוי.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הערכים ה־Mutable שנכיר בקורס הם מעין \"מכולות\" שמכילות ערכים אחרים.
\n", + "עד כה, אנו מכירים סוג ערך אחד שהוא Mutable – רשימה.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## כתובות של ערכים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### ערכים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "כדי להבין טוב יותר את הנושא, נעצור לרגע כדי להבין איך ערכים עובדים מאחורי הקלעים בפייתון.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "כשאנחנו יוצרים ערך כלשהו, פייתון מקצה עבורו מקום בזיכרון המחשב ושומרת שם את הערך.
\n", + "מאותו רגע לאותו ערך יש כתובת, שהיא מספר שמייצג איפה הוא נמצא בזיכרון.
\n", + "הכתובת של ערך נשארת זהה מרגע שהוא נוצר ועד סוף חייו.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(9876543)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "בשורה למעלה הגדרנו את הערך 9876543.
\n", + "אפילו שלא עשינו עליו פעולה מתוחכמת ולא שמרנו אותו במשתנה, פייתון תשמור את הערך הזה בזיכרון המחשב.
\n", + "לערך 9876543 יש כתובת עכשיו.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "כשאנחנו מגדירים משתנה חדש, אנחנו בסך־הכל יוצרים קישור בין שם המשתנה לבין הכתובת של הערך שהשמנו לתוכו.
\n", + "תוכלו לדמיין משתנה כסוג של לייזר שמצביע על מקום מסוים במפה – ראש הלייזר הוא שם המשתנה, והמקום במפה הוא כתובת הערך שלו.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "name = 12345" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "בשורה למעלה \"קשרנו\" את השם name לכתובת של הערך המספרי 12345.
\n", + "המשתנה name לא \"מכיל\" את הערך 12,345, אלא רק מצביע על הכתובת שבה הערך 12,345 מאוחסן.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### בדיקת כתובת של ערכים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הפונקציה id מקבלת כארגומנט ערך, ומחזירה מספר שמייצג את הכתובת שלו – המיקום של הערך בזיכרון.
\n", + "נראה דוגמה:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "number = 100000\n", + "print(\"ID before: \" + str(id(number)))\n", + "number = 123456\n", + "print(\"ID after: \" + str(id(number)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הדוגמה האחרונה מבהירה שעבור ערכים שונים, אפילו אם אותו שם משתנה מצביע עליהם, יש כתובות שונות.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "number = 100000\n", + "print(\"ID before: \" + str(id(number)))\n", + "number = number + 1\n", + "print(\"ID after: \" + str(id(number)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "בדוגמה הגדלנו את ערך המשתנה number מ־100,000 ל־100,001.
\n", + "החלק החשוב לזכור בדוגמה הזו היא שההעלאה מ־100,000 ל־100,001 לא באמת \"שינתה את הערך ששמור במשתנה\", אלא גרמה למשתנה להצביע לכתובת אחרת של ערך אחר.\n", + "

\n", + "

\n", + "בשורה הראשונה \"קשרנו\" את שם המשתנה number לערך 100,000, ולכן כשביקשנו את id(number) למעשה ביקשנו לדעת את הכתובת של 100,000.
\n", + "בשורה השנייה \"קשרנו\" את שם המשתנה number לערך 100,001, ולכן כשביקשנו את id(number) למעשה ביקשנו לדעת את הכתובת של 100,001.\n", + "

\n", + "

\n", + " עבור שתי השורות הראשונות מודפסת הכתובת של הערך הראשון שיצרנו, 100,000.
\n", + " עבור שתי השורות האחרונות מודפסת הכתובת של הערך השני שיצרנו, 100,001.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "חשוב לדעת שהתייחסות לאותו ערך פעם נוספת עלולה ליצור מופע חדש שלו, שיאוחסן בכתובת אחרת:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(f\"ID of number ({number}): \" + str(id(number)))\n", + "number2 = 100001\n", + "print(f\"ID of number2 ({number2}): \" + str(id(number2)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "אבל השמה של משתנה אחד למשתנה אחר תגרום לכך ששני המשתנים יפנו לאותה כתובת:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(\"ID of number: \" + str(id(number)))\n", + "number3 = number\n", + "print(\"ID of number2: \" + str(id(number3)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "ניתן לדמיין את המצב כמו שני ראשי לייזר שמצביעים לאותה נקודה על המפה,
\n", + "או כמו מגירה שמכילה ערך ושהדביקו עליה שתי מדבקות עם שמות שונים.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### רשימה" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נבדוק האם שינוי של ערך בתוך רשימה יגרום לפייתון לבנות רשימה חדשה.
\n", + "אם פייתון יבנה רשימה חדשה אחרי שינוי הערך, נוכל לראות זאת בקלות לפי השינוי במיקום של הרשימה בזיכרון.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_list = ['It\\'s', 'never', 'enough']\n", + "print(f\"id() of my_list ({my_list}) before:\\n\\t\" + str(id(my_list)))\n", + "my_list[2] = 'lupus'\n", + "print(f\"id() of my_list ({my_list}) after:\\n\\t\" + str(id(my_list)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "בדוגמה שינינו ערך ברשימה ששמה my_list, וראינו שהמיקום שלה לא משתנה.
\n", + "זה מה שאנחנו מצפים מערך שהסוג שלו הוא Mutable – ניתן לשנות אותו.
\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### סיכום ביניים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## השלכות" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### רשימות" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נעשה את הניסיון הבא:

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "str1 = \"Puns are the highest form of literature.\"\n", + "str2 = str1\n", + "str2 = str2 + \"\\n\\t - Alfred Hitchcock\"\n", + "\n", + "print(str1)\n", + "print('-' * len(str1))\n", + "print(str2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "עם הידע החדש שצברנו, נוכל לראות ש־str1 ו־str2 מצביעים למקומות שונים, בגלל ההשמה בשורה 3.\n", + "

\n", + "

\n", + "אבל ברשימות אפשר לשנות את הערכים גם בלי לבצע השמה. מה קורה אז?\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "list1 = [2, 8, 20, 28, 50, 82]\n", + "list2 = list1\n", + "list2.append(126)\n", + "\n", + "print(list1)\n", + "print('-' * len(str(list1)))\n", + "print(list2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "במקרה הזה, גרמנו ל־list2 להצביע לאותו מקום ש־list1 מצביעה עליו.
\n", + "מהסיבה הזו, שינוי של list2 משפיע גם על list1, ושינוי של list1 ישפיע גם על list2.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "print(id(list1))\n", + "print(id(list2))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " כדי \"להתגבר\" על זה, צריך להגיד לפייתון במוצהר שאנחנו מעוניינים ביצירת רשימה חדשה.
\n", + " ניתן לעשות את זה על־ידי קריאה לפעולה list.copy():\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "list1 = [2, 8, 20, 28, 50, 82]\n", + "list2 = list1.copy()\n", + "list2.append(126)\n", + "\n", + "print(list1)\n", + "print('-' * len(str(list1)))\n", + "print(list2)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### פרמטרים של פונקציה" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "נגדיר פונקציה שמקבלת מחרוזת, ומוסיפה לה בסוף את האות Z:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def append_to_string(my_string):\n", + " print('\\t--- Inside the function now ---')\n", + " print(f'\\tFunction got value: {my_string}, with id: {id(my_string)}.')\n", + " my_string = my_string + 'Z'\n", + " print(f'\\tChanged my_string to be {my_string}, with id: {id(my_string)}.')\n", + " print('\\t--- Finished to run the function now ---')\n", + "\n", + "s = 'Hello'\n", + "print(f'Before calling the function: s = {s}, with id: {id(s)}.')\n", + "append_to_string(s)\n", + "print(f'After calling the function: s = {s}, with id: {id(s)}.')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "מה קרה בפועל? למה המחרוזת לא השתנתה גם מחוץ לפונקציה?\n", + "

\n", + "

\n", + "הערך שהועבר לפרמטר של הפונקציה היה הכתובת של s, שעכשיו גם my_string מצביעה עליו.
\n", + "ברגע שביצענו את ההשמה my_string = my_string + 'Z', יצרנו באגף הימני ערך חדש, ושמנו ב־my_string את הכתובת שלו.
\n", + "המשתנה my_string מצביע כרגע לכתובת של ערך אחר, בזמן שהמשתנה s עדיין מצביע על הערך המקורי.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "במקרה הזה, הפונקציה לא שינתה את הערך של המחרוזת שהעברנו לה כארגומנט.
\n", + "גם אם מאוד היינו רוצים לעשות את זה – זה לא אפשרי, מכיוון שמחרוזות הן Immutable.
\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "ננסה לעשות אותו דבר עם רשימה:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def append_to_list(my_list):\n", + " print('\\t--- Inside the function now ---')\n", + " print(f'\\tFunction got value: {my_list}, with id: {id(my_list)}.')\n", + " my_list = my_list + [126]\n", + " print(f'\\tChanged my_string to be {my_list}, with id: {id(my_list)}.')\n", + " print('\\t--- Finished to run the function now ---')\n", + "\n", + "l = [2, 8, 20, 28, 50, 82]\n", + "print(f'Before calling the function: l = {l}, with id: {id(l)}.')\n", + "append_to_list(l)\n", + "print(f'After calling the function: l = {l}, with id: {id(l)}.')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "ההתרחשות הייתה זהה למה שקרה עם מחרוזות!
\n", + "זה קרה מכיוון שגם פה, דרסנו את my_list כך שיצביע לרשימה חדשה שיצרנו.
\n", + "בצד ימין של ההשמה, יצרנו רשימה חדשה שמכילה את האיברים 2, 8, 20, 28, 50, 82, 126.
בעצם ההשמה ביקשנו מ־my_list שבתוך הפונקציה להפנות לכתובת של הרשימה החדשה.
\n", + "ננסה להשתמש בפעולה של צירוף איבר חדש לרשימה, list.append(item), עליה למדנו השבוע:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def append_to_list(my_list):\n", + " print('\\t--- Inside the function now ---')\n", + " print(f'\\tFunction got value: {my_list}, with id: {id(my_list)}.')\n", + " my_list.append(126)\n", + " print(f'\\tChanged my_string to be {my_list}, with id: {id(my_list)}.')\n", + " print('\\t--- Finished to run the function now ---')\n", + "\n", + "l = [2, 8, 20, 28, 50, 82]\n", + "print(f'Before calling the function: l = {l}, with id: {id(l)}.')\n", + "append_to_list(l)\n", + "print(f'After calling the function: l = {l}, with id: {id(l)}.')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "הצלחנו!
\n", + "הרשימה השתנתה גם בתוך הפונקציה וגם מחוץ לה.
\n", + "אפשר ללמוד מהדוגמה הזו שכשאנחנו מבצעים השמה לשם משתנה מסוים, אנחנו משנים את הכתובת שאליה הצביע שם המשתנה לכתובת חדשה, ולא \"עורכים\" את התוכן שלו.
\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### כתיבת פונקציה כראוי" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "כשלמדנו פונקציות, אחד הדגשים שעלו הוא זה שפונקציה היא קטע קוד עצמאי.
\n", + "ככזו, פונקציה בדרך־כלל לא תשנה ערכים של משתנים שלא היא הגדירה.
\n", + "לדוגמה, קטע הקוד שמופיע למעלה ועורך את המשתנה l שהוגדר מחוץ לפונקציה, נחשב הרגל רע.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " הנה קטע הקוד מלמעלה בלי ההדפסות המסרבלות:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": 119, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 8, 20, 28, 50, 82, 126]\n" + ] + } + ], + "source": [ + "def append_to_list(my_list):\n", + " my_list.append(126)\n", + "\n", + "l = [2, 8, 20, 28, 50, 82]\n", + "append_to_list(l)\n", + "print(l)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " ננסה לרשום קוד זהה, רק שהפעם הפונקציה לא תערוך את המשתנה l:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": 126, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[2, 8, 20, 28, 50, 82]\n", + "[2, 8, 20, 28, 50, 82, 126]\n" + ] + } + ], + "source": [ + "def append_to_list(my_list):\n", + " list_copy = my_list.copy() # גם יעבוד my_list = my_list.copy()\n", + " list_copy.append(126)\n", + " return list_copy\n", + "\n", + "l = [2, 8, 20, 28, 50, 82]\n", + "new_l = append_to_list(l) # l גם יעבוד, אבל יאבד את הערך של l = append_to_list(l)\n", + "print(l)\n", + "print(new_l)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " צורת הכתיבה הזו מבטיחה לנו מספר יתרונות:\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Tuple" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### הגדרה" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " ברוח השיעור על העובדה שרשימות הן Mutable, הגיע הזמן להכיר את האח דל־התקציב שלהן: tuple.
\n", + " סוג הנתונים tuple לא מרגש במיוחד – הוא למעשה סוג של רשימה שאי אפשר לשנות. Immutable list, אם תרצו.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " נגדיר משתנה מסוג tuple באמצעות סוגריים עגולים:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals = ('dog', 'fish', 'horse')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " כמו ברשימה, ניתן לקבל איברים שנמצאים ב־tuple על־ידי פנייה למיקום שלהם:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "first_animal = animals[0]\n", + "print(f\"The first animal is {first_animal}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " ניסיון לשנות את ה־tuple לא יצליח, מן הסתם. Immutable, זוכרים?\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "animals[1] = 'pig'" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " יצירת tuple ריק תכתב כך:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_tuple = tuple()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " ועבור יצירת tuple עם איבר אחד בלבד, נכתוב את האיבר ואז פסיק אחריו, כדי שפייתון לא תפרש את הביטוי כסוגריים רגילים:\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": {}, + "outputs": [], + "source": [ + "my_tuple = (4, )" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
\n", + " \"תרגול\" \n", + "
\n", + "
\n", + "

\n", + " תרגול:\n", + " כתבו פונקצייה שמשתמשת ב־dir(), ומחזירה את כל הפעולות שיש ב־list ואין ב־tuple.
\n", + " בדקו גם אילו פעולות יש ב־tuple ואין ב־list.
\n", + " בשתי ההשוואות, התעלמו מפעולות שמתחילות בתו קו תחתון.\n", + "

\n", + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### שימושים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " אם tuple מעניק לי פחות חופש פעולה, למה להשתמש בו מלכתחילה?\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### דוגמאות" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_home = (35.027185, -111.022388) # x, y\n", + "traingle_sides_length = (4, 5, 6)\n", + "possible_directions = ('UP', 'DOWN', 'LEFT', 'RIGHT')\n", + "students_and_age = [('Itamar', 50), ('Yam', '27'), ('David', 16)] # רשימה של טאפלים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "##

מונחים

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
כתובת
מקום במחשב שבו שמור ערך כלשהו. הערך לעולם לא יחליף את הכתובת שלו.
\n", + "
Immutable
ערך שלא ניתן לשנות.
\n", + "
Mutable
ערך שניתן לשנות.
\n", + "
Tuple
סוג משתנה. Immutable. דומה לרשימה בתכונותיו.
\n", + "
" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/week3/Summary.ipynb b/week3/Summary.ipynb new file mode 100644 index 0000000..b5350cb --- /dev/null +++ b/week3/Summary.ipynb @@ -0,0 +1,862 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + " \"מיזם" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# תרגילים" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## הגדרה" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " פונקציית גיבוב היא פונקציה המקבלת קלט כלשהו ומחזירה ערך באורך קבוע.
\n", + " קיימות פונקציות גיבוב רבות, ולהן שימושים מגוונים.\n", + "

\n", + "\n", + "

\n", + " נמנה מספר תכונות נפוצות שקיימות בפונקציות גיבוב:\n", + "

\n", + " \n", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## מימוש בסיסי" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " בתרגיל זה נממש גרסה פשוטה של פונקציית גיבוב (hash function).
\n", + " פונקציית הגיבוב שלנו תקבל מחרוזת ותחזיר תמיד פלט באורך זהה.\n", + "

\n", + "

\n", + " תחילה נכיר את הפונקציה ord(תו).
\n", + " פונקציה זו מקבלת תו, ומחזירה ערך מספרי המייצג אותו:
\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "97" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "ord('a')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "פונקציית הגיבוב שלנו תעבוד באופן הבא:
\n", + "

\n", + "
    \n", + "
  1. נאתחל משתנה עזר בשם hash כך שערכו יהיה 1.
  2. \n", + "
  3. עבור כל אות במחרוזת:
  4. \n", + "
      \n", + "
    1. נחשב את ord(letter) ונכפיל במשתנה העזר hash.
    2. \n", + "
    3. נכפיל את הערך שקיבלנו במיקום של האות הבאה במחרוזת.\n", + "
    4. לתוצאה הזו נבצע מודולו 397643, ונשמור על hash.
    5. \n", + "
    \n", + "
  5. כדי שהפלט תמיד יהיה באורך זהה, נשתמש במודולו 100297 על התוצאה (חשבו: איך מודולו גורם לזה לקרות?)
  6. \n", + "
\n", + "

\n", + "פונקציית הגיבוב שיצרנו מחזירה תמיד ערכים באורך קבוע (בין 0 ל־100297) כפי שפונקציית גיבוב צריכה להחזיר (לאו דווקא באורך זה, אבל הפלט חייב להיות באורך קבוע).\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " דוגמה:
\n", + "

\n", + "\n", + "myhash('aba')
\n", + "62242
\n", + "\n", + "

\n", + " החישוב התבצע כך:
\n", + "

\n", + "\n", + "temp_hash = 1
\n", + "temp_hash = (temp_hash*ord('a')*1) % 397643\n", + "# temp_hash = (1*97*1) % 397643 = 97
\n", + "\n", + "

\n", + " שימו לב שכאן הכפלנו ב־1, כיון שמיקום האות הוא 0 ואנו מכפילים\n", + " באינדקס האות הבאה.\n", + "

\n", + "\n", + "temp_hash = (temp_hash*ord('b')*2) % 397643\n", + "# temp_hash = (97*98*2) % 397643 = 19012\n", + "temp_hash = (temp_hash*ord('a')*3) % 397643\n", + "# temp_hash = (19012*97*3) % 397643 = 363133\n", + "return temp_hash % 100297\n", + "# temp_hash = 363133 % 100297 = 62242" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " ממשו את פונקציית הגיבוב.
\n", + " על מנת לבדוק את עצמכם ודאו שקיבלתם את הערכים הבאים עבור המחרוזות הבאות:
\n", + "

\n", + "\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " שימו לב שזוהי פונקציית גיבוב מומצאת.
\n", + " אנחנו לעולם לא נשתמש בפונקציות גיבוב שהמצאנו בסביבות אמיתיות שאנחנו מתכנתים(!), משום שדבר כזה יסכן בוודאות את המשתמשים במערכת.
\n", + " זה עולם שלם שנחקר רבות, ואנחנו תמיד נשתמש רק בפונקציות גיבוב שנחקרו ופורסמו מטעמי המוסדות הרלוונטיים.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# כתבו את הפונקציה שלכם כאן" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## איקס־עיגול" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " נזכיר את החוקים של המשחק המוכר איקס־עיגול:
\n", + "

\n", + "\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### מימוש המשחק

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### ייצוג הלוח" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " את הלוח נייצג באמצעות רשימה של רשימות.
\n", + " כל רשימה תייצג שורה בלוח שלנו: הרשימה במיקום 0 תייצג את השורה הראשונה בלוח, הרשימה בשורה 1 את השורה השנייה וכך הלאה.
\n", + " הרשימות המייצגות את השורות יהיו רשימות של תווים, כאשר בכל תא יהיה אחד מבין התווים האפשריים – 'O', 'X' או '-'\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " לדוגמה, כך נראה לוח ריק:\n", + "

\n", + " \n", + "[['-', '-', '-'], ['-', '-', '-'], ['-', '-', '-']]\n", + " \n", + "

\n", + " נוח לדמיין את הרשימה הזו כתובה במאונך:\n", + "

\n", + "\n", + "\n", + "[\n", + " ['-', '-', '-'],\n", + " ['-', '-', '-'],\n", + " ['-', '-', '-']\n", + "]\n", + "\n", + " \n", + "

\n", + " כעת נראה איך נראה הלוח כאשר יש 'X' באלכסון:\n", + "

\n", + "\n", + "\n", + "[\n", + " ['X', '-', '-'],\n", + " ['-', 'X', '-'],\n", + " ['-', '-', 'X']\n", + "]\n", + "\n", + "

\n", + " וללא ההדפסה לאורך:\n", + "

\n", + "\n", + "[['X', '-', '-'], ['-', 'X', '-'], ['-', '-', 'X']]\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " תחילה נממש פונקציה המקבלת את הלוח ובודקת האם יש מנצח כלשהו \n", + " (X או O),\n", + " ומחזירה את האות של המנצח\n", + " ('X' או 'O')\n", + " אם יש מנצח ו־'' (מחרוזת ריקה)\n", + " אחרת.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "# check_board(board) כתבו את הפונקציה שלכם כאן" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " לפני שתמשיכו הלאה חשוב לוודא שהפונקציה שכתבתם עובדת.
\n", + " כתבו בדיקות עבור המקרים הבאים:\n", + "

\n", + "\n", + "\n", + "\n", + "

\n", + " סך־הכל תצטרכו לכתוב 10 בדיקות.\n", + "

\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# בדיקה עבור אלכסון ראשי" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# בדיקה עבור אלכסון משני" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# בדיקה עבור טור שמאלי" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# בדיקה עבור טור אמצעי" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# בדיקה עבור טור ימני" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# בדיקה עבור שורה עליונה" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# בדיקה עבור שורה אמצעית" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# בדיקה עבור שורה תחתונה" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# בדיקה עבור לוח מלא ללא ניצחון" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# בדיקה עבור לוח לא מלא ללא ניצחון" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### פונקציות לבדיקת תקינות קלט

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " במהלך המשחק אנו נקלוט מהשחקנים במשחק (המשתמשים) את המקומות בלוח בהם הם ירצו למקם את האות שלהם.
\n", + " מקומות אלו יהיו שני מספרים בתחום 0–2 המציינים את השורה והעמודה בה יש למקם את האות.
\n", + " לדוגמה, עבור:\n", + "

\n", + "\n", + "1 2\n", + "\n", + "

\n", + " נמקם את האות המתאימה לשחקן, נניח X, בשורה 1 ובעמודה 2, באופן הבא:\n", + "

\n", + "\n", + "[['-', '-', '-'], ['-', '-', 'X'], ['-', '-', '-']]\n", + "\n", + "

\n", + " זכרו כי הספירה מתחילה מ־0 ולכן מדובר בשורה האמצעית ובעמודה הימנית.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " כעת כתבו פונקציה המקבלת את הלוח, ואת התו שמייצג את השחקן ('X' או 'O'). כמו כן, הפונקציה תקלוט מהמשתמש שני מספרים.
\n", + " הפונקציה תבדוק האם התנאים הבאים מתקיימים, במידה והם מתקיימים היא תמקם את האות הנתונה במיקום המבוקש, ותעדכן את הלוח:
\n", + "

\n", + "\n", + "
    \n", + "
  • מספר השורה הוא בין 0 ל־2.
  • \n", + "
  • מספר העמודה הוא בין 0 ל־2.
  • \n", + "
  • המקום המבוקש לא תפוס על־ידי אות כלשהי (כלומר יש בו '-').
  • \n", + "
\n", + "\n", + "

\n", + " שימו לב, עליכם לחייב את המשתמש להכניס ערכים חוקיים. כלומר, המשחק לא ימשיך עד אשר יתקבל קלט תקין.
\n", + " כאשר נגלה בשלב מוקדם יותר שהלוח לא ניתן יותר למילוי – המשחק יסתיים.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "לוח לדוגמה:\n", + "

\n", + "\n", + "\n", + "board = [['-', '-', '-'], ['-', 'O', 'X'], ['-', '-', '-']]\n", + "\n", + "\n", + "

\n", + " הזנה חוקית:\n", + "

\n", + "\n", + "make_turn('X', board)\n", + "\n", + "
\n", + "\n", + "Player 'X' Please choose cell:\n", + "0 2\n", + "\n", + "[['-', '-', 'X'], ['-', 'O', 'X'], ['-', '-', '-']]\n", + "\n", + "

\n", + " הזנה לא חוקית:\n", + "

\n", + "\n", + "
\n", + "\n", + "Player 'X' Please choose cell:\n", + "5 -2\n", + "Invalid line chosen (5)\n", + "Invalid column chosen (-2)\n", + "[['-', '-', '-'], ['-', 'O', 'X'], ['-', '-', '-']]\n", + "\n", + "\n", + "
\n", + "\n", + "Player 'X' Please choose cell:\n", + "1 2\n", + "Place (1,2) is taken, use other.\n", + "[['-', '-', '-'], ['-', 'O', 'X'], ['-', '-', '-']]\n", + "\n", + "\n", + "
\n", + "\n", + "Player 'X' Please choose cell:\n", + "2 -2\n", + "Invalid column chosen (-2)\n", + "[['-', '-', '-'], ['-', 'O', 'X'], ['-', '-', '-']]\n", + "\n", + "\n", + "
\n", + "\n", + "Player 'X' Please choose cell:\n", + "1 1\n", + "Place (1,1) is taken, use other.\n", + "[['-', '-', '-'], ['-', 'O', 'X'], ['-', '-', '-']]\n", + "\n", + "\n", + "
\n", + "\n", + "

\n", + " שימו לב שלאחר כל פעולה אנו מדפיסים את הלוח, בין אם הצליחה ובין אם לא.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [], + "source": [ + "# make_turn(player_char,board) כתבו את הפונקציה שלכם כאן" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " בונוס: ממשו פונקציה שמדפיסה את הלוח לאורך.\n", + "

\n", + "\n", + "print_board(board)\n", + "\n", + "
\n", + "\n", + "\n", + "[\n", + " ['-', '-', '-'],\n", + " ['-', '-', '-'],\n", + " ['-', '-', '-']\n", + "]\n", + "" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### מימוש המשחק" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " כאמור המשחק ממשיך כל עוד אין מנצח ונותר מקום פנוי בלוח.
\n", + " נשים לב כי מספר המהלכים החוקיים יכול להיות לכל היותר כגודל הלוח.
\n", + " כלומר – אם לא הוכרז מנצח במהלך המשחק, המשחק ייגמר לאחר 9 מהלכים עבור לוח בגודל $3\\times3$.
\n", + " נספור את כמות המהלכים החוקיים במשחק. עבור מספר מהלך זוגי (0, 2, 4, ...) ישחק השחקן O, ועבור מספרי מהלך אי־זוגיים ישחק השחקן X.
\n", + " נתאר את מהלך המשחק בפסאודו־קוד:
\n", + "

\n", + "
    \n", + "
  1. אתחל את מונה המהלכים ל־0.
  2. \n", + "
  3. כל עוד אין מנצח וגם הלוח לא מלא:\n", + "
      \n", + "
    • אם מספר המהלך זוגי – בצע מהלך שחקן O.
    • \n", + "
    • אם מספר המהלך אי־זוגי – בצע מהלך שחקן X.
    • \n", + "
    \n", + "
  4. \n", + "
  5. הגדל את מונה המהלכים ב־1.
  6. \n", + "
  7. אם קיים ניצחון – הכרז על המנצח, אחרת הכרז תיקו.
  8. \n", + "
\n", + "

\n", + " ממשו את המשחק על־פי הפונקציות שמימשתם ותיאור מהלך המשחק.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# tic_tac_toe()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " כעת שחקו עם בני משפחה וחברים ;)\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## בנק 2.0" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " מנהלי הבנק היו מאוד מרוצים מהתוכנה הקודמת לניהול בנק שכתבתם וכעת היו רוצים לשפר אותה.
\n", + " תחילה הם הביעו דאגה מחוזק הסיסמאות. מנגנון הסיסמאות הקודם היה חלש ומנהלי הבנק מפחדים שיעשה בו שימוש לרעה.
\n", + " שמועות מתפשטות מאוד מהר ומנהלי הבנק שמעו שמימשתם גרסה לפונקציית גיבוב. הם מעוניינים לעשות בה שימוש במנגנון הסיסמאות החדש.\n", + "

\n", + "\n", + "

\n", + " מנגנון הסיסמאות ינוהל באופן הבא:\n", + "

\n", + "\n", + "
    \n", + "
  1. הבנק ינהל קובץ סיסמאות שיקרא bank_passwd.txt.
  2. \n", + "
  3. כאשר משתמש יפתח חשבון בנק, הוא יכניס את הסיסמה שהוא מעוניין שתשמש אותו להתחברות הבאה.
  4. \n", + "
  5. נחשב את ה־hash של הסיסמה הזו באמצעות פונקציית ה־hash שכתבנו בתחילת מחברת זו.
  6. \n", + "
  7. הבנק ישמור את שם המשתמש ותוצאת ה־hash בקובץ הסיסמאות בצורה קבועה מראש.
  8. \n", + "
\n", + "\n", + "

\n", + " כל סיסמה של משתמש תשמר בקובץ בצורה: username:62242,
\n", + " כאשר username הוא שם המשתמש שנרשם בפתיחת החשבון, ו־62242 הוא תוצאת ה־hash על הסיסמה שבחר.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### פתיחת חשבון בנק" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

בסעיף זה נממש את פונקציית פתיחת חשבון הבנק.
\n", + " הפונקציה תקבל שם משתמש וסיסמה, ותיצור רשומה חדשה בקובץ הסיסמאות עבור המשתמש שביקש להצטרף לבנק.
\n", + " כיוון שהבנק שלנו לא עבר לעבוד עם מספרי חשבון, עלינו לוודא שלא ששם המשתמש שנבחר לא קיים כבר בבנק, אם קיים כזה נדפיס שגיאה ולא נבצע דבר.
\n", + " אם לא קיים שם משתמש שכזה, נחשב את ה־hash של הסיסמה שהזין, ונוסיף לסוף הקובץ רשומה חדשה בייצוג שצוין בתחילת השאלה.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### דוגמאות" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + "תוכן קובץ הסיסמאות (לצורך הדוגמה):\n", + "

\n", + "\n", + "FreddieMercury:56443
\n", + "BBKing:33471
\n", + "DonaldDuck:17743

\n", + "register_to_bank('FreddieMercury', 'ILoveQueen')
\n", + "An account with name \"FreddieMercury\" already exists.
Account was not created.


\n", + "register_to_bank('Simba', 'ILoveNala')
\n", + "Account with name \"Simba\" was created and added to the bank.

\n", + "\n", + "

\n", + " תוכן קובץ הסיסמאות כעת:\n", + "

\n", + "\n", + "FreddieMercury:56443
\n", + "BBKing:19463
\n", + "DonaldDuck:17743
\n", + "Simba:6362
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### תרגיל" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

ממשו את פונקציית הרישום.

\n", + "

רמזים:

\n", + "\n", + "
    \n", + "
  • קראו את המידע מהקובץ לתוך רשימה, זכרו שכל שורה היא מחרוזת וניתן להפעיל עליה פעולות של מחרוזות לחילוץ שם המשתמש.
  • \n", + "
  • יש מצב פתיחה של קובץ שבאמצעותו ניתן להוסיף לקובץ קיים. קראו על פונקציית open וחפשו כיצד עושים זאת.
  • \n", + "
" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "# ממשו את פונקציית הרישום כאן register_to_bank(username,password)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### מערכת הזדהות" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " בעקבות השיפורים בחוזק הסיסמאות הצטרפו הרבה לקוחות לבנק.
\n", + " המנהלים מרוצים וכעת רוצים שתממשו עבורם מערכת הזדהות שעובדת עם קובץ הסיסמאות.\n", + "

\n", + "\n", + "

\n", + " מערכת ההזדהות תעבוד באופן הבא:\n", + "

\n", + "\n", + "
    \n", + "
  • הלקוח יכניס שם משתמש וסיסמה.\n", + "
      \n", + "
    • במידה והמשתמש לא קיים, נדפיס Account not registered. ונסיים.
    • \n", + "
    • במידה והלקוח קיים, אך הסיסמה לא נכונה – יש ללקוח עוד 2 נסיונות לספק סיסמה נכונה.
    • \n", + "
    \n", + "
  • \n", + "
  • למשתמש ינתנו 3 ניסיונות בסך־הכל להכניס סיסמה נכונה.\n", + "
      \n", + "
    • אם לא סיפק סיסמה נכונה בשלושתן – הרשומה שלו תימחק מקובץ הסיסמאות, ויהיה עליו להירשם מחדש בעתיד.
    • \n", + "
    • אחרת, הזיהוי הצליח.
    • \n", + "
    \n", + "
  • \n", + "
\n", + "\n", + "

\n", + " מערכת ההזדהות הינה פונקציה המקבלת שם משתמש וסיסמה.
\n", + " היא מחזירה True אם הזיהוי הצליח, ו־False אחרת.\n", + "

" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### דוגמאות" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " תוכן קובץ הסיסמאות (לצורך הדוגמה):\n", + "

\n", + "\n", + "
\n", + "\n", + "FreddieMercury:61875
\n", + "BBKing:33471
\n", + "DonaldDuck:17743

\n", + "authenticate('FreddieMercury', 'ILoveQueen')
\n", + "Wrong password (1/3). # myhash('ILoveQueen') = 99597 != 61875 (in password file)

\n", + "authenticate('FreddieMercury', 'LetItBe')
\n", + "Wrong password (2/3). # myhash('LetItBe') = 58060 != 61875 (in password file)

\n", + "authenticate('FreddieMercury', 'HeyJude')
\n", + "Wrong password (3/3). 'FreddieMercury' was removed. # myhash('HeyJude') = 8309 != 61875 (in password file)

\n", + "authenticate('FreddieMercury', 'IHatePasswords!')
\n", + "Account not registered. # FreddieMercury was removed in the previous example

\n", + "\n", + "authenticate('Simba', 'ILoveNala')
\n", + "Welcome 'Simba'. # myhash('ILoveNala') = 6362 == 6362 (in password file)

\n", + "\n", + "

\n", + " תוכן קובץ הסיסמאות כעת:\n", + "

\n", + "\n", + "
\n", + "\n", + "BBKing:19463
\n", + "DonaldDuck:17743
\n", + "Simba:6362
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "#### תרגול" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "

\n", + " ממשו את מערכת ההזדהות.\n", + "

" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# authenticate(username,password) ממשו את הפונקציה כאן" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.1" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/week3/images/binary-png-representation.png b/week3/images/binary-png-representation.png new file mode 100644 index 0000000..4c1a7e1 Binary files /dev/null and b/week3/images/binary-png-representation.png differ diff --git a/week3/images/exercise.svg b/week3/images/exercise.svg new file mode 100644 index 0000000..819a775 --- /dev/null +++ b/week3/images/exercise.svg @@ -0,0 +1,48 @@ + + + + + + + + diff --git a/week3/images/logo.png b/week3/images/logo.png new file mode 100644 index 0000000..0f1d548 Binary files /dev/null and b/week3/images/logo.png differ diff --git a/week3/images/textual-csv-representation.png b/week3/images/textual-csv-representation.png new file mode 100644 index 0000000..849f213 Binary files /dev/null and b/week3/images/textual-csv-representation.png differ diff --git a/week3/images/tip.png b/week3/images/tip.png new file mode 100644 index 0000000..a563b03 Binary files /dev/null and b/week3/images/tip.png differ diff --git a/week3/images/warning.png b/week3/images/warning.png new file mode 100644 index 0000000..4863041 Binary files /dev/null and b/week3/images/warning.png differ diff --git a/week3/images/while-flow.svg b/week3/images/while-flow.svg new file mode 100644 index 0000000..abae954 --- /dev/null +++ b/week3/images/while-flow.svg @@ -0,0 +1,2 @@ + +
הלכת לישון
הלכת לישון<br>
כל עוד
השעה היא לפני 8:00
[Not supported by viewer]
קום מהמיטה
קום מהמיטה
כבה את השעון
כבה את השעון<br>
לחץ על "נודניק"
וחזור לישון
[Not supported by viewer]
כן
כן
לא
לא
האם
השעון מצלצל?
[Not supported by viewer]
לא
לא
כן
כן
\ No newline at end of file diff --git a/week3/images/while-song.svg b/week3/images/while-song.svg new file mode 100644 index 0000000..d1124fe --- /dev/null +++ b/week3/images/while-song.svg @@ -0,0 +1,2 @@ + +
סיים את השיר
סיים את השיר
התחל את השיר
התחל את השיר
שמור בהמספר הנוכחי
את הערך 2
[Not supported by viewer]
שמור בסכום המספרים
את המספר הנוכחי ועוד
המספר הנוכחי
[Not supported by viewer]
המספר הנוכחי קטן
?או שווה ל־16
[Not supported by viewer]
כן
[Not supported by viewer]
לא
לא
:הדפס
המספר הנוכחי ועוד
המספר הנוכחי הם
סכום המספרים
[Not supported by viewer]
שמור במספר הנוכחי את
סכום המספרים
[Not supported by viewer]
\ No newline at end of file diff --git a/week3/resources/cereal.csv b/week3/resources/cereal.csv new file mode 100644 index 0000000..815c27c --- /dev/null +++ b/week3/resources/cereal.csv @@ -0,0 +1,78 @@ +name,mfr,type,calories,protein,fat,sodium,fiber,carbo,sugars,potass,vitamins,shelf,weight,cups,rating +100% Bran,N,C,70,4,1,130,10,5,6,280,25,3,1,0.33,68.402973 +100% Natural Bran,Q,C,120,3,5,15,2,8,8,135,0,3,1,1,33.983679 +All-Bran,K,C,70,4,1,260,9,7,5,320,25,3,1,0.33,59.425505 +All-Bran with Extra Fiber,K,C,50,4,0,140,14,8,0,330,25,3,1,0.5,93.704912 +Almond Delight,R,C,110,2,2,200,1,14,8,-1,25,3,1,0.75,34.384843 +Apple Cinnamon Cheerios,G,C,110,2,2,180,1.5,10.5,10,70,25,1,1,0.75,29.509541 +Apple Jacks,K,C,110,2,0,125,1,11,14,30,25,2,1,1,33.174094 +Basic 4,G,C,130,3,2,210,2,18,8,100,25,3,1.33,0.75,37.038562 +Bran Chex,R,C,90,2,1,200,4,15,6,125,25,1,1,0.67,49.120253 +Bran Flakes,P,C,90,3,0,210,5,13,5,190,25,3,1,0.67,53.313813 +Cap'n'Crunch,Q,C,120,1,2,220,0,12,12,35,25,2,1,0.75,18.042851 +Cheerios,G,C,110,6,2,290,2,17,1,105,25,1,1,1.25,50.764999 +Cinnamon Toast Crunch,G,C,120,1,3,210,0,13,9,45,25,2,1,0.75,19.823573 +Clusters,G,C,110,3,2,140,2,13,7,105,25,3,1,0.5,40.400208 +Cocoa Puffs,G,C,110,1,1,180,0,12,13,55,25,2,1,1,22.736446 +Corn Chex,R,C,110,2,0,280,0,22,3,25,25,1,1,1,41.445019 +Corn Flakes,K,C,100,2,0,290,1,21,2,35,25,1,1,1,45.863324 +Corn Pops,K,C,110,1,0,90,1,13,12,20,25,2,1,1,35.782791 +Count Chocula,G,C,110,1,1,180,0,12,13,65,25,2,1,1,22.396513 +Cracklin' Oat Bran,K,C,110,3,3,140,4,10,7,160,25,3,1,0.5,40.448772 +Cream of Wheat (Quick),N,H,100,3,0,80,1,21,0,-1,0,2,1,1,64.533816 +Crispix,K,C,110,2,0,220,1,21,3,30,25,3,1,1,46.895644 +Crispy Wheat & Raisins,G,C,100,2,1,140,2,11,10,120,25,3,1,0.75,36.176196 +Double Chex,R,C,100,2,0,190,1,18,5,80,25,3,1,0.75,44.330856 +Froot Loops,K,C,110,2,1,125,1,11,13,30,25,2,1,1,32.207582 +Frosted Flakes,K,C,110,1,0,200,1,14,11,25,25,1,1,0.75,31.435973 +Frosted Mini-Wheats,K,C,100,3,0,0,3,14,7,100,25,2,1,0.8,58.345141 +Fruit & Fibre Dates & Walnuts & and Oats,P,C,120,3,2,160,5,12,10,200,25,3,1.25,0.67,40.917047 +Fruitful Bran,K,C,120,3,0,240,5,14,12,190,25,3,1.33,0.67,41.015492 +Fruity Pebbles,P,C,110,1,1,135,0,13,12,25,25,2,1,0.75,28.025765 +Golden Crisp,P,C,100,2,0,45,0,11,15,40,25,1,1,0.88,35.252444 +Golden Grahams,G,C,110,1,1,280,0,15,9,45,25,2,1,0.75,23.804043 +Grape Nuts Flakes,P,C,100,3,1,140,3,15,5,85,25,3,1,0.88,52.076897 +Grape-Nuts,P,C,110,3,0,170,3,17,3,90,25,3,1,0.25,53.371007 +Great Grains Pecan,P,C,120,3,3,75,3,13,4,100,25,3,1,0.33,45.811716 +Honey Graham Ohs,Q,C,120,1,2,220,1,12,11,45,25,2,1,1,21.871292 +Honey Nut Cheerios,G,C,110,3,1,250,1.5,11.5,10,90,25,1,1,0.75,31.072217 +Honey-comb,P,C,110,1,0,180,0,14,11,35,25,1,1,1.33,28.742414 +Just Right Crunchy Nuggets,K,C,110,2,1,170,1,17,6,60,100,3,1,1,36.523683 +Just Right Fruit & Nut,K,C,140,3,1,170,2,20,9,95,100,3,1.3,0.75,36.471512 +Kix,G,C,110,2,1,260,0,21,3,40,25,2,1,1.5,39.241114 +Life,Q,C,100,4,2,150,2,12,6,95,25,2,1,0.67,45.328074 +Lucky Charms,G,C,110,2,1,180,0,12,12,55,25,2,1,1,26.734515 +Maypo,A,H,100,4,1,0,0,16,3,95,25,2,1,1,54.850917 +Muesli Raisins & Dates & Almonds,R,C,150,4,3,95,3,16,11,170,25,3,1,1,37.136863 +Muesli Raisins & Peaches & Pecans,R,C,150,4,3,150,3,16,11,170,25,3,1,1,34.139765 +Mueslix Crispy Blend,K,C,160,3,2,150,3,17,13,160,25,3,1.5,0.67,30.313351 +Multi-Grain Cheerios,G,C,100,2,1,220,2,15,6,90,25,1,1,1,40.105965 +Nut&Honey Crunch,K,C,120,2,1,190,0,15,9,40,25,2,1,0.67,29.924285 +Nutri-Grain Almond-Raisin,K,C,140,3,2,220,3,21,7,130,25,3,1.33,0.67,40.692320 +Nutri-grain Wheat,K,C,90,3,0,170,3,18,2,90,25,3,1,1,59.642837 +Oatmeal Raisin Crisp,G,C,130,3,2,170,1.5,13.5,10,120,25,3,1.25,0.5,30.450843 +Post Nat. Raisin Bran,P,C,120,3,1,200,6,11,14,260,25,3,1.33,0.67,37.840594 +Product 19,K,C,100,3,0,320,1,20,3,45,100,3,1,1,41.503540 +Puffed Rice,Q,C,50,1,0,0,0,13,0,15,0,3,0.5,1,60.756112 +Puffed Wheat,Q,C,50,2,0,0,1,10,0,50,0,3,0.5,1,63.005645 +Quaker Oat Squares,Q,C,100,4,1,135,2,14,6,110,25,3,1,0.5,49.511874 +Quaker Oatmeal,Q,H,100,5,2,0,2.7,-1,-1,110,0,1,1,0.67,50.828392 +Raisin Bran,K,C,120,3,1,210,5,14,12,240,25,2,1.33,0.75,39.259197 +Raisin Nut Bran,G,C,100,3,2,140,2.5,10.5,8,140,25,3,1,0.5,39.703400 +Raisin Squares,K,C,90,2,0,0,2,15,6,110,25,3,1,0.5,55.333142 +Rice Chex,R,C,110,1,0,240,0,23,2,30,25,1,1,1.13,41.998933 +Rice Krispies,K,C,110,2,0,290,0,22,3,35,25,1,1,1,40.560159 +Shredded Wheat,N,C,80,2,0,0,3,16,0,95,0,1,0.83,1,68.235885 +Shredded Wheat 'n'Bran,N,C,90,3,0,0,4,19,0,140,0,1,1,0.67,74.472949 +Shredded Wheat spoon size,N,C,90,3,0,0,3,20,0,120,0,1,1,0.67,72.801787 +Smacks,K,C,110,2,1,70,1,9,15,40,25,2,1,0.75,31.230054 +Special K,K,C,110,6,0,230,1,16,3,55,25,1,1,1,53.131324 +Strawberry Fruit Wheats,N,C,90,2,0,15,3,15,5,90,25,2,1,1,59.363993 +Total Corn Flakes,G,C,110,2,1,200,0,21,3,35,100,3,1,1,38.839746 +Total Raisin Bran,G,C,140,3,1,190,4,15,14,230,100,3,1.5,1,28.592785 +Total Whole Grain,G,C,100,3,1,200,3,16,3,110,100,3,1,1,46.658844 +Triples,G,C,110,2,1,250,0,21,3,60,25,3,1,0.75,39.106174 +Trix,G,C,110,1,1,140,0,13,12,25,25,2,1,1,27.753301 +Wheat Chex,R,C,100,3,1,230,3,17,3,115,25,1,1,0.67,49.787445 +Wheaties,G,C,100,3,1,200,3,17,3,110,25,1,1,1,51.592193 +Wheaties Honey Gold,G,C,110,2,1,200,1,16,8,60,25,1,1,0.75,36.187559 diff --git a/week3/resources/hope.txt b/week3/resources/hope.txt new file mode 100644 index 0000000..c360621 --- /dev/null +++ b/week3/resources/hope.txt @@ -0,0 +1,14 @@ +בַּעֲלַת-הַנוֹצָה הִיא תִּקְוָה +– תִשְׁכֹּן בַּנְּשָׁמָה זוּ +הַמִּלִּים, בְּלִי הַנִּגּוּן אֶת הִיא שָׁרָה +– מִשִּׁיר פּוֹסֶקֶת וְאֵינָהּ + +בְּיוֹתֵר? תִּמְתַּק מָתַי רִנָּתָהּ +הַסּוּפָה תְהִי וְקָשָׁה-מָרָה – תָסְכַּת בִּסְעָרָה עֵת +הַקְּטַנָּה, הַצִּפּוֹר אֶת תַּכְלִים תּוּכַל אֲשֶׁר +חִמֵּמָה. רַבִּים כֹּה זוּ + +– קָרוֹת-מִקֹּר בַּאֲרָצוֹת שְׁמַעְתִּיהָ +– זָרִים-מוּזָרִים יַמִּים וְעַל +בְּעֹצֶם-מְצוּקָה, גַּם אֵלֶּה, וּבְכָל +מִמֶּנִּי. – פֵּרוּר בִּקְּשָׁה לֹא מֵעוֹלָם \ No newline at end of file diff --git a/week3/resources/passwords.txt b/week3/resources/passwords.txt new file mode 100644 index 0000000..1b9df6a --- /dev/null +++ b/week3/resources/passwords.txt @@ -0,0 +1,25 @@ +123456 +password +123456789 +12345678 +12345 +111111 +1234567 +sunshine +qwerty +iloveyou +princess +admin +welcome +666666 +abc123 +football +123123 +monkey +654321 +!@#$%^&* +charlie +aa123456 +donald +password1 +qwerty123 \ No newline at end of file