אוניברסיטת חיפה החוג למדעי המחשב.5.6 מבוא למדעי המחשב סמסטר א' תשע"ז בחינה סופית מועד א', 31.1.2017 מרצה: שולי וינטנר מתרגלים: סמאח אידריס, ראמי עילבוני, דולב שרון הנחיות: 1. משך הבחינה: 120 דקות. 2. היציאה מהכיתה במהלך הבחינה אסורה. 3. אין להשתמש בכל חומר עזר. 4. קראו היטב כל שאלה וודאו שאתם מבינים אותה לפני שתתחילו לענות עליה. אם יש שאלות, פנו למרצה או למתרגלים. ניתן לכתוב הערות בעברית, גם בגוף פונקציות C. אם לא נכתב אחרת, מותר להשתמש בפונקציות וקבועים שנלמדו בכיתה מתוך הספריה stdio בלבד. לא ניתן להשתמש בפונקציות שלא נלמדו בכיתה. בהצלחה! 1 2 3 סה"כ
שאלה (35%) 1 נתונה רשימה מקושרת שמבנה הרשומה בה מוגדר כך: typedef struct cell *CellPtr; typedef struct cell double contents; CellPtr next; Cell; הרשימה מכילה מספרים ממשיים המייצגים מקדמים של פולינום, מסודרים ממקדם החזקה הגדולה ביותר, בתחילת הרשימה, למקדם האיבר החופשי, בסופה. הגדירו פונקציה רקורסיבית בשם polynomial אשר מקבלת רשימה כזאת וכן מספר ממשי x. על הפונקציה לחשב ולהחזיר את ערכו של הפולינום בנקודה x. למשל, אם הרשימה מכילה את האברים הבאים: 2.0, 3.1, -7.5, 0, -1 אזי הפולינום הוא 2.0 x 4 + 3.1 x 3-7.5 x 2-1 ערכו של הפולינום הזה בנקודה 2=x הינו 25.8, וזה הערך שעל הפונקציה להחזיר. דרישות: 1. באפשרותכם להגדיר את כותרת הפונקציה כרצונכם. הסבירו במפורש מהם הפרמטרים שהפונקציה מקבלת ומהו הערך המוחזר ממנה. הסבירו גם כיצד היא נקראת בפעם הראשונה. 2. סיבוכיות מקום: ללא הגבלה. סיבוכיות זמן:,O(n) כש- n מספר האברים בקלט. הבהרות: שימו לב שעליכם להגדיר פונקציה רקורסיבית. 1. ניתן להניח שהקלט חוקי ואין צרך לבדוק זאת. 2. אין להשתמש במשתנים סטטיים או חיצוניים. 3. אין להגדיר יותר מפונקציה אחת. 4. לחישוב חזקה השתמשו בפונקציה.pow לחישוב x y כתבו.pow(x,y) 5.
double polynomial (CellPtr list, double x, int *exponent) double temp; if (NULL==list) *exponent = 0; else temp = polynomial(list->next, x, exponent); return (list->contents * pow(x,(*exponent)++) + temp);
שאלה (30%) 2 נתון מערך של שלמים בשם a באורך n. כמו כן נתון מערך בשם order באורך n, שמכיל פרמוטציה של המספרים בין 0 ל- n-1. הגדירו פונקציה בשם reorder שמקבלת את שני המערכים הללו ואת אורכם n. על הפונקציה לסדר מחדש את אברי המערך a כך שיתקיים לכל i ו- j בין 0 ל- n-1 : אם order[i]<order[j] אזי גם.a[i]<a[j] 9,0,-2,10,1 4,2,0,1,3 10,1,-2,0,9 למשל, אם 5=n ו- a מכיל את האברים הבאים: ואם order מכיל את הפרמוטציה הבאה: אזי על הפונקציה לסדר מחדש את a כך: הבהרות: על הפונקציה לפעול בסיבוכיות זמן אופטימלית. 1. סיבוכיות מקום:,O(n) כלומר מותר להגדיר מערכים נוספים בגודל n. 2. להשתמש בכל הפונקציות שנלמדו בכיתה. אם אתם מותר בשאלה זו 3. משתמשים בפונקציה כזו, ציינו את שמה והסבירו מה היא מחשבת ומה הסיבוכיות שלה. אין צורך להגדיר אותה או להצהיר עליה. אין להשתמש במשתנים חיצוניים. 4. אין להגדיר יותר מפונקציה אחת. 5. void reorder (int a[], int order[], int n) int i; int *temp; temp = (int *)malloc(n*sizeof(int)); sort(a,n); for (i=0; i<n; i++) temp[i] = a[order[i]]; for (i=0; i<n; i++) a[i] = temp[i]; free(temp);
שאלה (35%) 3 היטורי הוא משחק דמוי סודוקו שבו ריבוע בגודל k*k של מספרים שלמים או משבצות שחורות. לצורך פשטות נניח שהמספרים הם תמיד בין 1 ל- k, ושמשבצת שחורה מיוצגת על ידי המספר 0. פתרון חוקי להיטורי הוא כזה שבו אין שורה שבה מספר שמופיע יותר מפעם אחת, אין עמודה שבה מספר שמופיע יותר מפעם אחת, ואין שתי משבצות שחורות צמודות (במאוזן או במאונך; שתי משבצות שחורות באלכסון אינן פוגעות בחוקיות. הגדירו פונקציה המקבלת מערך דו-ממדי ריבועי בגודל k*k ואת גודלו k, ומחזירה 1 אם הוא פתרון חוקי להיטורי, 0 אחרת. למשל, הריבוע הבא הוא פיתרון חוקי להיטורי (8=k): דרישות: סיבוכיות זמן: ) 3.O(k.1 סיבוכיות מקום: (1)O, כלומר אסור להגדיר מערכים נוספים. 2. אין להשתמש במשתנים חיצוניים. 3. מותר להגדיר יותר מפונקציה אחת. 4. 0 8 0 6 3 2 0 7 3 6 7 2 1 0 5 4 0 3 4 0 2 8 6 1 4 1 0 5 7 0 3 0 7 0 3 0 8 5 1 2 0 5 6 7 0 1 8 0 6 0 2 3 5 4 7 8 8 7 1 4 0 3 0 6 int hitori(int a[max][max], int k) return (rows(a,k) && neighbors(a,k));
int rows(int a[max][max], int k) int i, j, val, count_rows, count_cols; for (i=0; i<k; i++) /* check row/col i */ for (val=1; val<=k; val++) /*check value val */ count_rows = count_cols = 0; for (j=0; j<k; j++) if (a[i][j] == val) count_rows++; if (count_rows > 1) if (a[j][i] == val) count_cols++; if (count_cols > 1) return 1; int neighbors(int a[max][max], int k) int i, j; for (i=0; i<k; i++) for (j=0; j<k; j++) if (a[i][j] == 0) if ((j+1 < k && a[i][j+1] == 0) (i+1<k && a[i+1][j] == 0)) return 1;