תרגילים נוספים: שבוע 3

זוהי רשימת תרגילים חלקית.
פתרונות ותרגילים נוספים יתווספו בהמשך השבוע.

מחברת 1

תרגיל 1 (בר ולטר)

אקרוסטיכון היא שיטת כתיבה של שיר או פרוזה, בה ליקוט האות הראשונה של כל מילה, שורה או בית בשיר יוצר מילה או מספר מילים, שם, אותיות האלפבית כסדרן וכדומה.

סעיף 1

כתבו תוכנית שמקבלת מהמשתמש מחרוזת, ומדפיסה מחרוזת חדשה המורכבת מהאות הראשונה בכל מילה מהמחרוזת המקורית.

עבור הקלט “יש ווילונות פירחוניים יותר”, יודפס: יופי
עבור הקלט “משהו עצום וגדול להביא הביתה”, יודפס: מעולה
עבור הקלט “אני חייב לאכול המבורגר”, יודפס: אחלה
עבור הקלט “כדי להבריא, הומלץ כעת בידוד וגם דוקטור” יודפס: כלהכבוד

סעיף 2

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

  1. עבור הקלט “אני חייב לאכול המבורגר” ואז “word”, יודפס: אחלה

  2. עבור הקלט: “לילה לילה
    מכה אפורה
    האוטו שלנו” ואז “line”, יודפס: למה

  3. עבור הקלט: “החלמ ולחמצחל
    זלמלח חלמח
    טחלמחל ילמלחמ” ואז “word”, יודפס “הוזחטי”

סעיף 3

בשיר “אדון הסליחות” יש “אקרוסתיכון מיוחד”.
הוא מורכב מהאות הראשונה של כל שורה שאינה השורה האחרונה של הפסקה.
כתבו תוכנית שמקבלת את הטקסט של השיר ומחזירה את האקרוסטיכון המיוחד שלו.

השיר נמצא כאן

אֲדוֹן הַסְּלִיחוֹת
בּוֹחֵן לְבָבוֹת
גּוֹלֶה עֲמוּקוֹת
דּוֹבֵר צְדָקוֹת
חָטָאנוּ לְפָנֶיךָ, רַחֵם עָלֵינוּ!

הָדוּר בְּנִפְלָאוֹת
וָתִיק בְּנֶחָמוֹת
זוֹכֵר בְּרִית אָבוֹת
חוֹקֵר כְּלָיוֹת
חָטָאנוּ לְפָנֶיךָ, רַחֵם עָלֵינוּ!

טוֹב וּמֵטִיב לַבְּרִיּוֹת
יוֹדֵעַ כָּל נִסְתָּרוֹת
כּוֹבֵשׁ עֲוֹנוֹת
לוֹבֵשׁ צְדָקוֹת
חָטָאנוּ לְפָנֶיךָ, רַחֵם עָלֵינוּ!

מָלֵא זַכִּיּוֹת
נוֹרָא תְהִלּוֹת
סוֹלֵחַ עֲוֹנוֹת
עוֹנֶה בְּעֵת צָרוֹת
חָטָאנוּ לְפָנֶיךָ, רַחֵם עָלֵינוּ!

פּוֹעֵל יְשׁוּעוֹת
צוֹפֶה עֲתִידוֹת
קוֹרֵא הַדּוֹרוֹת
רוֹכֵב עֲרָבוֹת
שׁוֹמֵעַ תְּפִלּוֹת
תְּמִים דֵּעוֹת
חָטָאנוּ לְפָנֶיךָ, רַחֵם עָלֵינוּ!

תרגיל 2 (בר ולטר)

בסופר הקורונה, אסור שיהיו יותר מ 100 אנשים בו זמנית.
נקבל מהמשתמש את מספר העובדים וכך נדע כמה לקוחות ניתן להכניס.
לדוגמה: אם יש בסופר 20 עובדים, ניתן להכניס עד 80 לקוחות (100-20 = 80).

התוכנית מתחילה כאשר הסופר נפתח, כלומר יש בו 0 לקוחות.
התוכנית תשאל כמה עובדים יש בסופר ומכך תבין כמה לקוחות ניתן להכניס.

כל פעם שקבוצה נכנסת או יוצאת, נקלוט מהמשתמש את קבוצת האנשים הבאה.
אם האנשים נכנסים – המספר חיובי, אם האנשים יוצאים – המספר שלילי.

התוכנית מסתיים כאשר יוכנס “close” אשר מסמל כי החנות נסגרת ולא ניתן להכנס יותר!

תרגיל 3 (איתמר רביב)

חפיסת קלפים סטנדרטית מכילה 52 קלפים. לכל קלף בחבילה יש את המאפיינים הבאים:

  • צורה (Suite) – תלתן, עלה, לב או יהלום
  • צבע (Color) – לב ויהלום יהיו אדומים, עלה ותלתן יהיו שחורים.
  • דרגה (Rank) – אס (1), המספרים מ־2 ועד 10, נסיך, מלכה ומלך.

בחפיסה סטנדרטית, בכל צורה יופיעו כל אחת מהדרגות פעם אחת בדיוק (13 קלפים עבוור כל סמל).
כתבו פונקציה המייצרת חפיסת קלפים, הפונקציה תחזיר רשימה של כל הקלפים - בדקו שקיבלתם 52 קלפים ברשימה.

מחברת 2

תרגיל 1 (בר ולטר)

קבלו מחרוזת ואות והחזירו רשימה של המקומות בהן היא מופיעה

לדוגמה:

  1. עבור הקלט"abcdabcdabcdabcd"’, “c” יודפס: [2, 6, 10, 14]
  2. עבור הקלט “'how are you doing”, “z” יודפס: “'Not in list”

מחברת 3

תרגיל 1 (איתמר רביב)

  1. במשתנה secret שניתן להשיג מכאן ישנה מחרוזת המייצגת תמונה. כתבו את תוכן המשתנה לקובץ עם סיומת .png וגלו מה יש בתמונה. שימו לב למצבי הכתיבה לקובץ בפונקציית open - עליכם לכתוב לקובץ במצב “בינארי”.

מחברת 5

תרגיל 1 (איתמר רביב)

ניתן לייצג “משימה” כרשומה בעזרת tuple.
כתבו פונקציה המקבלת את כל המידע המפורט מטה ומחזירה tuple המייצג משימה.

  1. תאריך הוספה
  2. תאריך דדליין
  3. תיאור – טקסט המתאר את המשימה
  4. שם המבצע אליו משויכת המשימה
  5. האם המשימה הסתיימה (בוצעה)

כתבו תוכנית (אוסף של פונקציות) המנהלת רשימת משימות על גבי קובץ שנקרא לו tasks.csv.

התוכנית תאפשר:

  1. קליטת משימות חדשות ושמירתן בקובץ
  2. הדפסת רשימת המשימות
    2.1 אפשרו סוגי סינונים שונים - לפי מבצע, לפי תאריך או לפי האם המשימה הסתיימה.
  3. פונקציה שמאפשרת לסמן משימה כמשימה שבוצעה.
  4. הדפסת המשימות שעבר הדדליין שלהן

את המשימות שמרו בקובץ כך שכל משימה בשורה נפרדת, וכל השדות מופרדים בפסיק.
השורה הראשונה בקובץ תהיה השדות של המשימה כפי שהוזכרו מעלה, בתוספת שדה ראשון בשם id המהווה מזהה ייחודי של משימה. המזהה של המשימה הראשונה הוא 1, של הבאה אחריה 2 וכן הלאה.

כך נראה קובץ csv ובו שלוש משימות:

ID,date,due_date,description,assignee,isdone
1,20.04.2020,25.04.2020,create todo list system,Moti,False
2,21.04.2020,25.04.2020,break the wall,Shlomo,True
3,23.04.2020,24.04.2020,eat a shwarma,David Momo,False
לייק 1

עדיף לגשת אליהם בסיום הגשת התרגילים של שבוע 3?
לדעתך מומלץ לכולם לעשות אותם למרות שהם לא להגשה או שזה יותר בגדר חזרה נוספת?

יש כאלו גם לשבוע 1 וגם לשבוע 2.
ממליץ לעשות אחרי סיום תרגילי המחברות נטו כדי להימנע ממצב של איחור בהגשה.
מאמין שתרגול תמיד יכול לעזור למצוא נקודות חולשה ולחזק, ובניגוד לתרגילים האחרים על התרגילים האלו אנחנו מרשים לפרסם פתרונות ולדסקס (ומפרסמים גם את פתרונות הסגל)

לייק 1

מחברת 3 תרגיל 1:

משהו לא מסתדר לי בתמונה שאני מקבל (מצב)


מה יכולה להיות הטעות ?

לייק 1

הסתכלתי עכשיו על המחרוזת ואין מצב שזה bmp, יש מצב שזו עריכה שביצעתי לתרגיל של איתמר.
רוצה לנסות רגע לשנות את הסיומת ל־png?

אני מקבל את אותה התוצאה =\
אני חושב שיש משהו שאני עושה לא נכון, האם יש צורך לעשות משהו למחרוזת עצמה ?

באינטרנט מצאתי איזה שהוא הסבר שצריך לעשות אולי encoding
אבל זה מחזיר לי בכלל שגיאה.

לייק 1

ניסיתי בעצמי, פתרת כמו שצריך :laughing: זו אשמתי.
אם תרצה, עדכנתי את הקישור למשתנה שיביא תמונה בעלת משמעות :slight_smile:

אני לא בטוח שאתה טעית.
תראה מה קיבלתי עם הקוד החדש:

אם זו תמונה בעלת משמעות - אני איבדתי כל משמעות :slight_smile:
הכתם הצהוב אני יכול רק לנחש מה זה :sun_with_face:

באסה, זה כנראה משהו שנדפק בהעברה ל־pastebin. אבל כן הבנת את הרעיון XP

לייק 1

טוב נו, היו זמנים שדברים כאלה הפכו לאומנות אז נשאר שמחים :blush:

לייק 1

שאלה בנוגע למחברת 5 תרגיל 1:

האם זו מערכת פונקציות שעובדת בצורה “אינסופית” עם ממשק שעובד כמו תפריט ומאפשר לי לנהלת פעולות שונות בסדר לא כרונולוגי?
למשל: לעבור בין קליטת משימות להדפסת רשימות ואז שוב לקליטת משימות וכו …

או שמא אנו אמורים לעשות פשוט פונקציות נפרדות שבעתיד יוכלו להיות מוטמעות לכדי תוכנית שרצה
בצורה שותפת שכזו.

Why not both? :slight_smile:

לייק 1

שאלה לגבי הפעולה סימן קריאה על קובץ (!)
הצלחתי להריץ את הפעולה ! כל עוד הקובץ נמצא באותה תיקייה,
אבל אם הקובץ נמצא בתיקייה אחרת, איך ניתן להריץ אותו?

היי, עשיתי את תרגיל 1 מחברת 5 (רשימת מטלות) בגדול זה עובד
אבל מרגיש לי שיצא לי ממש מסורבל וזה עוד בלי שעשיתי בדיקות קלט למה שנכנס לי במשימה עצמה
אלא בדיקות קלט רק למה שמוזן אצלי בממשק עצמו.

אני לא רוצה להכביד על הצוות, אבל אם יתפנה בקטע הזוי זמן, הייתי שמח אם מישהו יוכל להציץ בזה :slight_smile:

מוזמן לפרסם את הפתרון פה, אשמח להציץ :slight_smile:

זה דיי ארוך (ממליץ להריץ כדי לראות את ההפועה של המחרוזות)

קוד
# Run this if its the first time
# with open('tasks.csv', 'w') as file:
#     title = 'id,added time,expire time,task,name,finished\n'
#     file.write(title)

# Input validation functions


def is_menu_input_valid(user_choose):
    if len(user_choose) == 1 and user_choose.isdecimal() and ( 0 <= int(user_choose) <= 4):
        return True
    return False


def is_filter_input_valid(user_choose):
    if len(user_choose) == 1 and user_choose.isdecimal() and ( 0 <= int(user_choose) <= 5) and int(user_choose) != 3:
        return True
    return False


# Filters


def choose_filter():
    filter_choosed = ['','']
    is_valid = False
    while not is_valid:
        filter_choosed[0] = input("""Insert number of filter to preform:
        \t0 - By Id
        \t1 - By Date Of Creation
        \t2 - By Expiration Date
        \t4 - By Name of Responsible
        \t5 - By Done or Not
            """)

        if is_filter_input_valid(filter_choosed[0]):
            is_valid = True
            filter_choosed[0] = int(filter_choosed[0])
        else:
            print("** Value is not valid **".upper())

    if filter_choosed[0] == 0:
        filter_choosed[1] = input("Enter ID: ")
    elif filter_choosed[0] == 1:
        filter_choosed[1] = input("Enter Date Of Creation: ")
    elif filter_choosed[0] == 2:
        filter_choosed[1] = input("Enter Date Of Creation: ")
    elif filter_choosed[0] == 4:
        filter_choosed[1] = input("Enter Task Name of Responsible: ")
    elif filter_choosed[0] == 5:
        done_or_not = input("Enter 0 to see Done tasks or 1 for  Not Done: ")
        if done_or_not == '0':
            filter_choosed[1] = 'True'
        else:
            filter_choosed[1] = 'False'
    return filter_choosed


# Task managment functions


def get_task():
    print("lets add a new task: ".upper())
    recuired_input = ["Add current date: ", "Add task expierd date: ","Type task: ", "Who is responsible for the task: ", "Is task completed (y/n): "]
    counter = 0
    task = []
    while counter < len(recuired_input):
        if counter == len(recuired_input) - 1:
            is_complete = input(recuired_input[counter])
            if is_complete == 'y':
                task.append('True')
            else:
                task.append('False')
        else:
            task.append(input(recuired_input[counter]).lower())
        counter += 1
    return tuple(task)


def add_task(task):
    with open('tasks.csv', 'r') as file:
        all_tasks = file.readlines()

    # get the last id
    last_task = all_tasks[len(all_tasks) - 1].split(',')
    if len(all_tasks) == 1:
        last_id = 0
    else:
        last_id = int(last_task[0])

    next_id = str(last_id + 1)
    new_task_as_string = next_id + ',' + ','.join(task) + "\n"

    with open('tasks.csv', 'a') as file:
        file.write(new_task_as_string)

    return "** Task Added **".upper()


def show_all_tasks():
    with open('tasks.csv', 'r') as file:
        all_tasks = file.readlines()

    counter = 0
    while counter < len(all_tasks):
        task_as_list = all_tasks[counter].split(',')
        print(all_tasks[counter].split(','))
        counter += 1


def show_by_filter(filter_id, content):
    with open('tasks.csv', 'r') as file:
        all_tasks = file.readlines()

    counter = 0
    while counter < len(all_tasks):
        task_as_list = all_tasks[counter].split(',')
        if task_as_list[filter_id].strip() == content:
            print(all_tasks[counter].split(','))
        counter += 1


def done_task(task_id):
    with open('tasks.csv', 'r') as file:
        all_tasks = file.readlines()

    if (0 < task_id < len(all_tasks)):
        task = all_tasks[task_id].split(',')
        if task[-1] == 'True\n':
            print('Task Is Already Done')
        else:
            task[-1] = 'True\n'
            all_tasks[task_id] = ','.join(task)
            all_tasks = ''.join(all_tasks)
            with open('tasks.csv', 'w') as file:
                file.write(all_tasks)
            print("** Task done **".upper())
    else:
        print("** Id is not exists **".upper())


# System Function


def menu(lists_of_tasks):
    is_runing = True
    while is_runing:
        user_choose = input("""\nHello Again, Insert number of action to preform:
        \t0 - Exit
        \t1 - Add Task
        \t2 - Mark Task As Done
        \t3 - Show By Filter
        \t4 - Show All Tasks
            """)

        if is_menu_input_valid(user_choose):
            user_choose = int(user_choose)
            if user_choose == 0:
                is_runing = False
            elif user_choose == 1:
                task = lists_of_tasks[user_choose - 1]()
                add_task(task)
            elif user_choose == 2:
                task_id = int(input("Enter task ID to mark as Done"))
                lists_of_tasks[user_choose - 1](task_id)
            elif user_choose == 3:
                user_filter = choose_filter()
                current_filter = lists_of_tasks[user_choose - 1](user_filter[0], user_filter[1])
            elif user_choose == 4:
                lists_of_tasks[user_choose - 1]()
            else:
                lists_of_tasks[user_choose - 1]()
        else:
            print("** Value is not valid **".upper())
    
    return "** Exit is done **".upper()


lists_of_tasks = [get_task, done_task, show_by_filter, show_all_tasks]
print(menu(lists_of_tasks))

תודה ים :heart_eyes:

לייק 1
  1. ב־is_menu_input_valid / is_filter_input_valid – מצא דרך לממש את הפונקציה בשורה אחת
  2. בנוגע למחרוזות תפריט – אולי הייתי בונה פונקציה שמדפיסה אותן כדי להפריד לוגיקה מתצוגה
  3. את filter_choosed[0] הייתי מכניס למשתנה כדי לא לחזור עליו הרבה פעמים, ובאופן כללי את כל ה־if/elif הייתי מוציא לפונק’
  4. אהבתי מה שעשית עם get_task, שים לב שאת ה־if שם יש דרך לממש בשורה אחת. באופן כללי יש מצב שהייתי מוציא את התנאי של ה־if וכו’ מחוץ ללולאה שם
  5. אתה חוזר על הקוד של קריאת הקובץ כמה פעמים בכל מני מקומות, יתכן שעדיף לחלץ אותו לפונקציה אחת
  6. את task.csv אפשר לשמור כמשתנה גלובאלי (בראש הקוד, מחוץ לפונקציות). זה יאפשר לכולן לגשת אליו, ואם תצטרך יום אחד לשנות אותו תוכל לעשות את זה במקום אחד בקוד. זה סבבה כי הוא Immutable ואנחנו לא עורכים אותו לאורך התוכנית, רק קוראים ממנו.
  7. את show_all_tasks הייתי מעדיף שתפצל לפונקציה שמחזירה את הרשימות, ועוד פונקציה שמדפיסה
  8. את if task[-1] == 'True\n': יותר אלגנטי לנסח כ:if task[-1].strip() == 'True':

זה מה שהסקתי ממעבר זריז על הקוד :slight_smile:
בסך הכל עבודה מצוינת

וואי תודה !! אני אעבור על זה ואתקן לעצמי.

תרגיל ממש לא פשוט היה לי יותר קשה מכל התרגילים השבוע.
בעיקר בגלל המורכבות שלו.

:blush:

לייק 1

אשמח להכוונה בתרגיל 3 עם התמונה. לא הבנתי מה אני צריכה לכתוב?

לכתוב את המחרוזת הבינארית שקיימת בלינק לתוך קובץ