לדלג לתוכן

2.3 בקרת זרימה ולולאות פתרון

פתרון - בקרת זרימה ולולאות

פתרון תרגיל 1

for (let i = 1; i <= 100; i++) {
    if (i % 3 === 0 && i % 5 === 0) {
        console.log("FizzBuzz");
    } else if (i % 3 === 0) {
        console.log("Fizz");
    } else if (i % 5 === 0) {
        console.log("Buzz");
    } else {
        console.log(i);
    }
}

חשוב לבדוק את i % 3 === 0 && i % 5 === 0 ראשון, אחרת מספר שמתחלק בשניהם ייתפס קודם רק על ידי אחד מהם.

פתרון תרגיל 2

let dayNumber = Number(prompt("Enter a day number (1-7):"));

let dayName;
let dayType;

switch (dayNumber) {
    case 1:
        dayName = "Sunday";
        break;
    case 2:
        dayName = "Monday";
        break;
    case 3:
        dayName = "Tuesday";
        break;
    case 4:
        dayName = "Wednesday";
        break;
    case 5:
        dayName = "Thursday";
        break;
    case 6:
        dayName = "Friday";
        break;
    case 7:
        dayName = "Saturday";
        break;
    default:
        dayName = "Invalid day";
}

// using fall-through for day type
switch (dayNumber) {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
        dayType = "Workday";
        break;
    case 6:
    case 7:
        dayType = "Weekend";
        break;
    default:
        dayType = "";
}

console.log(`Day: ${dayName}`);
if (dayType) {
    console.log(`Type: ${dayType}`);
}

פתרון תרגיל 3

const secretNumber = 42;
const maxAttempts = 7;
let attempts = 0;
let guessed = false;

while (attempts < maxAttempts && !guessed) {
    let input = prompt(`Guess the number (attempt ${attempts + 1}/${maxAttempts}):`);

    if (input === null) {
        console.log("Game cancelled!");
        break;
    }

    let guess = Number(input);
    attempts++;

    if (isNaN(guess)) {
        console.log("Please enter a valid number");
        continue;
    }

    if (guess === secretNumber) {
        guessed = true;
        alert(`Correct! You got it in ${attempts} attempts!`);
    } else if (guess < secretNumber) {
        console.log("Too low!");
    } else {
        console.log("Too high!");
    }
}

if (!guessed) {
    console.log(`Game over! The number was ${secretNumber}`);
}

פתרון תרגיל 4

// ascending triangle
for (let i = 1; i <= 5; i++) {
    let row = "";
    for (let j = 0; j < i; j++) {
        row += "*";
    }
    console.log(row);
}

console.log("---");

// descending triangle
for (let i = 5; i >= 1; i--) {
    let row = "";
    for (let j = 0; j < i; j++) {
        row += "*";
    }
    console.log(row);
}

פלט:

*
**
***
****
*****
---
*****
****
***
**
*

פתרון תרגיל 5

// Part A - if/else if/else
let score = 85;
let grade;

if (score >= 90) {
    grade = "A";
} else if (score >= 80) {
    grade = "B";
} else if (score >= 70) {
    grade = "C";
} else if (score >= 60) {
    grade = "D";
} else {
    grade = "F";
}

console.log(`Grade: ${grade}`);

// Part B - for...of with break
const fruits = ["apple", "banana", "cherry", "date"];

for (const fruit of fruits) {
    if (fruit === "cherry") {
        console.log(`Found it: ${fruit}!`);
        break;
    }
    console.log(`Checking: ${fruit}`);
}

// Part C - while loop
let total = 0;
let n = 1;

while (n <= 10) {
    if (n % 2 === 0) {
        total += n;
    }
    n++;
}

console.log(`Sum of even numbers 1-10: ${total}`);

שינויים מפייתון:
- elif הפך ל-else if
- for fruit in fruits: הפך ל-for (const fruit of fruits)
- == הפך ל-===
- f"..." הפך ל-`...`
- n += 1 אפשר גם n++

פתרון תרגיל 6

const correctPassword = "secret123";
const maxAttempts = 3;
let attempt = 0;
let success = false;

do {
    let input = prompt(`Enter password (${maxAttempts - attempt} attempts left):`);

    if (input === null) {
        console.log("Cancelled");
        break;
    }

    attempt++;

    if (input === correctPassword) {
        success = true;
        alert("Access granted!");
    } else {
        let remaining = maxAttempts - attempt;
        if (remaining > 0) {
            console.log(`Wrong password. ${remaining} attempts left.`);
        }
    }
} while (!success && attempt < maxAttempts);

if (!success && attempt >= maxAttempts) {
    alert("Account locked!");
}

השתמשנו ב-do...while כי צריך לשאול את המשתמש לפחות פעם אחת לפני שבודקים אם נגמרו הניסיונות.

פתרון תרגיל 7

א. for...of עם מערך:

const words = ["hi", "hello", "hey", "greetings", "yo", "welcome"];

for (const word of words) {
    if (word.length > 4) {
        console.log(word);
    }
}
// prints: "hello", "greetings", "welcome"

ב. for...in עם אובייקט:

const product = {
    name: "Laptop",
    price: 999,
    brand: "Dell",
    weight: 1.5,
    color: "Silver",
    stock: 42
};

for (const key in product) {
    if (typeof product[key] === "number") {
        console.log(`${key}: ${product[key]}`);
    }
}
// prints:
// "price: 999"
// "weight: 1.5"
// "stock: 42"

פתרון תרגיל 8

function canWatch(user, movie) {
    if (user === null) {
        return "No user found";
    }

    if (!user.isLoggedIn) {
        return "Please log in first";
    }

    if (!user.hasPaid) {
        return "Please purchase a subscription";
    }

    if (user.age < movie.minAge) {
        return "You are too young for this movie";
    }

    return "Enjoy the movie!";
}

עם guard clauses הקוד שטוח ומסודר - כל תנאי בלתי תקין גורם ליציאה מוקדמת, וה-"happy path" (החלק הראשי) בסוף בלי קינון.

פתרון תרגיל 9

for (let i = 1; i <= 10; i++) {
    for (let j = 1; j <= 10; j++) {
        console.log(`${i} x ${j} = ${i * j}`);
    }
    console.log(""); // empty line between numbers
}

פתרון תרגיל 10

for (let num = 2; num <= 100; num++) {
    let isPrime = true;

    for (let i = 2; i <= Math.sqrt(num); i++) {
        if (num % i === 0) {
            isPrime = false;
            break; // no need to check further
        }
    }

    if (isPrime) {
        console.log(num);
    }
}
  • הלולאה החיצונית עוברת על כל מספר מ-2 עד 100
  • הלולאה הפנימית בודקת אם המספר מתחלק במספר כלשהו מ-2 עד השורש שלו
  • אם נמצא מחלק - המספר לא ראשוני, נצא עם break
  • אם לא נמצא מחלק - המספר ראשוני, נדפיס אותו

תשובות לשאלות

  1. for...of עובר על ערכים - משתמשים בו עם מערכים ומחרוזות. for...in עובר על מפתחות (keys) - משתמשים בו עם אובייקטים. אל תשתמשו ב-for...in על מערכים כי הוא מחזיר אינדקסים כמחרוזות.

  2. do...while מריץ את הבלוק לפחות פעם אחת לפני שבודק את התנאי. משתמשים בו כשצריך שהפעולה תתבצע לפחות פעם אחת - למשל בקשת קלט מהמשתמש.

  3. בלי break ב-switch, הקוד "נופל" ל-case הבא (fall-through) ומריץ אותו גם. למשל אם color הוא "red" ואין break, ירוצו גם הפקודות של "green" ו-"blue".

  4. guard clauses הופכים קוד עם הרבה קינון (nesting) לקוד שטוח וקריא. במקום לקנן if בתוך if בתוך if, בודקים מקרי קצה ויוצאים מוקדם עם return.

  5. בJS אין אופרטור // לחילוק שלם. משתמשים ב-Math.floor(a / b) כדי לעגל למטה את תוצאת החילוק. למשל Math.floor(10 / 3) מחזיר 3.