Computer Programming Summer 2017

Slides:



Advertisements
Similar presentations
מבוא למדעי המחשב לתעשייה וניהול
Advertisements

מבוא למדעי המחשב לתעשייה וניהול דוגמאות ותרגול נוסף במערך חד ממדי הרצאה 12.
רקורסיות נושאי השיעור פתרון משוואות רקורסיביות שיטת ההצבה
תכנות תרגול 7 שבוע : מערכים עד היום התוכניות שלנו לא ידעו לשמור כמות גדולה של מידע ללא הגדרת כמות גדולה של משתנים. עד היום התוכניות שלנו לא.
תכנות תרגול 9 שבוע : הקשר בין מערכים למצביעים נרצה לעמוד על הקשר בין מערך למצביע מאחר ומערכים הם הכללה של משתנים הרי שברור שלמערך ולכל אחד מאיבריו.
תכנות תרגול 6 שבוע : חישוב e זוהי הנוסחא לחישוב e נראה כיצד לתרגם אותה לפונקציה n n.
תרגול 5 רקורסיות. רקורסיה קריאה של פונקציה לעצמה –באופן ישיר או באופן עקיף היתרון : תכנות של דברים מסובכים נעשה ברור ונוח יותר, מכיוון שזו למעשה צורת.
תכנות תרגול 4 שבוע : לולאות while לולאות while while (condition) { loop body } במקרה של קיום התנאי מתבצע גוף הלולאה ברגע שהתנאי לא מתקיים נצא.
תכנות תרגול 2 שבוע : שבוע שעבר כתבו תוכנית המגדירה שלושה משתנים מאתחלת אותם ל 1 2 ו 3 ומדפיסה את המכפלה שלהם את ההפרש שלהם ואת הסכום שלהם.
מבוא לשפת C חידות ונקודות חשובות נכתב על-ידי יורי פקלני. © כל הזכויות שמורות לטכניון – מכון טכנולוגי לישראל.
11 Introduction to Programming in C תרגול
מבוא למדעי המחשב תרגול 8 - מחרוזות שעת קבלה : יום שני 11:00-12:00 דוא " ל :
מבוא כללי למדעי המחשב תרגול. הבית האדום כתובת : רחוב קוקוריקו 2 הבית הירוק כתובת : רחוב קוקוריקו 4 הבית הצהוב כתובת : רחוב קוקוריקו 1 הבית הורוד כתובת.
תכנות תרגול 9 שבוע : מערכים int a; a=5; int a[10]; a[2] = 5; 5 a a[0] a[1] a[2] a[9]  5 משתנה בודד מערך גישה למשתנה השלישי במערך.
11 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
מבוא למדעי המחשב © אריק פרידמן 1 מצביעים כמערכים דוגמה.
1 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
תכנות תרגול 6 שבוע : תרגיל שורש של מספר מחושב לפי הסדרה הבאה : root 0 = 1 root n = root n-1 + a / root n-1 2 כאשר האיבר ה n של הסדרה הוא קירוב.
מבוא לשפת C תרגול 12: עוד רקורסיה
11 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
1 Formal Specifications for Complex Systems (236368) Tutorial #1 Course site : T.A. :Emilia Katz.
תכנות תרגול 6 שבוע : הגדרת פונקציות return-value-type function-name(parameter1, parameter2, …) הגדרת סוג הערכים שהפונקציה מחזירה שם הפונקציהרשימת.
תכנות תרגול 10 שבוע : הקשר בין מערכים למצביעים נרצה לעמוד על הקשר בין מערך למצביע מאחר ומערכים הם הכללה של משתנים הרי שברור שלמערך ולכל אחד מאיבריו.
מבוא כללי למדעי המחשב תרגול 3. לולאות while לולאות while while (condition) { loop body } במקרה של קיום התנאי מתבצע גוף הלולאה ברגע שהתנאי לא מתקיים נצא.
תכנות בשפת C תרגול 9 רקורסיה המשך
ערכים עצמיים בשיטות נומריות. משוואה אופינית X מציין וקטור עצמי מציינת ערך עצמי תואם לוקטור.
קורס תכנות – סימסטר ב ' תשס " ח שיעור שישי: מערכים
מבוא למדעי המחשב תרגול 6 - מערכים שעת קבלה : יום שני 11:00-12:00 דוא " ל :
תכנות תרגול 5 שבוע : הגדרת פונקציות return-value-type function-name(parameter1, parameter2, …) הגדרת סוג הערכים שהפונקציה מחזירה שם הפונקציהרשימת.
מערכים עד היום כדי לייצג 20 סטודנטים נאלצנו להגדיר עד היום כדי לייצג 20 סטודנטים נאלצנו להגדיר int grade1, grade2, …, grade20; int grade1, grade2, …, grade20;
עקרון ההכלה וההדחה.
תכנות תרגול 4 שבוע : לולאות for לולאות for for (counter=1 ;counter
תכנות מונחה עצמים Object Oriented Programming (OOP) אתגר מחזור ב' Templates תבניות.
מבוא למדעי המחשב תרגול 3 שעת קבלה : יום שני 11:00-12:00 דוא " ל :
תכנות בשפת C תרגול 15 תרגול חזרה 2 תרגילים ממבחנים
פונקציות תכנות בשפת סי תרגול 7. הגדרה: המונח רקורסיה (recursion) מתאר מצב שבו פונקציה קוראת לעצמה באופן ישיר או באופן עקיף. שימוש: נוח להשתמש בפונקציות.
1 מבוא למדעי המחשב סיבוכיות. 2 סיבוכיות - מוטיבציה סידרת פיבונאצ'י: long fibonacci (int n) { if (n == 1 || n == 2) return 1; else return (fibonacci(n-1)
מבוא למדעי המחשב תרגול 9 – מערכים ומחרוזות, תרגילי חזרה שעת קבלה : יום שני 11:00-12:00 דוא " ל :
1 מבוא למדעי המחשב backtracking. 2 מוטיבציה בעיית n המלכות: נתון: לוח שחמט בגודל. המטרה: לסדר על הלוח n מלכות כך שאף אחת לא תאיים על השנייה. דוגמא: עבור.
11 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
תכנות תרגול 8 שבוע : מערכים עד היום התוכניות שלנו לא ידעו לשמור כמות גדולה של מידע ללא הגדרת כמות גדולה של משתנים. עד היום התוכניות שלנו לא.
1 מבוא למדעי המחשב רקורסיה. 2 רקורסיה היא שיטה לפתרון בעיות המבוססת על העיקרון העומד ביסוד אינדוקציה מתמטית: אם ידועה הדרך לפתור בעיה עבור המקרים הבסיסיים.
תרגול 13 חזרה 1. Exam example 8 public class Stam { private char x; public Stam() { this.x = '*'; } public Stam (char c) { this.x = c; } public Stam getStam()
מבוא למדעי המחשב לתעשייה וניהול הרצאה 12. ספריות.
1 Formal Specifications for Complex Systems (236368) Tutorial #1 Course site:
1 Introduction to Programming in C - Fall 2010 – Erez Sharvit, Amir Menczel 1 Introduction to Programming in C תרגול
מספרים אקראיים ניתן לייצר מספרים אקראיים ע"י הפונקציה int rand(void);
Programming Arrays.
מבוא למדעי המחשב לתעשייה וניהול
Tirgul 12 Trees 1.
Formal Specifications for Complex Systems (236368) Tutorial #1
מבוא למדעי המחשב סיבוכיות.
Introduction to Programming in C
שיעור חמישי: מערכים ומחרוזות
מצביעים קרן כליף.
SQL בסיסי – הגדרה אינדוקטיבית
תרגול מס' 7: Memoization Quicksort תרגילים מתקדמים ברקורסיה
תרגול 11 NP complete.
מבוא כללי למדעי המחשב תרגול 4
תרגול 8 תחומי הכרה פונקציות
שאלות מבחינות קודמות יואב ציבין.
Introduction to Programming in C
Programming in C תרגול Introduction to C - Fall Amir Menczel.
Introduction to Programming in C
תרגול Introduction to C - Fall Amir Menczel.
נושאים מחרוזות מיון (מיון בועות) רקורסיה
שיעור עשירי: מיונים, חיפושים, וקצת סיבוכיות חישוב
Computer Programming תרגול 3 Summer 2016
Engineering Programming A
מבוא לתכנות ב- Java תרגול 10 - רשימות מקושרות.
Presentation transcript:

Computer Programming Summer 2017 תרגול 7 1 1 Introduction to C - Fall 2010 - Amir Menczel

רקורסיה הגדרה: המונח רקורסיה (recursion) מתאר מצב שבו פונקציה קוראת לעצמה באופן ישיר או באופן עקיף. שימוש: נוח להשתמש בפונקציות רקורסיביות על מנת לפתור בעיות בעלות אופי רקורסיבי. באופן כללי, השיטה תהיה להקטין את מימד הבעיה, לפתור את הבעיה על המימד היותר קטן ולהשתמש בפיתרון שמתקבל על מנת לפתור את הבעיה במימד אחד יותר גבוהה.

דוגמה מס' 1 הגדרה: פלינדרום הוא רצף תווים שניתן לקרוא משני הכיוונים ללא שינוי בתוצאה. דוגמאות: "ABBA", "ABA", "לבלבל". כתוב פונקציה רקורסיבית המקבלת מחרוזת, ומחזירה TRUE אם המחרוזת היא פלינדרום, FALSE אם אינה. (נניח כי FALSE מוגדר כ-0 ו- TRUE מוגדר כ-1)

דוגמה מס' 1 int is_pal(char s[], int first, int last) { if (first>=last) return TRUE; return (s[first] == s[last]) && is_pal(s, first+1,last-1); }

דוגמה מס' 1- מחסנית ריצה: void main() { is_pal("ABBA",0, 3); T T T s=“ABBA” , first=0, last = 3 if (0>=3) return TRUE; return (s[0] == s[3]) && is_pal(s, 1, 2); s=“ABBA” , first=1, last = 2 if (1>=2) return TRUE; return (s[1] == s[2]) && is_pal(s, 2, 1); s=“ABBA” , first=2, last = 1 if (2>=1) return TRUE; return ... T T T

דוגמה מס' 1- פונקציית מעטפת: int is_pal2(char s[]) { return is_pal(s, 0, strlen(s) – 1); }

דוגמה מס' 2 – harmonic number ברצוננו לכתוב פונקציה רקורסיבית rec_harmonic_num(n) אשר תדפיס למסך את הפיתוח של h(n). למשל, עבור הקריאה rec_harmonic_num(5), נקבל על המסך: 1/5+1/4+1/3+1/2+1=2.28

תזכורת – משתנים סטאטיים מגדירים באופן הבא: static int var; ניתן לאתחל בשורת ההגדרה בלבד כאשר חייבים לאתחל בביטויי קבוע. אם אנחנו לא מאתחלים אותם, המערכת תאתחל אותם אוטומטית לאפס. הscope- של משתנים סטאטיים הוא רק הפונקציה שבה הם הוגדרו אך הם ממשיכים להתקיים גם אחרי שביצוע הפונקציה נגמר (למעשה עד סוף ריצת התוכנית). אתחול המשתנה קורה רק בריצה הראשונה של הפונקציה. לפיכך הערך של משתנה סטאטי בפונקציה כלשהי נשמר בין קריאות עוקבות לפונקציה זו.

דוגמה מס' 2– harmonic number void rec_harmonic_sum(int n) { static double sum=1; if(n==1)/*Stop condition*/ printf("1=%.2f\n", sum); sum=1; /* If we don’t reset sum to 1, the function will not work correctly next time. Can you figure out why? */ return; } printf("1/%d+", n); sum+=1.0/n; /* using 1.0 to force floating point division (instead of integer division by default)*/ rec_harmonic_sum(n-1); /*The recursive call. */

דוגמה מס' 3– abc כתוב פונקציה רקורסיבית אשר חתימתה היא: void abc(char arr[], int lastPlace, int curPlace) המקבלת מערך של char-ים, את אינדקס סוף המערך ומספר שלם שהוא המקום במערך ממנו אנו מעונינים להתחיל במילוי המערך בתווים (בקריאה ראשונה יהיה מס' זה שווה ל- 0). הפונקציה מדפיסה את כל האפשרויות למלא את המערך מהמקום שקיבלה, curPlace, עד המקום lastPlace באותיות a,b,c במילים אחרות, מטרת הפונקציה היא להדפיס את כל האפשרויות ליצור מילה באורך מסוים בעזרת האותיות a,b,c .

דוגמה מס' 3– abc void abcWarper(char word[], int lengthOfWord){ למשל: עבור התוכנית הבאה: void abcWarper(char word[], int lengthOfWord){ abc(word, lengthOfWord,0); } void main(){ char word[5]; abcWarper(word,3); נקבל את הפלט: aaa aab aac aba abb abc aca acb acc baa bab bac bba bbb bbc bca bcb bcc caa cab cac cba cbb cbc cca ccb ccc

דוגמה מס' 3– abc כתובתו של תחילת המערך אינדקס סוף המערך המקום הנוכחי שאנחנו משנים void abc(char arr[],int lastPlace, int curPlace) { if (curPlace == lastPlace) arr[curPlace]='\0'; printf("%s\t",arr); return; } arr[curPlace] = 'a'; abc (arr,lastPlace,curPlace+1); arr[curPlace] = 'b'; arr[curPlace] = 'c'; תנאי העצירה: אם הגענו ל- lastPlace אז שים במקום הנוכחי יש '0\' (הגענו לסוף), הדפס את המחרוזת (מהתחלתה) וחזור. כעת אנחנו עובדים על המקום curPlace במערך: הצב בו a, וקרא לפונק' abc (עם כתובת המערך, ואינדקס המקום הבא) אשר תדאג למילוי כל האפשרויות הקימות בשאר המערך. לאחר שחזרת, הצב את b במקום a, ושוב קרא לפונק' עם המקום הבא במערך כפרמטר. כנ"ל לגבי c.

דוגמה מס' 3– abc נראה את תרשים הקריאות המתקבל מהרצת הדוגמא שלמעלה (בדומה לתרשים הקריאות שראינו בכתה): כל ריבוע מייצג קריאה לפונקציה, כאשר בתוך כל ריבוע מופיע תוכן המערך שהפונקציה מקבלת. ערך הפרמטרcurPlace הוא משותף לכל רמה בתרשים ומצויין בצד ימין. aab aac aba abb abc aca acb acc baa bab bac bba bbb bbc bca bcb bcc caa cab cac cba cbb cbc cca ccb ccc aaa הדפסה: aa? ab? ac? ba? bb? bc? ca? cb? cc? a?? b?? c?? ??? curPlace=0 curPlace=1 curPlace=2 curPlace=3

דוגמה מס' 4 כתבו תוכנית הקולטת עד 20 ערכים שלמים (1- מציין סוף קלט) למערך ומוצאת את הערך המקסימאלי. לשם כך, ניתן לפרק את הבעיה לשתי בעיות קטנות יותר כתבו פונקציה רקורסיבית שקולטת את המערך כתבו פונקציה רקורסיבית שמחזירה את הערך המקסימאלי

דוגמה מס' 4 int GetArray(int arr[], int i){ int num; if (i > MAX_LEN – 1){ return 0; } scanf("%d", & num); if (num!= -1) { arr[i] = num; return GetArray(arr, i+1) + 1; else { int main(){ int max,a[MAX_LEN],length; length = GetArray(a, 0); max=Max(a,0, length ); printf(“max=%d\n”max); return 0; } int Max(int a[], int i, int length){ int max; if (i == length -1) { return a[i]; } max = Max(a, i + 1); return (a[i] > max ? a[i] : max);

דוגמה מס' 5 כתוב פונקציה רקורסיבית אשר מקבלת מחרוזת s, תו ch, ומספר שלם n. הפונקציה תחפש את המופע ה- n-י של ch במחרוזת s ותחזיר את האינדקס שלו. דוגמא: בהינתן המחרוזת “abbc”, התו b, והשלם 2 (עבור n) הפונקציה תחזיר 2. התו ‘b’ מופיע בפעם השנייה במחרוזת s באינדקס 2 במחרוזת.

דוגמה מס' 5 int FindNOccurence(char s[], char ch, int n, int index){ if (n == 0) return index -1; if (s[index] == '\0') return -1; if (s[index] == ch) return FindNOccurence (s, ch, n – 1, index + 1); return FindNOccurence(s, ch, n, index + 1); {

דוגמה מס' 6 נתונה הפונקציה הרקורסיבית הבאה: #include <stdio.h> int secret(int n){ If(n < 0) return 1 + secret (-1 * n); if (n < 10) return 1; return 1 + secret(n/10); } מה הערך של secret(-4321) ו- secret(12345) ? מה מבצעת הפונקציה secret עבור פרמטר חיובי ועבור פרמטר שלילי? כתוב פונקציה זו מחדש בצורה לא רקורסיבית.

דוגמה מס' 6 פתרון: סעיף א': 5 בשני המקרים. סעיף א': 5 בשני המקרים. סעיף ב': הפונקציה מחזירה את מס' התווים שמייצגים את הארגומנט. כך למשל הפלט של התוכנית הבאה: void main() { char s[80]; printf("%d\n",secret(-43221)); printf("%d\n",secret(12345)); } יהיה: 6 5 }

דוגמה מס' 6 כתוב אותה פונקציה בצורה לא רקורסיבית. פתרון: int iterSecret(int n){ int len=1; if(n < 0) { n=(-1) * n; len++; } while(n >=10) { n/=10; return len;

דוגמה מס' 7 int what(int a, int b){ if(!a && !b) { return 1; } עיין בפונקציה הבאה: int what(int a, int b){ if(!a && !b) { return 1; } if(a > b) { return a * what(a-1, b); return b * what(a, b-1); בהנחה שהפונקציה הנ"ל מקבלת שני ערכים אי-שליליים (חיוביים או אפס), סמן את כל התשובות הנכונות (בדף התשובות): הפונקציה נכנסת לרקורסיה אינסופית. הערך המוחזר של הפונקציה תמיד 0. הערך המוחזר של הפונקציה יכול להיות 0. הערך המוחזר של הפונקציה תמיד 1. הערך המוחזר של הפונקציה יכול להיות 1. בקבלת שני ערכים חיוביים a ו- b, אם הערכים לא גדולים מידי,הפונקציה מחזירה את הערך של a! x b!. אף לא אחת מהתשובות לעיל.

דוגמה מס' 7 int what(int a, int b){ if(!a && !b) { return 1; } עיין בפונקציה הבאה: int what(int a, int b){ if(!a && !b) { return 1; } if(a > b) { return a * what(a-1, b); return b * what(a, b-1); בהנחה שהפונקציה הנ"ל מקבלת שני ערכים אי-שליליים (חיוביים או אפס), סמן את כל התשובות הנכונות (בדף התשובות): הפונקציה נכנסת לרקורסיה אינסופית. הערך המוחזר של הפונקציה תמיד 0. הערך המוחזר של הפונקציה יכול להיות 0. הערך המוחזר של הפונקציה תמיד 1. הערך המוחזר של הפונקציה יכול להיות 1. – נכון (למשל כאשר a=0 ו-b=0) בקבלת שני ערכים חיוביים a ו- b, אם הערכים לא גדולים מידי,הפונקציה מחזירה את הערך של a! x b!. - נכון אף לא אחת מהתשובות לעיל.

דוגמה מס' 8 Subset Sum problem נתונה סדרת ערכים שלמים (כמערך) arr ומספר שלם S. צ"ל: האם קיימת תת-סדרה במערך כך שסכומה S. למשל עבור: arr 17 1 5 6 7 ו-S=14 התשובה היא כן כי קיימת תת-סדרה במערך שהיא: 7,6,1 וסכומה 14.

דוגמה מס' 8 האלגוריתם: עבור כל איבר i במערך, יש 2 אפשרויות: אפשרות א': כן לוקחים את האיבר ה- i, ומנסים למצוא SubsetSum בגודל S-arr[i] במערך קטן יותר ב-1. אפשרות ב': לא לוקחים את האיבר ה- i , ומנסים למצוא SubsetSum בגודל S במערך קטן יותר ב-1. תנאי העצירה שלנו יהיו: אם קיבלנו באיזשהו שלב S==0 אז נמצא SubsetSum במערך ונחזיר 1. אחרת, אם קיבלנו S<0 או 0==n, אז הבחירות שלקחנו עד עכשיו אינן מובילות לפתרון (אם S<0 אזי עברנו את הסכום המבוקש ואם 0==n אזי עדיין לא הגענו לסכום ואין לרשותנו אברים מתוכם נוכל לבחור) ונחזיר 0.

דוגמה מס' 8 int SubsetSum(int arr[], int idx, int n, int S) { if (S==0) { return 1; /* Termination condition #1. */ } if (S<0 || n==0) { return 0; /* Termination condition #2.*/ return SubsetSum(arr, idx+1, n-1, S-arr[idx]) || SubsetSum(arr, idx+1, n-1, S); טיפול באפשרות א' טיפול באפשרות ב'

דוגמה מס' 9 שנו את הפונקציה שכתבתם בשאלה הקודמת כך שהיא תחזיר את כמות תתי-הקבוצות של איברי המערך המקיימות שסכומן שווה בדיוק ל-s.

דוגמה מס' 9 int SubsetSum(int arr[], int idx, int n, int S) { if (S==0) { return 1; /* Termination condition #1. */ } if (S<0 || n==0) { return 0; /* Termination condition #2.*/ return SubsetSum(arr, idx+1, n-1, S-arr[idx]) + SubsetSum(arr, idx+1, n-1, S);

דוגמה מס' 10 נתון מערך דו-מימדי בגודל m*n המכיל מספרים טבעיים קטנים מ-100. מסלול חוקי במערך מתחיל בתא (0,0) ומסתיים בתא (m-1,n-1), כאשר ההתקדמות תלויה בספרת האחדות והעשרות של המס' שבתא הנוכחי. אם בתא (2,3) רשום המס' 13, אז ישנם 2 דרכים להתקדם מתא זה: 1) 1+ בשורות ו 3+ בעמודות. כלומר לתא (3,6). 2) 3+ בשורות ו 1+ בעמודות. כלומר לתא (5,4). אם בתא רשום מס' חד ספרתי, למשל 3, נתייחס אליו כאל 03.

דוגמה מס' 10 לדוגמה: מסלול אפשרי הוא המסלול הצבוע בירוק. כתבו פונקציה רקורסיבית המחזירה את מס' המסלולים החוקיים במערך (כמובן שאסור להשתמש בלולאות).

דוגמה מס' 10 #define ROWS 5 #define COLS 4 int countPaths(int arr[][COLS], int row, int col) { if ( (row == ROWS-1) || (col == COLS-1)) { return 1; } if ((row > ROWS-1) || (col > COLS-1)) { return 0; if (arr[row][col]/10 == arr[row][col]%10) { return countPaths(arr, row + arr[row][col]/10, col + arr[row][col]/10); return countPaths(arr, row + arr[row][col]/10, col + arr[row][col]%10) + countPaths(arr, row + arr[row][col]%10, col + arr[row][col]/10);

דוגמה מס' 11 כתבו פונקציה רקורסיבית void X(int lines) שמדפיסה את האות X באמצעות כוכביות ב-lines שורות (נניח ש-lines תמיד אי-זוגי). ניתן להשתמש בלולאות. לדוגמא עבור X(9) יודפס:  * * * * * * * * * * *  הכוכבית הראשונה חייבת להופיע בתחילת השורה הראשונה. אין להגדיר פונקציה נוספת.

דוגמה מס' 11 פתרון: הרעיון הוא להדפיס את השורה הראשונה של X, אחר כך לפתור את תת-הבעיה עבור X ללא השורה הראשונה והאחרונה ואז להדפיס את השורה האחרונה (שהיא זהה לראשונה). ניתן להדגים את סדר הפעולות הכרונולוגי בכל קריאה רקורסיבית באמצעות התרשים הבא:

דוגמה מס' 11 void X(int lines){ int static blank; int I; for (i=0; i<blank; i++) putchar(' '); putchar('*');   if(lines==1){ puts(""); return; }   for (i=0; i<lines-2; i++) putchar(' '); puts("*");   blank++; X(lines-2); blank--; for (i=0; i<blank; i++) putchar(' '); putchar('*'); }