490 likes | 692 Views
תכנות פונקציונאלי - II. רקורסיה מבוסס על: לירון, א., לפידות ת., לוי, ד. ופז, ת. (1999). תכנות פונקציונאלי – פרדיגמה תכנותית נוספת , המרכז הישראלי להוראת המדעים. תכנות פונקציונאלי - תיאורים רקורסיביים. להלן שלושה תיאורים רקורסיביים. לכל תיאור, ציירו את הציור המתאים לרמה 3.
E N D
תכנות פונקציונאלי - II רקורסיה מבוסס על:לירון, א., לפידות ת., לוי, ד. ופז, ת. (1999). תכנות פונקציונאלי – פרדיגמה תכנותית נוספת, המרכז הישראלי להוראת המדעים.
תכנות פונקציונאלי - תיאורים רקורסיביים להלן שלושה תיאורים רקורסיביים. לכל תיאור, ציירו את הציור המתאים לרמה 3. • מגדל ברמה N בנוי ממשולש שעליו מונח מגדל קטן יותר ברמהN-1. • המגדל הבסיסי הוא ברמה 1, וצורתו משולש . • עץ בינארי ברמה N בנוי מצורת V שבכל אחת מקצותיה עץ בינארי קטן יותר ברמהN-1. • העץ הבסיסי הוא ברמה 1, וצורתו V. • שטיח ברמה N בנוי מריבוע שבכל אחד מקדקודיו שטיח קטן יותר ברמהN-1. • השטיח הבסיסי הוא ברמה 1, וצורתו ריבוע.
תכנות פונקציונאלי - תיאורים רקורסיביים • נתונים תיאורים רקורסיביים. לכל תיאור, רשמו מספר ביטויים המתאימים לתיאור. • פלינדרום הוא מילה שהאות הראשונה והאחרונה שלה זהות, וביניהן נמצא פלינדרום קצר יותר. הפלינדרום הבסיסי מכיל אות אחת (כרצונכם). • מילה חוקית בשפת דג מתחילה באות ד' ומסתיימת באות ג', וביניהן נמצאת מילה חוקית קצרה יותר בשפת דג. המילה החוקית הבסיסית היא המילה הריקה (ללא תווים).
תכנות פונקציונאלי - תיאורים רקורסיביים • נתונים ארבעה תיאורים רקורסיביים. לכל תיאור, רשמו מספר ביטויים המתאימים לתיאור. • ביטוי חוקי נפתח בתו A , מסתיים בתו B, וביניהם נמצא ביטוי חוקי קצר יותר. הביטוי החוקי הבסיסי הוא התו C. • ביטוי חוקי נפתח בתו A, מסתיים בתו B, וביניהם נמצאים שני ביטויים חוקיים קצרים יותר. הביטוי החוקי הבסיסי הוא התו C .
תכנות פונקציונאלי – מציור לתיאור רקורסיבי תנו לעץ תיאור רקורסיבי.
תכנות פונקציונאלי - סיכום: חשיבה רקורסיבית • רקורסיה היא תופעה מיוחדת המופיעה בתחומים רבים. • הגדרה רקורסיבית של מושג היא הגדרה שבה מגדירים את המושג בעזרת הגדרה פשוטה יותר של אותו מושג. • חשוב לתת למושג שם שמתאר אותו. • המושג יכול להיות ציור, מילה, סדרה חשבונית, מבנה, או תהליך.
תכנות פונקציונאלי - סיכום: חשיבה רקורסיבית • הגדרה רקורסיבית מורכבת בדרך-כלל משני חלקים: • המקרה הבסיסי (הפשוט) ביותר, הנקרא גם תנאי העצירה. • המקרה הכללי, הנקרא גם הקריאה הרקורסיבית, המתאר את התופעה (המושג) בעזרת הגדרה פשוטה יותר של אותה תופעה (מושג).
תכנות פונקציונאלי - פונקציות רקורסיביות • נבנה אלגוריתם רקורסיבי לחישוב סכום האברים ברשימת מספרים. • נסחו את הפתרון באופן מילולי. • תרגמו את הפתרון המילולי לפונקציה.
תכנות פונקציונאלי - פונקציות רקורסיביות חישוב סכום אברי רשימה )define (sum_list l( (cond [(empty? l) 0[ [(+ (first l) (sum_list (rest l)))]))
תכנות פונקציונאלי - פונקציות רקורסיביות • אלגוריתם רקורסיבי לחישוב סכום האברים הזוגיים ברשימת מספרים. • נסחו את הפתרון באופן מילולי. • תרגמו את הפתרון המילולי לפונקציה.
תכנות פונקציונאלי - פונקציות רקורסיביות סכום האברים הזוגיים ברשימה )define (sum_even l) (cond [(empty? l) 0] [(even? (first l)) (+ (first l) (sum_even (rest l)))] [else (sum_even (rest l))]))
תכנות פונקציונאלי - פונקציות רקורסיביות הוצאת איבר מרשימה • דוגמאות: • אם נוציא מהרשימה(10 20 30 40) את האיבר השני, נקבל את הרשימה (10 30 40). • אם נוציא מהרשימה (what a nice day) את האיבר השלישי, נקבל את הרשימה (what a day). • באופן כללי: הפונקציה קולטת מספר i גדול מ- 0 ורשימה, ומחזירה את הרשימה ללא האיבר ה- i-י.
תכנות פונקציונאלי - פונקציות רקורסיביות בניה הדרגתית של הפונקציה. • נכתוב פונקציה without-1 המקבלת רשימה ומחזירה אותה ללא האיבר הראשון. • למשל: (without-1 ‘( 10 20 30 40 ) ) תחזיר (20 30 40). (define (without_1 l) (rest l))
תכנות פונקציונאלי - פונקציות רקורסיביות • נכתוב פונקציה without-2 המקבלת רשימה ומחזירה אותה ללא האיבר השני. • למשל, (without-2 ‘( 10 20 30 40 ) ) תחזיר (10 30 40). (define (without_2 l) (cons (first l)(without_1 (rest l))))
תכנות פונקציונאלי - פונקציות רקורסיביות • האם ניתן להיעזר בפונקציות הקודמות לכתיבת without-3? • נניח שהרשימה המקורית היא (10 20 30 40 50 60). נבדוק מה יחזירו הפונקציות הקודמות • (without_1 ‘(10 20 30 40 50 60)) ( 20 30 40 50 60) • (without_2 ‘(10 20 30 40 50 60)) ( 10 30 40 50 60) • כעת נכתוב פונקציה שתוציא מהרשימה את האיבר השלישי שלה. • (without_3 ‘(10 20 30 40 50 60)) ( 10 20 40 50 60 )
תכנות פונקציונאלי - פונקציות רקורסיביות • כדי להוציא מרשימה את האיבר השלישי שלה, ניתן להחזיר את האיבר הראשון לרשימה המתקבלת מהוצאת האיבר השני מהרשימה ללא האיבר הראשון. (define (without_3 l) (cons (first l)(without_2 (rest l)))) • נשלים את הפונקציה המוציאה מרשימה את האיבר הרביעי שלה.
תכנות פונקציונאלי - פונקציות רקורסיביות • מה משותף לפונקציות האחרונות? • כיצד ניתן להשתמש במשותף לפונקציות הקודמות בבניית הפונקציה הכללית without?
תכנות פונקציונאלי - פונקציות רקורסיביות • הפונקציה without המוציאה מרשימה L את האיבר הנמצא במקום n. (define (without n L) (cond [(= n 1) (rest L)] [else (cons (first L) (without (sub1 n) (rest L)))])) • מדוע תנאי העצירה הוא (= n 1) ? • מדוע במקרה זה מוחזרת שארית הרשימה (rest L)?
תכנות פונקציונאלי - פונקציות רקורסיביות, כלים לעיבוד רשימות • upto ("עד ל-" ):הפונקציה מקבלת רשימה L ואינדקס n ומחזירה את nהאיברים הראשונים ברשימה (עד לאיבר ה- n, כולל איבר זה). > (upto 3 ‘( alon gila roni miri moti yael )) (alon gila roni ) > (upto 2 ‘( 10 (2.5 3.5) x hello )) (10 (2.5 3.5 ) ) • בתהליך דומה לתהליך הקודם ניתן לבנות את הפונקציה: (define (upto n l) (cond [(= n 1)(cons (first l) '())] [else (cons (first l) (upto (sub1 n)(rest l)))]))
תכנות פונקציונאלי - פונקציות רקורסיביות, כלים לעיבוד רשימות • הפונקציה from ( "מ-" ): הפונקציה מקבלת רשימה L ואינדקס n ומחזירה את איברי הרשימה מהמקום ה-n ואילך. > (from 3 ‘( alon gila roni miri moti yael)) (roni miri moti yael ) > (from 2 ‘( 10 (2.5 3.5) x hello)) ((2.5 3.5) x hello) (define (from n l) (cond [(= n 1) l] [else (rest (from (sub1 n) l))]))
תכנות פונקציונאלי - פונקציות רקורסיביות, כלים לעיבוד רשימות • הניחו כי הכלים from, upto קיימים. • בנו באמצעותם פונקציה חדשה - (between L a b), המחזירה את איברי הרשימה L מהמקום a עד המקום b. > (between ‘( alon gila roni miri moti yael ) 3 5) (roni miri moti ) > ( between ‘( 10 (2.5 3.5) x hello ) 2 3 ) ( ( 2.5 3.5 ) x ) • הפונקציה between איננה רקורסיבית.
תכנות פונקציונאלי - פונקציות רקורסיביות, כלים לעיבוד רשימות • הפונקציה (between L a b) המחזירה את איברי הרשימה L מהמקום a עד המקום b: (define (between l a b) (upto (add1 (- b a)) (from a l))) > (between '(1 2 3 4 5 6 7) 2 4) (2 3 4) > (between '(1 2 3 4 5 6 7) 2 7) (2 3 4 5 6 7) > (between '(1 2 3 4 5 6 7) 4 4) (4)
תכנות פונקציונאלי - פונקציות רקורסיביות, כלים לעיבוד רשימות • הפונקציה (between L a b) המחזירה את איברי הרשימה L מהמקום a עד המקום b: (define (between l a b) (upto (add1 (- b a)) (from a l))) מה תהיה תגובת המחשב להוראות הבאות: > (between '(1 2 3 4 5 6 7) 1 8) > (between '(1 2 3 4 5 6 7) 1 7) > (between '(1 2 3 4 5 6 7) 3 2)
תכנות פונקציונאלי - פונקציות רקורסיביות, כלים לעיבוד רשימות • השתמשו בכלים from ו- upto להגדרת הפונקציה (insert L x n), המכניסה את האיבר x למקום ה- n ברשימה L. • דוגמאות: • (insert ‘(alon dalya roni miri) ‘gadi 3) • (alon dalya gadi roni miri) • (insert ‘(10 (2.5 3.5) x hello) ‘(a b c) 2) • (10 (a b c) (2.5 3.5) x hello) • הגדירו את הפונקציה insert כפונקציה רקורסיבית, ללא שימוש בכלים fromו- .upto
תכנות פונקציונאלי - פונקציות רקורסיביות • נושאים נוספים: • מסננות קלט: • מהן • בנייתן • באופן פשוט לבדיקת אופיו של אובייקט מסוים • בהמשך - לבדיקת אופיין של רשימות • בדיקות • מודל האנשים הקטנים
תכנות פונקציונאלי - פונקציות רקורסיביות, מיפוי (map) • פונקציה המקבלת רשימת מספרים חיוביים ומחזירה רשימה של שורשי המספרים. • עבור הרשימה ‘(100 64 0 25 1) תוחזר הרשימה (10 8 0 5 1 ). • פונקציה המקבלת רשימה של רשימות לא ריקות ומחזירה רשימה של איבריהם הראשונים. • עבור ‘((my cat) (good morning) (dad and mom)) תוחזר הרשימה (my good dad).
תכנות פונקציונאלי - פונקציות רקורסיביות, מיפוי (map) • פונקציה המקבלת רשימת מספרים חיוביים ומחזירה רשימה של שורשי המספרים. (define (sqrt_list l) (cond [(empty? l) l] [else (cons (sqrt (first l)) (sqrt_list (rest l)))]))
תכנות פונקציונאלי - פונקציות רקורסיביות, מיפוי (map) • פונקציה המקבלת רשימה של רשימות לא ריקות ומחזירה רשימה של איבריהם הראשונים. (define (first_list l) (cond [(empty? l) l] [else (cons (first (first l)) (first_list (rest l)))]))
תכנות פונקציונאלי - פונקציות רקורסיביות, מיפוי (map) • הפונקציות הנ"ל מקבלות רשימה (רשימת קלט) ומחזירות רשימה (רשימת פלט). • לכל איבר ברשימת הקלט מותאם איבר ברשימת הפלט. • התאמה כזו נקראת פונקצית מיפוי.
תכנות פונקציונאלי - פונקציות רקורסיביות, מיפוי (map) • דוגמאות נוספות לפונקציות מיפוי.
תכנות פונקציונאלי - פונקציות רקורסיביות, מיפוי (map) • פונקציה MAP הקולטת את פונקצית המיפוי ורשימה ומבצעת את המיפוי. )define (map list operation) (cond [(empty? list ) '()] [else (cons (operation (first list)) (map (rest list) operation))])) > (map '(8 7 6) add1) (9 8 7) > (map '(16 0 6) sqrt) (4 0 2.4494897427832)
תכנות פונקציונאלי - פונקציות רקורסיביות, סינון (filter) • כתבו פונקציה רקורסיבית המקבלת רשימה כלשהי ומחזירה רשימה רק עם המספרים שבה. • נסחו את הפתרון באופן מילולי. • תרגמו את הפתרון המילולי לפונקציה.
תכנות פונקציונאלי - פונקציות רקורסיביות, סינון (filter) • כתבו פונקציה רקורסיבית המקבלת רשימה כלשהי ומחזירה רשימה רק עם המספרים שבה. )define (only_numbers l) (cond [(empty? l ['() ( [(number? (first l)) (cons (first l) (only_numbers (rest l [((( [else (only_numbers (rest l))]))
תכנות פונקציונאלי - פונקציות רקורסיביות, סינון (filter) • הפונקציה הבאה מקבלת רשימת מספרים. (define (sod L) (cond [ ( empty? L ) ‘( ) ] [ (negative? (first L ) ) ( sod ( rest L ) ) ] [ else (cons ( sqrt (first L)) (sod (rest L )))])) • מה מחזירה הפונקציה עבור הרשימות הבאות? (64 -4 100 25 -25 ) (1 49 -9 -16 81 4 ) • מה מבצעת הפונקציה? • תנו לפונקציה שם משמעותי.
תכנות פונקציונאלי - פונקציות רקורסיביות, סינון (filter) • כתבו פונקציה שמקבלת רשימה כלשהי ובונה רשימה חדשה ללא הרשימות שבה. (define (not_list l) (cond [(empty? l) '()] [(list? (first l)) (not_list (rest l))] [else (cons (first l) (not_list (rest l)))]))
תכנות פונקציונאלי - פונקציות רקורסיביות, סינון (filter) • הפונקציות הנ"ל מקבלות רשימה (רשימת קלט) ומחזירות רשימה (רשימת פלט) שנמצאים בה רק האיברים המקיימים תנאי מסוים. • פונקציות מסוג זה נקראות פונקצית סינון. • הציעו דוגמאות נוספות לפונקציות סינון. • כתבו את הפונקציה filter (מהם קלטיה?)
תכנות פונקציונאלי - פונקציות רקורסיביות, סינון (filter) פונקצית סינון הקולטת את פונקצית המיפוי ורשימה ומבצעת את הסינון. (define (filter l predicate) (cond [(empty? l) '()] [(predicate (first l)) (cons (first l) (filter (rest l) predicate))] [else (filter (rest l) predicate)]))
תכנות פונקציונאלי - פונקציות רקורסיביות, סינון (filter) • כתיבת פרדיקטים היכולים לשמש כקלט לפונקצית סינון. • השתמשו בפונקציה filter וכתבו ביטוי הקולט רשימת מספרים ומחזיר רשימה שמצויים בה רק המספרים המתחלקים ב- 6. (define (divide_6? x) (= (reminder x 6) 0)) > (divide_6? 8( #f > )divide_6? 12( #t >) filter '(4 6 12 67 60 180) divide_6(? (6 12 60 180)
תכנות פונקציונאלי - פונקציות רקורסיביות, צמצום (reduce) • כתבנו פונקציה הקולטת רשימת מספרים ומחזירה את סכומם. • פרדיקטים: • כתבו פונקציה הקולטת רשימה ומחזירה #t אם כל איברי הרשימה הם רשימות ו- #f אחרת. • כתבו פונקציה הקולטת רשימת מספרים ומחזירה #t אם כל איברי הרשימה זוגיים ו- #f אחרת.
תכנות פונקציונאלי - פונקציות רקורסיביות, צמצום (reduce) • הפונקציות הנ"ל הן פונקציות צמצום היות והן קולטות רשימה ומחזירות מספר או ערך בוליאני. • כתבו את הפונקציה reduce. • מהם קלטיה? • האם ניתן לתפוס את כל המקרים בפונקציה אחת?
תכנות פונקציונאלי - map, filter, reduce • פונקציות הן first order objects • המושג הפשטה
תכנות פונקציונאלי • תרגיל: • רשמו ביטוי הקולט רשימה ומחזיר את מספר האיברים הגדולים מממוצע המספרים ברשימה.
תכנות פונקציונאלי • אין השמה, אין אפשרות לשים ערכים בזיכרון (בדומה למתמטיקה) • פתרון: בעזרת פונקציות. • פתרון התרגיל באופן מסורתי: • חישוב הממוצע והשמתו במשתנה. • ספירת מספר האיברים הגדולים מהממוצע. • בתכנות פונקציונאלי: הרכבת פונקציות.
תכנות פונקציונאלי • פונקציה הקולטת רשימה ומחזירה את מספר האיברים הגדולים מממוצע איברי הרשימה. )define (sup-big-than-average l) (big-than-average l (average l))) )define (big-than-average l average) (cond [(empty? l) 0 ] ](> (first l) average) (add1 (big-than-average (rest l) average))] ]else (big-than-average (rest l) average)]))
תכנות פונקציונאלי • רשמו ביטוי שהקלט שלו הוא רשימה המחזיר את מספר האיברים הגדולים מממוצע איברי הרשימה. • הגדרת פונקצית-על על-מנת לשמור את הממוצע של הרשימה המקורית.
תכנות פונקציונאלי, פונקציות רקורסיביות, סיכום • פונקציה רקורסיבית היא פונקציה הקוראת לעצמה. או ליתר דיוק, גורמת להפעלה חוזרת של אותה הפונקציה אבל בדרך-כלל עם ערכי פרמטרים שונים. מרכיבים בסיסיים בפונקציה רקורסיבית: • תנאי עצירה (מקרה בסיסי) שפועל על אחד מהפרמטרים של הפונקציה. • תנאי העצירה מגדיר מה מחזירה הפונקציה במקרה הפשוט ביותר (המקרה הבסיסי). • קריאה רקורסיבית או צעד רקורסיבי שגורם להפעלה החוזרת. • שינוי הפרמטרים בקריאה הרקורסיבית צריך להיות "בכיוון" של תנאי העצירה. • אם אין שינוי בפרמטר המתאים, הפונקציה (התהליך) לא תעצור.
תכנות פונקציונאלי, פונקציות רקורסיביות, סיכום סוגי רקורסיה: • רקורסית קצה (tail recursion) - יוצרת תהליך חישובי איטרטיבי (לולאה). • רקורסיה אמיתית (מלאה) - יוצרת תהליך רקורסיבי מלא. • רקורסיה לינארית (חד-ממדית) מכילה קריאה רקורסיבית יחידה. • רקורסיה מורכבת (רב-ממדית) מכילה יותר מקריאה רקורסיבית אחת.
תכנות פונקציונאלי • פונקציות והרכבתם • פונקציות הן איבר מסדר ראשון • אין השמה • רעיונות נלווים של מדעי המחשב : • מסננת קלט • בדיקות • רקורסיה • מבני נתונים • מבנה בסיסי - רשימה • בהמשך נבנה ממבנה זה מבנים מורכבים יותר
תכנות פונקציונאלי – דיון • באיזה מובן סוג התכנות שחווינו מהווה פרדיגמה תכנותית?