דילוג לתוכן המרכזי

בגרות במדעי המחשב יסודות מדעי המחשב 899371 - בחינה לדוגמה

1–2 יח"ל · שאלון 899371 · 6 שאלות · 2 שעות · פתרון מלא לכל סעיף

בחינת הבגרות במדעי המחשב, יסודות מדעי המחשב, בחינה לדוגמה, כל 6 השאלות כמו בשאלון. לכל סעיף יש תשובה ופתרון מלא: הרעיון, הקוד או המעקב, ובדיקה קצרה. כל קוד מופיע ב-Java וב-C#. נסו לפתור לבד, ואז פתחו את הפתרון.

הוראות הבחינה (כמו בשאלון)

א. משך הבחינה: שעתיים.

ב. מבנה השאלון ומפתח הערכה: בשאלון זה שני פרקים.
פרק ראשון (2 * 20) 40 נקודות
פרק שני (2 * 30) 60 נקודות
סך הכל 100 נקודות

חומר עזר מותר בשימוש: כל חומר עזר, חוץ ממחשבון שיש בו אפשרוּת תכנות.

הוראות מיוחדות:
את כל התוכניות שיש לכתוב בשפת מחשב בשפה אחת בלבד – Java או C#.
הערה: לא יורדו נקודות אם תכתבו בתוכניות אות גדולה במקום אות קטנה או להפך.

יש לכתוב במחברת הבחינה בלבד. יש לרשום "טיוטה" בראש כל עמוד המשמש טיוטה.
כתיבת טיוטה בדפים שאינם במחברת הבחינה עלולה לגרום לפסילת הבחינה.

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

בהצלחה!

השאלות
בשאלון זה שני פרקים.
יש לענות על שאלות משני הפרקים, לפי ההוראות בכל פרק.

הערה: בכל שאלה שנדרשת בה קליטה, אין צורך לבדוק את תקינות הקלט.
לפותרים בשפת Java: בכל שאלה שנדרשת בה קליטה, הניחו שבתוכנית כתובה ההוראה:
Scanner input = new Scanner(System.in);

פרק ראשון

ענו על שתי שאלות מתוך השאלות 1–3 (20 נקודות לכל שאלה)

שאלה 1 · מעקב – זוגות סמוכים שווים במערך (20 נקודות)

נתונים שני מערכים מטיפוס שלם: a בגודל 9 , ו־ b בגודל 8.

המערך a מכיל מספרים גדולים מ־ 0 , והמערך b מכיל כולו אפסים.

012345678
a28881224776
01234567
b00000000

נתון קטע התכנית שלפניך, הכתוב ב־ Java וב־ C#.

Java

Java
int count = 0;
for(int i=0; i<(a.length-1); i++)
{
      if(a[i] == a[i+1])
      {
         b[count] = a[i];
         count++;
      }
}

C#

C#
int count = 0;
for(int i=0; i<(a.Length-1); i++)
{
      if(a[i] == a[i+1])
      {
         b[count] = a[i];
         count++;
      }
}
1.

עקבו בעזרת טבלת מעקב אחר ביצוע קטע התכנית בעבור המערכים a ו־ b הנתונים, ורישמו את המערך b לאחר ביצוע קטע התכנית.
בטבלת המעקב יש לכלול עמודה לכל אחד מהמשתנים האלה: b[count], count, a[i], a[i+1], i

2.

תנו דוגמה מייצגת למערך a בגודל 9 המכיל מספרים גדולים מ־ 0 ,שבעבורו, לאחר ביצוע קטע התכנית, המערך b יכיל רק אפסים.

◂ פתרון מלא לשאלה 1

סעיף 1

תשובה

b = {8, 8, 7, 0, 0, 0, 0, 0} (count = 3)

מה נדרש: לעקוב בטבלת מעקב אחר ביצוע הקטע על המערכים הנתונים, ולרשום את b בסוף.

רעיון: הלולאה עוברת על כל זוג תאים סמוכים ב־a: (a[0],a[1]), (a[1],a[2]), …, (a[7],a[8]) – כלומר i רץ מ־0 עד 7 (8 איטרציות, כי התנאי הוא i < a.length-1 = 8). בכל פעם ששני תאים סמוכים שווים, הערך נכתב ל־b במקום count, ו־count גדל ב־1. כך b מתמלא מתחילתו בערכים שהופיעו "פעמיים ברצף".

פתרון – טבלת מעקב (count ו־b[count] אחרי ביצוע גוף הלולאה; בעמודה b[count] רשומה ההשמה כשהיא מתבצעת):

ia[i]a[i+1]a[i] == a[i+1] ?b[count]count
(התחלה)0
028לא–0
188כןb[0] ← 81
288כןb[1] ← 82
3812לא–2
41224לא–2
5247לא–2
677כןb[2] ← 73
776לא–3
8הלולאה מסתיימת (8 < 8 לא מתקיים)3

המערך b לאחר ביצוע קטע התכנית:

01234567
b88700000

בדיקה: על המערכים הנתונים מתקבל b = 8 8 7 0 0 0 0 0 ו־count = 3.

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

סעיף 2

תשובה

למשל a = {1, 2, 3, 4, 5, 6, 7, 8, 9} – כל מערך שאין בו שני תאים סמוכים שווים.

מה נדרש: מערך a בגודל 9 עם מספרים חיוביים שבעבורו b יישאר כולו אפסים.

רעיון: ל־b נכתב ערך רק כאשר a[i] == a[i+1]. כל הערכים ב־a גדולים מ־0, ולכן כל השמה הייתה מכניסה ל־b ערך שונה מ־0. מכאן ש־b נשאר אפסים אם ורק אם אין ב־a שני תאים סמוכים שווים.

פתרון: דוגמה מייצגת:

012345678
a123456789

(כל מערך שבו אין שני תאים סמוכים שווים מתאים, למשל גם 5, 3, 5, 3, 5, 3, 5, 3, 5 – ערכים שווים מותרים, כל עוד הם לא צמודים.)

בדיקה: בשתי הדוגמאות התנאי לא מתקיים אף פעם, count נשאר 0 ו־b = 0 0 0 0 0 0 0 0.

שאלה 2 · דמי משלוח – קליטה, צבירה ומניה (20 נקודות)

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

הערה: אין צורך לבדוק את תקינות הקלט.

1.

כיתבו ב־ Java פעולה בשם check (ב C# Check) שתקבל מספר שלם וגדול מ־ 0 המייצג את מספר המוצרים שלקוח הזמין. הפעולה תקלוט לכל מוצר את מחירו.
הפעולה תחזיר true אם הלקוח אינו צריך לשלם דמי משלוח, אחרת — הפעולה תחזיר false.

2.

כיתבו ב־ Java פעולה בשם checkAll (ב- C# CheckAll) שתקלוט בעבור כל אחד מ־ 850 הלקוחות שהזמינו מוצרים בטלפון ביום מסוים, את מספר המוצרים שכל אחד מהם הזמין. הפעולה תדפיס את מספר הלקוחות שצריכים לשלם דמי משלוח.
ניתן להשתמש בפעולה שכתבתם בסעיף א.

◂ פתרון מלא לשאלה 2

סעיף 1

תשובה

צוברים n מחירים שנקלטים ומחזירים sum > 150.

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

רעיון: צבירה – משתנה sum מתחיל ב־0, בלולאה של n סיבובים קולטים מחיר ומוסיפים אותו לסכום. בסוף מחזירים את ערך הביטוי sum > 150. המחיר נקלט כמספר ממשי (double), כי מחיר יכול להיות לא שלם.

פתרון: הקוד המלא – בלשונית Java/C#. ב־Java משתמשים ב־input שהוגדר בתוכנית (Scanner input = new Scanner(System.in)); ב־C# קולטים עם double.Parse(Console.ReadLine()).

בדיקה:

•2 מוצרים: 100, 50 ⇒ סכום 150, לא גדול מ־150 ⇒ false.
•2 מוצרים: 100, 50.5 ⇒ 150.5 ⇒ true.
•מוצר אחד: 200 ⇒ true.
•3 מוצרים: 10, 10, 10 ⇒ false.

טעות נפוצה: לכתוב sum >= 150. לפי השאלה רק סכום גדול מ־150 פוטר מדמי משלוח, וסכום של 150 בדיוק – משלמים.

הקוד המלא
public static boolean check(int n)
{
    double sum = 0;
    for (int i = 0; i < n; i++)
    {
        double price = input.nextDouble();
        sum = sum + price;
    }
    return sum > 150;
}

סעיף 2

תשובה

850 פעמים: קולטים מספר מוצרים; אם !check(products) – count++; בסוף מדפיסים count.

מה נדרש: לקלוט לכל אחד מ־850 הלקוחות את מספר המוצרים שלו, ולהדפיס כמה לקוחות צריכים לשלם דמי משלוח.

רעיון: לולאה של 850 סיבובים. בכל סיבוב קולטים את מספר המוצרים של הלקוח ומזמנים את check עם המספר הזה – check עצמה קולטת את המחירים ומחזירה האם הלקוח פטור. אם check מחזירה false, הלקוח צריך לשלם ⇒ מגדילים מונה. בסוף מדפיסים את המונה.

פתרון: הקוד המלא – בלשונית Java/C#.

בדיקה: על קלט גדול של לקוחות הפעולה מחזירה בדיוק את מספר הלקוחות שסכומם לכל היותר 150. שתי הגרסאות הדפיסו 436.

טעות נפוצה: לספור את הלקוחות שפטורים מדמי משלוח (check מחזירה true) במקום את אלה שצריכים לשלם. שימו לב גם שאין לקלוט את המחירים ב־checkAll – הקליטה שלהם נעשית בתוך check.

הקוד המלא
public static void checkAll()
{
    int count = 0;
    for (int i = 1; i <= 850; i++)
    {
        int products = input.nextInt();
        if (!check(products))
            count++;
    }
    System.out.println(count);
}

שאלה 3 · בריכה – מערך הרשאות לפי גיל (20 נקודות)

בבריכה "מים גועשים" יש 3 מתקנים: מקפצה, ג'קוזי וסאונה.

במקפצה יכולים להשתמש בני 12 ומעלה.

בג'קוזי יכולים להשתמש בני 16 ומעלה.

בסאונה יכולים להשתמש בני 18 ומעלה.

הערה: אין צורך לבדוק את תקינות הקלט.

1.

כיתבו פעולה בשם checkAge (ב- C# - CheckAge) שתקבל מספר שלם age המייצג גיל של מבקר בבריכה.
הפעולה תחזיר מערך חד־ממדי של מספרים שלמים בגודל 3. כל תא במערך מייצג את אחד מהמתקנים בבריכה. סדר התאים במערך: מקפצה (תא 0), ג'קוזי (תא 1), סאונה (תא 2).
במערך יופיע הערך 1 בעבור מתקן שהמבקר רשאי להשתמש בו (בהתאם לגילו – age) והערך 0 בעבור מתקן שהמבקר אינו רשאי להשתמש בו.

2.

כיתבו פעולה בשם count (ב- C# - Count) שתקלוט בעבור יום מסוים את גילו של כל מבקר בבריכה.
הקלט מסתיים כאשר ייקלט מבקר שאינו רשאי להשתמש בשום מתקן.
הפעולה תדפיס את מספר המבקרים שרשאים להשתמש בכל אחד מן המתקנים באותו יום. אין חשיבות לסדר ההדפסה.
דוגמה להדפסה: 10,20,15

◂ פתרון מלא לשאלה 3

סעיף 1

תשובה

מערך int[3]; arr[0]=1 אם age≥12, arr[1]=1 אם age≥16, arr[2]=1 אם age≥18.

מה נדרש: פעולה שמקבלת גיל ומחזירה מערך בגודל 3 של 0/1: תא 0 – מקפצה (12+), תא 1 – ג'קוזי (16+), תא 2 – סאונה (18+).

רעיון: יוצרים מערך חדש בגודל 3 – כל תאיו מאותחלים אוטומטית ל־0. לכל מתקן בודקים בנפרד אם הגיל מגיע לגיל המינימום שלו, ואם כן – מציבים 1 בתא שלו. משתמשים בשלושה if נפרדים (ולא if–else if), כי מבקר יכול להיות רשאי להשתמש בכמה מתקנים יחד.

פתרון: הקוד המלא – בלשונית Java/C#.

בדיקה:

ageמערך מוחזר
11[0,0,0]
12[1,0,0]
15[1,0,0]
16[1,1,0]
17[1,1,0]
18[1,1,1]
40[1,1,1]

טעות נפוצה: להשתמש ב־else if החל מהגיל הנמוך – אז בן 18 יקבל רק [1,0,0]. וגם לבדוק "גדול מ־12" במקום "גדול או שווה ל־12": בני 12 בדיוק רשאים להשתמש במקפצה.

הקוד המלא
public static int[] checkAge(int age)
{
    int[] arr = new int[3];   // כל התאים מאותחלים ל-0
    if (age >= 12)
        arr[0] = 1;           // מקפצה
    if (age >= 16)
        arr[1] = 1;           // ג'קוזי
    if (age >= 18)
        arr[2] = 1;           // סאונה
    return arr;
}

סעיף 2

תשובה

לולאת זקיף עם checkAge: כל עוד המבקר רשאי במתקן כלשהו – counters[i] += allowed[i]; בסוף מדפיסים את 3 המונים.

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

רעיון: מערך מונים counters בגודל 3 (תא לכל מתקן, באותו סדר כמו במערך ש־checkAge מחזירה). לולאת זקיף (while):

1.קולטים גיל ראשון ומחשבים allowed = checkAge(age).
2.כל עוד המבקר רשאי במתקן אחד לפחות (סכום שלושת התאים גדול מ־0) – מוסיפים את allowed[i] ל־counters[i] לכל i (1 מגדיל את המונה, 0 לא משנה), ואז קולטים את הגיל הבא ומחשבים לו את allowed.
3.בסוף מדפיסים את שלושת המונים, מופרדים בפסיקים.

המבקר האחרון (זה שעוצר את הקלט) אינו רשאי באף מתקן, ולכן ממילא אינו נספר. (אפשר גם לכתוב את התנאי allowed[0] == 1: מי שאינו רשאי במקפצה – אינו רשאי בשום מתקן.)

פתרון: הקוד המלא – בלשונית Java/C#.

בדיקה: קלט: 13, 17, 25, 16, 12, 30, 19, 8.

•מקפצה: כל 7 המבקרים שלפני ה־8 ⇒ 7.
•ג'קוזי: 17, 25, 16, 30, 19 ⇒ 5.
•סאונה: 25, 30, 19 ⇒ 3.

הפלט: 7,5,3. כשהגיל הראשון הוא 5 הודפס 0,0,0.

טעות נפוצה: לקלוט את הגיל רק בתוך הלולאה ולבדוק את התנאי על גיל שעוד לא נקלט, או לספור גם את המבקר שסיים את הקלט.

הקוד המלא
public static void count()
{
    int[] counters = new int[3];
    int age = input.nextInt();
    int[] allowed = checkAge(age);
    while (allowed[0] + allowed[1] + allowed[2] > 0)
    {
        for (int i = 0; i < 3; i++)
            counters[i] = counters[i] + allowed[i];
        age = input.nextInt();
        allowed = checkAge(age);
    }
    System.out.println(counters[0] + "," + counters[1] + "," + counters[2]);
}

פרק שני

ענו על שתי שאלות מתוך השאלות 4–6 (30 נקודות לכל שאלה)

שאלה 4 · תעודה ומקצועות – מערך עצמים (30 נקודות)

נתונה המחלקה Subject המייצגת מקצוע בתעודה של תלמיד ולה שתי תכונות: שם המקצוע - subName והציון – grade (מספר שלם בין 0-100)

Java
public class Subject{
      private String subName;
      private int grade;
}

בנוסף, נתונה המחלקה ReportCard המייצגת תעודה של תלמיד ולה שתי תכונות: שם התלמיד – stuName ומערך של עצמים subArray מטיפוס Subject בגודל מספר המקצועות שהתלמיד למד.

Java
public class ReportCard{
      private String stuName;
      private Subject[] subArray;
}

הנח שקיימות פעולות get ו- set בעבור כל התכונות בשתי המחלקות.

לפנייך ממשק חלקי של המחלקה ReportCard

תאור הפעולהכותרת הפעולה
פעולה בונה המקבלת את שם התלמיד ומספר המקצועות שלמד ומאתחלת את התכונות. המערך subArray מאותחל למערך ריק בגודל numpublic ReportCard(String name, int num)
פעולה המחזירה את ממוצע כל הציונים בתעודה של התלמיד.public double average()
פעולה המחזירה true אם התלמיד נחשב מצטיין, אחרת מחזירה false. תלמיד מצטיין הוא תלמיד אשר ממוצע ציוניו הוא 85 ומעלה.public Boolean isExcellent()
א.

ממשו את הפעולה הבונה של המחלקה ReportCard.

ב.

ממשו את הפעולה isExcellent במחלקה ReportCard.
ניתן להשתמש בפעולה average של המחלקה ReportCard מבלי לממש אותה.
הניחו כי איברי המערך subarray שונים מ- null.

ג.

כיתבו פעולה חיצונית ששמה PrintExcellent המקבלת מערך של עצמים – array מטיפוס ReportCard המייצג תלמידים מכיתה מסויימת. הפעולה תדפיס את שמות התלמידים המצטיינים.
חובה להשתמש בפעולה isExcellent של המחלקה ReportCard.
הניחו כי איברי המערך subarray שונים מ- null.

◂ פתרון מלא לשאלה 4

סעיף א

תשובה

stuName = name; subArray = new Subject[num];

מה נדרש: לממש את הפעולה הבונה ReportCard(name, num).

רעיון: הבנאי מציב את השם בתכונה stuName, ויוצר מערך חדש של num הפניות לעצמים מטיפוס Subject. המערך "ריק": כל תאיו מאותחלים ל־null (עדיין אין בו עצמי Subject).

פתרון: הקוד המלא – בלשונית Java/C#.

בדיקה: אחרי new ReportCard("Test", 4) התקבל: stuName = "Test", אורך subArray הוא 4, ו־subArray[0] הוא null.

טעות נפוצה: ליצור בבנאי גם עצמי Subject חדשים לכל תא (אין לנו את שמות המקצועות והציונים), או לכתוב Subject[] subArray = new Subject[num]; – הצהרה על משתנה מקומי חדש, שמשאירה את התכונה עצמה null.

הקוד המלא
public ReportCard(String name, int num)
{
    this.stuName = name;
    this.subArray = new Subject[num];
}

סעיף ב

תשובה

return this.average() >= 85;

מה נדרש: לממש את isExcellent – true אם ממוצע הציונים 85 ומעלה.

רעיון: מותר להשתמש ב־average בלי לממש אותה. מזמנים אותה על העצם הנוכחי ומשווים: average() >= 85.

פתרון: הקוד המלא – בלשונית Java/C#. (בממשק כתוב הטיפוס Boolean; ב־Java אפשר להחזיר boolean או Boolean – שניהם עובדים. ב־C# הטיפוס הוא bool.)

בדיקה:

תלמידציוניםממוצעisExcellent
Dana90, 80, 8585.0true
Avi84, 86, 8484.67false
Noa100, 7085.0true
Yossi60, 70, 8070.0false
Maya8585.0true

טעות נפוצה: לכתוב > 85 – ממוצע של 85 בדיוק הוא כבר "מצטיין".

הקוד המלא
public boolean isExcellent()
{
    return this.average() >= 85;
}

סעיף ג

תשובה

לכל i: אם array[i].isExcellent() – מדפיסים array[i].getStuName().

מה נדרש: פעולה חיצונית (סטטית, מחוץ למחלקה ReportCard) שמקבלת מערך תעודות ומדפיסה את שמות התלמידים המצטיינים, תוך שימוש ב־isExcellent.

רעיון: עוברים על כל תאי המערך. לכל תעודה שואלים array[i].isExcellent(); אם התשובה true – מדפיסים את שם התלמיד בעזרת פעולת ה־get של התכונה stuName (שהשאלה מניחה שקיימת). הפעולה חיצונית, ולכן אסור לגשת ישירות לתכונה הפרטית stuName.

פתרון: הקוד המלא – בלשונית Java/C#.

בדיקה: על מערך של 5 התעודות מהטבלה בסעיף ב מודפסים:

Dana
Noa
Maya

טעות נפוצה: לכתוב array[i].stuName – התכונה פרטית (private) ואין אליה גישה מחוץ למחלקה; חייבים getStuName() (ב־C#: GetStuName()).

הקוד המלא
public static void PrintExcellent(ReportCard[] array)
{
    for (int i = 0; i < array.length; i++)
    {
        if (array[i].isExcellent())
            System.out.println(array[i].getStuName());
    }
}

שאלה 5 · פיקסלים – מערך דו־ממדי של עצמים (30 נקודות)

פיקסל (Pixel) הוא יחידת מידע המתארת נקודה בתמונה דיגיטלית. כל פיקסל מורכב משילוב של שלושה צבעים: אדום, ירוק וכחול.
כל אחד משלושת הצבעים האלה (אדום, ירוק וכחול) מקבל ערך מספרי מ־ 0 עד 255 (כולל). המספר מייצג את עוצמת הצבע בנקודה. באמצעות שילוב של שלושת הצבעים בערכים שונים מ־ 0 עד 255 אפשר לקבל כל גוון בקֶשת הצבעים.

נתונה המחלקה Pixel – פיקסל, ולה שלוש תכונות:

•red – צבע אדום, מספר שלם מ־0 עד 255
•green – צבע ירוק, מספר שלם מ־0 עד 255
•blue – צבע כחול, מספר שלם מ־0 עד 255

הניחו שיש פעולות get/Get ו־set/Set בעבור תכונות המחלקה. ניתן להשתמש בפעולות המחלקה מבלי לממש אותן.

נתון ממשק חלקי של המחלקה: Pixel

תיאור הפעולהכותרת הפעולה
פעולה בונה המקבלת ערכים בעבור תכונות המחלקהpublic Pixel (int red, int green, int blue)
פעולה המחזירה true אם הנקודה היא בצבע אדום, אחרת היא מחזירה falseJava – public boolean isRed ()<br>C# – public bool IsRed ()
פעולה המחזירה true אם הנקודה היא בצבע ירוק, אחרת היא מחזירה falseJava – public boolean isGreen ()<br>C# – public bool IsGreen ()
פעולה המחזירה true אם הנקודה היא בצבע כחול, אחרת היא מחזירה falseJava – public boolean isBlue ()<br>C# – public bool IsBlue ()
פעולה המחזירה true אם הנקודה היא בצבע שאינו כחול, אדום וירוק.Java – public boolean isOther ()<br>C# – public bool IsOther ()

נתונה המחלקה Structure – ולה תכונה אחת בלבד:

•arr – מערך דו־ממדי מטיפוס Pixel בגודל N*N.
1.

כתבו פעולה פנימית במחלקה Structure ששמה isBalanced בשפת Java או IsBalanced בשפת C# .
הפעולה תחזיר true אם במערך arr מספר הנקודות בצבע האדום זהה למספר הנקודות בצבע הירוק וזהה למספר הנקודות בצבע הכחול. אחרת הפעולה תחזיר false .
שימו לב: הפעולה תחזיר true גם אם יש נקודות בצבעים שאינם אדום, ירוק וכחול, כל עוד מספרי הנקודות האדומות, הירוקות והכחולות זהים.

2.

כתבו פעולה פנימית במחלקה Structure ששמה allOthers בשפת Java או AllOthers בשפת C#.
הפעולה תחזיר true אם קיימת שורה במערך arr כך שמתקיים התנאי: לכל נקודה בשורה יש צבע שונה מכחול, אדום וירוק. אחרת, הפעולה תחזיר false.

◂ פתרון מלא לשאלה 5

סעיף 1

תשובה

סופרים בלולאה כפולה red/green/blue בעזרת isRed/isGreen/isBlue ומחזירים red == green && green == blue.

מה נדרש: פעולה פנימית ב־Structure שבודקת אם מספר הפיקסלים האדומים = מספר הירוקים = מספר הכחולים במערך הדו־ממדי arr.

רעיון: שלושה מונים (red, green, blue) שמתחילים ב־0. לולאה כפולה עוברת על כל התאים arr[i][j] (שורה i, עמודה j). לכל פיקסל שואלים את פעולות המחלקה Pixel – isRed / isGreen / isBlue – ומגדילים את המונה המתאים. פיקסלים "אחרים" לא נספרים בכלל, וזה בדיוק מה שהשאלה מבקשת. בסוף מחזירים red == green && green == blue.

ב־Java מספר השורות הוא arr.length ואורך שורה הוא arr[i].length; ב־C# המערך מוגדר Pixel[,] ומשתמשים ב־arr.GetLength(0) וב־arr.GetLength(1), ובגישה arr[i, j].

פתרון: הקוד המלא – בלשונית Java/C#.

בדיקה (R/G/B – פיקסל אדום/ירוק/כחול, O – פיקסל בצבע אחר):

•{R,G,B},{O,R,G},{B,O,O} – שניים מכל צבע ⇒ true.
•{R,R,G},{O,Y,O},{B,G,R} (Y – צהוב, צבע "אחר") – 3 אדומים, 2 ירוקים, 1 כחול ⇒ false.
•{R} (מערך 1×1) ⇒ false.
•מערך שכולו פיקסלים "אחרים" – 0 = 0 = 0 ⇒ true (לפי ההגדרה: המספרים זהים).

טעות נפוצה: לכתוב red == green == blue – זה לא חוקי (ב־Java זו שגיאת קומפילציה, כי red == green הוא ערך בוליאני). יש לשלב שתי השוואות עם &&.

הקוד המלא
public boolean isBalanced()
{
    int red = 0, green = 0, blue = 0;
    for (int i = 0; i < arr.length; i++)
    {
        for (int j = 0; j < arr[i].length; j++)
        {
            if (arr[i][j].isRed())
                red++;
            if (arr[i][j].isGreen())
                green++;
            if (arr[i][j].isBlue())
                blue++;
        }
    }
    return red == green && green == blue;
}

סעיף 2

תשובה

לכל שורה: all = true; כל פיקסל שאינו isOther מאפס את all; אם all נשאר true – return true. בסוף return false.

מה נדרש: להחזיר true אם יש לפחות שורה אחת ב־arr שבה כל הפיקסלים הם "אחרים" (isOther מחזירה true).

רעיון: זו שאלה של "קיים ... כך שלכל ...":

•לולאה חיצונית על השורות ("קיימת שורה").
•לכל שורה – משתנה בוליאני all שמתחיל ב־true, ולולאה פנימית על הפיקסלים בשורה ("לכל נקודה"). אם נמצא פיקסל שאינו "אחר" – all הופך ל־false.
•אם בסוף השורה all עדיין true – מצאנו שורה מתאימה ומחזירים true מייד.
•אם עברנו על כל השורות ולא נמצאה שורה כזאת – מחזירים false.

פתרון: הקוד המלא – בלשונית Java/C#.

בדיקה:

•{R,G,B},{O,R,G},{B,O,O} – בכל שורה יש פיקסל אדום/ירוק/כחול ⇒ false.
•{R,R,G},{O,Y,O},{B,G,R} (Y – צהוב, צבע "אחר") – שורה 1 כולה "אחרים" ⇒ true.
•{R,G,B},{G,B,R},{O,Y,O} – השורה האחרונה כולה "אחרים" ⇒ true.
•{R} ⇒ false.

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

הקוד המלא
public boolean allOthers()
{
    for (int i = 0; i < arr.length; i++)
    {
        boolean all = true;   // נניח שכל הנקודות בשורה i "אחרות"
        for (int j = 0; j < arr[i].length; j++)
        {
            if (!arr[i][j].isOther())
                all = false;
        }
        if (all)
            return true;
    }
    return false;
}

שאלה 6 · זוגות "סוף התחלה" – הגרלה למערך עצמים (30 נקודות)

זוג "סוף התחלה" הוא זוג של מספרים חיוביים ושלמים שבו הספרה הראשונה באחד מן המספרים זהה לספרה האחרונה במספר האחר (אין חשיבות לסדר המספרים).
מספר הקטן מ־ 10 (כלומר, שמורכב מספרה אחת בלבד) נחשב גם לספרה הראשונה וגם לספרה האחרונה.

דוגמאות לזוג "סוף התחלה":

מספר Iמספר II
30906783
25534

נתונה המחלקה PairOfNums — זוג מספרים חיוביים, ולה שתי תכונות:

Java
public class PairOfNums {
      private int num1 ;
      private int num2 ;
}

הנח שקיימות פעולות get ו־ set בשפת Java ופעולות Get ו־ Set בשפת C# בעבור תכונות המחלקה.
לפניך ממשק חלקי של המחלקה PairOfNums בשפות Java ו־ C# .
אפשר להשתמש בפעולות הממשק ללא צורך לממש אותן.

תיאור הפעולהכותרת הפעולה
פעולה בונה המקבלת ערכים בעבור תכונות המחלקה.public PairOfNums (int num1, int num2)
פעולה המחזירה true אם העצם הוא זוג "סוף התחלה", אחרת היא מחזירה false .בשפת Java: public boolean endStart ()<br>בשפת C#: public bool EndStart ()

לפניך כותרת פעולה חיצונית בשפת :

public static PairOfNums[] generate (int n)

הפעולה generate / Generate בונה מערך ריק של עצמים מטיפוס PairOfNums בגודל n . בעבור כל תא במערך, הפעולה מגרילה שני מספרים בין 1 ל־ 1,000 (כולל), ובודקת אם הם זוג "סוף התחלה". אם כן, מוכנס לתא עצם שערכי התכונות שלו הם זוג המספרים שהוגרלו. אחרת, הפעולה ממשיכה להגריל מספרים עד שמתקבל זוג "סוף התחלה", ואז מוכנס לתא עצם שערכי התכונות שלו הם זוג המספרים שהוגרלו.
לאחר שהמערך מתמלא, הפעולה מחזירה את המערך.

הערה: הנח ש־ n גדול מאפס.

מַמֵש את הפעולה.

◂ פתרון מלא לשאלה 6

פתרון

תשובה

לכל תא: מגרילים num1, num2 בתחום 1..1000 ויוצרים PairOfNums; כל עוד !endStart() – מגרילים מחדש; מכניסים לתא; בסוף מחזירים את המערך.

מה נדרש: לממש את generate(n): ליצור מערך של n עצמי PairOfNums, שבכל תא שלו יש זוג "סוף התחלה" של מספרים אקראיים בין 1 ל־1000, ולהחזיר אותו.

רעיון:

1.יוצרים מערך PairOfNums[] בגודל n (תאיו null).
2.לכל תא i: מגרילים num1 ו־num2 בתחום 1..1000, ויוצרים מהם עצם PairOfNums.
3.הבדיקה אם זה זוג "סוף התחלה" נעשית בפעולה endStart של העצם (מותר להשתמש בה בלי לממש). כל עוד היא מחזירה false – מגרילים זוג חדש ויוצרים עצם חדש (לולאת while).
4.כשמתקבל זוג מתאים – מכניסים את העצם לתא i.
5.אחרי שכל התאים מלאים – מחזירים את המערך.

הגרלה בתחום 1..1000:

•Java: (int) (Math.random() * 1000) + 1 – הביטוי Math.random() * 1000 נותן ממשי ב־[0,1000), ההמרה ל־int נותנת 0..999, ועוד 1 ⇒ 1..1000.
•C#: rnd.Next(1, 1001) – הגבול העליון אינו נכלל, ולכן כותבים 1001. עצם ה־Random נוצר פעם אחת בתחילת הפעולה ולא בכל הגרלה.

פתרון: הקוד המלא – בלשונית Java/C#.

בדיקה: לבדיקה צריך את endStart (הספרה האחרונה: x % 10; הספרה הראשונה: מחלקים ב־10 כל עוד x ≥ 10, והתנאי – הספרה האחרונה של אחד שווה לראשונה של האחר, בשני הכיוונים). על דוגמאות השאלה: endStart(3090, 6783) = true, endStart(25, 534) = true, ולעומת זאת endStart(12, 34) = false. בכל מערך שנוצר כל התאים מלאים, כל זוג הוא "סוף התחלה" וכל המספרים בין 1 ל־1000. דוגמה לפלט אחד: (981,629) (904,649) (790,217) (888,818) (257,765) (78,844).

טעות נפוצה: להגריל את הזוג פעם אחת לפני הלולאה על המערך (כך כל התאים יקבלו את אותו זוג), או לשכוח לבנות עצם חדש / להגריל מחדש את שני המספרים בתוך לולאת ה־while – ואז הלולאה לא מסתיימת. טעות נוספת ב־Java: (int) Math.random() * 1000 + 1 – ההמרה ל־int חלה רק על Math.random() ונותנת תמיד 0, והתוצאה תמיד 1.

הקוד המלא
public static PairOfNums[] generate(int n)
{
    PairOfNums[] arr = new PairOfNums[n];
    for (int i = 0; i < n; i++)
    {
        int num1 = (int) (Math.random() * 1000) + 1;   // 1..1000
        int num2 = (int) (Math.random() * 1000) + 1;
        PairOfNums pair = new PairOfNums(num1, num2);
        while (!pair.endStart())
        {
            num1 = (int) (Math.random() * 1000) + 1;
            num2 = (int) (Math.random() * 1000) + 1;
            pair = new PairOfNums(num1, num2);
        }
        arr[i] = pair;
    }
    return arr;
}
טבלת התשובות
שאלהסעיףתשובה
11

b = {8, 8, 7, 0, 0, 0, 0, 0} (count = 3)

2

למשל a = {1, 2, 3, 4, 5, 6, 7, 8, 9} – כל מערך שאין בו שני תאים סמוכים שווים.

21

צוברים n מחירים שנקלטים ומחזירים sum > 150.

2

850 פעמים: קולטים מספר מוצרים; אם !check(products) – count++; בסוף מדפיסים count.

31

מערך int[3]; arr[0]=1 אם age≥12, arr[1]=1 אם age≥16, arr[2]=1 אם age≥18.

2

לולאת זקיף עם checkAge: כל עוד המבקר רשאי במתקן כלשהו – counters[i] += allowed[i]; בסוף מדפיסים את 3 המונים.

4א

stuName = name; subArray = new Subject[num];

ב

return this.average() >= 85;

ג

לכל i: אם array[i].isExcellent() – מדפיסים array[i].getStuName().

51

סופרים בלולאה כפולה red/green/blue בעזרת isRed/isGreen/isBlue ומחזירים red == green && green == blue.

2

לכל שורה: all = true; כל פיקסל שאינו isOther מאפס את all; אם all נשאר true – return true. בסוף return false.

6-

לכל תא: מגרילים num1, num2 בתחום 1..1000 ויוצרים PairOfNums; כל עוד !endStart() – מגרילים מחדש; מכניסים לתא; בסוף מחזירים את המערך.

כל האתר במבט אחד

קיצורי דרך לכל הכלים, הבגרויות והקורסים

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