Skip to content

DRAFT JS QUICKSTART Code Samples

Author TODO Items

Decisions affect what parts of our code execute at run-time. They are the way we are able, as developers, to choose what we want our program to do. All of this can be accomplished with the humble if statement.

The first thing to understand about the if statement is its grammar [TODO: Link]. The basic grammar looks like this.

if(conditionalExpression)
statementOrStatementBlock // true side
else
statementOrStatementBlock // false side

There are two keywords in this grammar.

  • The if keyword tells the computer we’re about to make a true/false decision based on some information (the conditionalExpression). The statementOrStatementBlock will be executed only if the conditional expression produces a true boolean result.
  • The else keyword tells the computer what to do should that conditional expression turns out to produce a false result. Note that the else portion with its statementOrStatementBlock is entirely optional.

Besides the keywords, we have these placeholder parts of the grammar.

  • The conditionalExpression is simply any expression that can produce a true or false value.
    • By the way, the words true and false are JavaScript keywords.
  • A statementOrStatementBlock is either a single statement or a single statement block (a block is zero or more statements inside curly braces - { }).
    • A single statement can be on its own line.
    • A statement block should have the opening curly brace at then end of the same line as the initial statement and the closing curly brace on its own line.

The following is an example of a statement block with properly positioned curly braces.

Sample Code
if(quantity === 0) {
// zero or more lines of code
} else {
// zero or more lines of code
}

It’s important to remember that this if-else structure provides alternate paths of logic. If one path is followed, then the other is not followed.

Let’s explore the If/Else statement with a simple example.

  1. To begin, create a file called grok-decisions.js. Then run it in the terminal with node --watch grok-decisions.js.

  2. Let’s add some code to portray using a self-serve gas station where we want to fuel up our vehicle.

    grok-decisions.js
    let bankBalance = 78.23;
    let preAuthorizationAmount = 50.00;
    if(bankBalance > preAuthorizationAmount) {
    console.log('Transaction Approved.');
    console.log('Please Remove Card Now and Lift Nozzle');
    }
  3. We’ve hard-coded values in our program, and you can probably guess what is going to be displayed on the screen. Because the bank balance is the larger of the two values, then the conditional expression bankBalance > preAuthorizationAmount results in a true, and then the code inside statement block is executed.

    If you’re using the debugger, try placing a breakpoint on the if statement and then step through the code.

  4. Let’s edit the preAuthorizationAmount and increase it to $100.

    grok-decisions.js
    let preAuthorizationAmount = 50.00;
    let preAuthorizationAmount = 100.00;
  5. Now, because 78.23isnotgreaterthan78.23 is *not* greater than 100.0, the code execution jumps past the instructions on the “true” side of the if statement, and nothing is displayed on the screen.

  6. Let’s add an else side to our if statement.

    grok-decisions.js
    if(bankBalance > preAuthorizationAmount) {
    console.log('Transaction Approved');
    console.log('Please Remove Card Now and Lift Nozzle');
    }
    } else {
    console.log('Transaction Declined.');
    console.log('Please Remove Your Card').;
    }
  7. Play with making changes to either the bankBalance or the preAuthorizationAmount and observe the effects. Can you control which output is generated by modifying the values of these variables?

With this simple example, a whole world of possibilities begins to open up for us as programmers. But to really grasp the possibilities, we need to add more decisions and explore more conditioal expressions.

So far, we’ve created two alternate paths of logic by adding a single if statement. Let’s see what else we can compare, and what that might mean for the total number of logical paths available to our program.

  1. Modify the grok-decisions.js to reset the preAuthorizationAmount to $50. Then add some code to track the fuel purchase and update your bank balance.

    grok-decisions.js
    let bankBalance = 78.23;
    let preAuthorizationAmount = 100.00;
    let preAuthorizationAmount = 50.00;
    let actualFuelCost;
    if(bankBalance > preAuthorizationAmount) {
    console.log('Transaction Approved.');
    console.log('Please Remove Card Now and Lift Nozzle');
    actualFuelCost = 23.98;
    } else {
    console.log('Transaction Declined.');
    console.log('Please Remove Your Card');
    actualFuelCost = 0;
    }
    console.log(`Fuel Purchase:\t$ ${actualFuelCost}`);
  2. Let’s enhance the self-serve gas station experience. Often, there’s an option to choose a car wash. Let’s weave that into our existing code.

    grok-decisions.js
    let bankBalance = 78.23;
    let preAuthorizationAmount = 50.00;
    let carWashAmount = 0;
    let actualFuelCost;
    let includeCarWash = true;
    if(includeCarWash == true) {
    carWashAmount = 19.99;
    }
    // remaining code is unchanged...

    Because we have given our carWashAmount an initial value of 0, we don’t have to have an else block on our new IF statement.

  3. Notice how the if uses includeCarWash == true as the conditional expression. Earlier, includeCarWash was given a value of true, and therefore it’s data type is boolean. Since all that a conditional expression needs is a boolean result, it’s redundant to use includeCarWash == true. Let’s fix that.

    grok-decisions.js
    if(includeCarWash == true) {
    if(includeCarWash) {
    carWashAmount = 19.99;
    }

    This is much cleaner. By the way, I was careful in choosing the name includeCarWash for our variable, because it reads smoothly for us as humans:

    “If we include the car wash…”

  4. We’ll fill out the rest of this with a receipt of all the charges. We’ll also reset the car wash amount if the pre-authorization fails.

    grok-decisions.js
    if(bankBalance > preAuthorizationAmount) {
    console.log('Transaction Approved.');
    console.log('Please Remove Card Now and Lift Nozzle');
    actualFuelCost = 23.98;
    } else {
    console.log('Transaction Declined.');
    console.log('Please Remove Your Card');
    actualFuelCost = 0;
    carWashAmount = 0;
    }
    // We'll be using these more in some later examples
    let total;
    let message;
    total = carWashAmount + actualFuelCost;
    message = `
    Fuel Purchase:\t$ ${actualFuelCost}
    Car Wash: +\t$ ${carWashAmount}
    Total: =\t$ ${total}
    `;
    console.log(`Fuel Purchase:\t$ ${actualFuelCost}`);
    console.log(message);
    bankBalance = bankBalance - total;
    console.log(`Your new balance is: $ ${bankBalance}`);
  5. ⚗️ Try some experimentation. Try editing the values for includeCarWash and preAuthorizationAmount in various combinations. Because we have two decision statements stacked on top of each other, how many alternating paths of logic are present in the code?

Let’s throw in some assorted combinations of the other relational operators with a few more if/else statements.

  1. You can think of == as being a “general equality” operator, while === is a “strict equality” operator. Strict equality requires the data types to also match.

    grok-decisions.js
    // Can we compare strings and numbers?
    const five = 5;
    const digit = '5';
    if(digit == five) {
    message = `Looks like '${digit}' and ${five} are the same.`
    console.log(message);
    } else {
    console.log('No, we treat them differently.');
    }
    if(digit === five) {
    console.log('Yup, still the same');
    } else {
    message = `Strictly speaking, '${digit}' (a ${typeof digit}) is not the same as ${five} (which is a ${typeof five})`;
    console.log(message);
    }
  2. The opposite of == is !=. Likewise, the opposite of === is !==.

    grok-decisions.js
    const seven = 7;
    if(seven != five) {
    console.log('Of course 7 is not equal to 5');
    }
    if(seven !== seven.toString()) {
    console.log('Strict equality requires the same value AND data type!');
    }
  3. We’ve seen the > operator. Our remaining operators are >=, < and <=. Have you thought about what the opposite of > is? Examine the following experiment to see if you can figure it out.

    grok-decisions.js
    if(seven >= 7) {
    console.log('\nCan you tell me which operator gives the opposite of >=?');
    }
    if(seven <= 7) {
    console.log('Can you tell me which operator gives the opposite of <=?\n');
    }
  4. There’s another little experiment that you can try. See if your ideas around “opposite” relational operators still holds.

    grok-decisions.js
    let number = 0; // Try different numbers...
    console.log(' 0')
    console.log('<---|---|---|---|---|--->');
    console.log(' The Number Line');
    if(number < 0) {
    console.log('Less than 0 |');
    }
    if(number > 0) {
    console.log(' | Greater than 0');
    }
    if(number === 0) {
    console.log(' Exactly | Zero!')
    }
    console.log(`The number is: ${number}`);

    ⚗️ Do a little more experimentation. Try different values for number and observe the results.

Relational operations are only the beginning. JavaScript also has a few Logical Operators to help us compare boolean values.

  1. We’ve seen the use of a single boolean inside a conditional expression. But what if we had two boolean values. Consider these variables.

    grok-decisions.js
    // Use these to hold true/false values
    let torpedoLoaded, targetSelected;
    // ⚗️ How many combinations of true/false can you do with two boolean variables?
    torpedoLoaded = true;
    targetSelected = true;
  2. Let’s add in some comparisons to explore the logical operators.

    grok-decisions.js
    // Logical OR operator
    if(torpedoLoaded || targetSelected) {
    // Logical NOT operator
    if(!torpedoLoaded) {
    console.log('... loading the torpedo ...');
    }
    if(!targetSelected) {
    console.log('... aquiring target ...');
    }
    }
    // Logical AND operator
    if(torpedoLoaded && targetSelected) {
    console.log('Ready to fire torpedo.');
    }
  3. ⚗️ Play with the code by trying different true/false combinations for the two variables. What do you observe?

We can combine arithmetic, relational and boolean operations to handle complex conditional expressions. When we do that, the natural order of those operations follows this precidence.

  1. Arithmetic operations are executed to produce some value.
  2. Relational operations are performed next to compare values and produce some boolean value.
  3. Logical operations are evaluated to produce a true/false result.
  1. Did you know that for most post-secondary schools in Canada, you need to be enrolled in more than three courses to be considered a full-time student?

    grok-decisions.js
    let courseCount = 4;
    let isEnrolled = false, isFullTimeStudent;
    if(courseCount > 0)
    isEnrolled = true;
    if(isEnrolled && courseCount >= 3)
    isFullTimeStudent = true;
    else
    isFullTimeStudent = false;
    console.log(`\n${courseCount} courses. Full time? ${isFullTimeStudent}`);
  2. Various financing options are available for students, but sometimes full-time students will find themselves eligible for special scholarships. Usually, there are some conditions that might apply…

    grok-decisions.js
    let netIncomeLastYear = 32_374; // $32,374
    let currentGpa = 3.8; // 😊
    let existingBursaries = 0; // 😢
    let eligibleScholarship = 0;
    // Are you eligible for extra funding?
    if(isFullTimeStudent && netIncomeLastYear / 2 < 16_198 && currentGpa >= 3.5)
    eligibleScholarship = 2_500;
    else if(isFullTimeStudent && netIncomeLastYear / 2 < 16_198 && currentGpa > 3.0)
    eligibleScholarship = 1_500;
    else if(existingBursaries < netIncomeLastYear / 8.2 && currentGpa > 3.7)
    eligibleScholarship = 2_000;
    console.log(`You are eligible for $ ${eligibleScholarship} in special funding.\n`);
  3. Review the code above carefully. Can you see the order of operations? Part of the job of a developer is to think through whatever possible logic is required to produce the correct solution.

Hopefully you’re already aware that JavaScript is a dynamically typed language. That has a bearing on decisions because you don’t need a strictly-typed true or false in a conditional expression. JavaScript supports the notion of “truthy” and “falsy” values.

  1. Remember the student funding we were exploring? We can test if any scholarships or bursaries are available. A non-zero value would be regarded as “truthy”.

    grok-decisions.js
    if(existingBursaries) {
    console.log(`You have been granted $ ${existingBursaries} in additional funding.`);
    }
    if(eligibleScholarship) {
    console.log(`You are eligible for $ ${eligibleScholarship} in additional scholarships. (Application is required)`);
    }
  2. Imagine that somewhere we have gathered information about a student. (We’ll just hard-code it for now.) We can simply check if that data exists before we proceed to process that information.

    grok-decisions.js
    let student;
    // Hard-code for this demo
    student = {
    id: 19263874,
    name: 'Stewart Dent'
    }
    // Sometime later in our code...
    if(student) { // IF we have student info...
    console.log('Your eligibility status has been forwarded to the registrar''s office');
    } else {
    console.log('Please log in to preserve your funding assessment.');
    }
  3. This could be a good opportunity to experiment with additional truthy/falsy decisions. What further examples can you create on your own?

When things go sideways...

Fixing Bugs

If you’ve made it this far, then you need to consider how we might accidentally introduce “bugs” into our code that are revealed only at run-time. These are called Logical Errors. Conditional expressions are a common place where these errors occur.

Head over to the following article to discover some of the more common logical errors that can creep into our code.

Logical Errors

Part 7 - Using Function Calls in Decisions

Section titled “Part 7 - Using Function Calls in Decisions”

If you understand what expressions are, you might have already thought of how you might involve a function call in your conditional expression.

  1. Add the following functions at the end of your script file.

    grok-decisions.js
    // Helper functions for financial assistance
    function calculateScholarship(isFullTime, currentGpa, income, bursaries) {
    let eligibleAmount = 0;
    const isLowIncome = checkIncome(income);
    const hasLowBursaries = checkBursariesAgainstIncome(bursaries, income);
    if(isFullTime && isLowIncome && hasSufficentGPA(currentGpa))
    eligibleAmount = 2_500;
    else if(isFullTime && isLowIncome && hasMinimumGPA(currentGpa))
    eligibleAmount = 1_500;
    else if(hasLowBursaries && hasHighGPA(currentGpa))
    eligibleAmount = 2_000;
    return eligibleAmount;
    }
    function checkIncome(netIncome) {
    const baseLimit = 16_198;
    // return a boolean value
    return netIncome / 2 < baseLimit;
    }
    function checkBursariesAgainstIncome(bursaries, netIncome) {
    return bursaries < netIncome / 8.2;
    }
    function hasMinimumGPA(gpa) {
    return gpa > 3.0;
    }
    function hasSufficentGPA(gpa) {
    return gpa >= 3.5;
    }
    function hasHighGPA(gpa) {
    return gpa > 3.7;
    }
  2. Return to the code where you were checking for potential scholarships and make the following edits.

    grok-decisions.js
    let netIncomeLastYear = 32_374; // $32,374
    let currentGpa = 3.8; // 😊
    let existingBursaries = 0; // 😢
    let eligibleScholarship = 0;
    let eligibleScholarship = calculateScholarship(isFullTimeStudent, currentGpa, netIncomeLastYear, existingBursaries);
    // Are you eligible for extra funding?
    if(isFullTimeStudent && netIncomeLastYear / 2 < $16_198 && currentGpa >= 3.5)
    eligibleScholarship = 2_500;
    else if(isFullTimeStudent && netIncomeLastYear / 2 < $16_198 && currentGpa > 3.0)
    eligibleScholarship = 1_500;
    else if(existingBursaries < netIncomeLastYear / 8.2 && currentGpa > 3.7)
    eligibleScholarship = 2_000;
    console.log(`You are eligible for $ ${eligibleScholarship} in special funding.\n`);
  3. Consider the effect of these changes. Does the use of functions make the decisions easier to read and understand?

Code Review

Experiment with additional changes to this tutorial. For example, what would happen if you included a 5% sales tax on the price of the car wash (calculated after price is assigned to the variable)? Are there any potential “bugs” in your code? How would you find and fix those bugs?

Perhaps you would like to add descriptions of your data types as you experiment. Consider adding these functions to your script.

Extra functions for grok-decisions.js
const describeDataType = function (value) {
let result;
if (value == undefined || value == null) {
result = `The value is ${value}`;
} else {
result = `The data type is ${value.constructor.name}`;
}
return result;
};
const getDataType = function (value) {
let result;
if (value == undefined || value == null) {
result = `${value}`; // as a string
} else {
result = value.constructor.name;
}
return result;
};
const ify = function (expression) {
let result;
let type = typeof expression;
if (type === "boolean") {
result = expression;
} else if (expression) {
result = `truthy`;
} else {
result = `falsy`;
}
return result;
};

Up to this point, we’ve relied on Simple Sequence and Conditionals (if-else) as the primary means of flow control. Those can take us a long way towards writing sophisticated code to handle complex problems, but they miss a whole other characteristic of code execution critical to most software needs: Handling Repetition.

The idea of doing certain steps over and over is a pretty simple one. A common place where we see this is in the area of mathematics.

Remember the idea of factorials? A factorial is where we follow a pattern of multiplying a number by all the numbers that come before it. For example, the factorial of five is

5!=5×4×3×2×1=1205! = 5 \times 4 \times 3 \times 2 \times 1 = 120

This is an ideal example of a problem that requires repetition to produce the solution (particularly if we want to calculate the factorial of any number, not just 5).

Before we jumpt into the code, let’s take a quick look at the different ways we are able to handle repetition in JavaScript.

Just as with if-else statements, the various types of loops in JavaScript make use of conditional expressions to control the flow of execution. There difference, however, is that the alternate paths of logic for the if-else would only run once, while the alternate paths of logic for the loops can run multiple times (based on the truthiness of the conditional expression).

Let’s look at a couple of the JavaScript statements where we can perform looping.

There are many looping statements in JavaScript. The oldest, and most general-purpose, is the while statement. As a simplistic example, consider the following code. It outputs the numbers 1 through 10 to the console.

while Statement
let count = 1;
while (count <= 10) {
console.log(`Item ${count}`);
count = count + 1;
}

The conditional expression - (count <= 10) - controls the repetition of the code inside the curly braces. As long as that expression results in a true or truthy value, the code will repeat. Also note that the value of count is modified inside the curly braces. Each time through the loop, its value increases by one, until it ultimately holds the value 11. At that point, the conditional expression results in a false, causing the loop to exit.

Another popular looping statement is the for statement. Look again at the code for the while statement. Notice how there are three instructions that control the repetition:

  • let count = 1 - Creates the variable and gives it an initial value
  • count <= 10 - The conditional expression controlling entry to the code in the curly braces
  • count = count + 1 - Changes the value of the variable tested in the conditional expression
while Statement
let count = 1;
while (count <= 10) {
console.log(`Item ${count}`);
count = count + 1;
}

The for statement brings all three of these instructions into one place, making it easier to see what affects execution of the code in the curly braces.

for Statement
// An alternative to our while statement
for (let count = 1; count <= 10; count = count + 1) {
console.log(`Item ${count}`);
}

Looping structures are a powerful way to control the flow of execution of our code. These, along with conditional statements, are great candidates for use inside of functions.

Let’s explore the logic of looping by solving several types of mathematical problems.

In our first example, we’ll use the while loop to calculate the factorial of a number. The while loop is ideal for this problem because we might not know how many times we need to repeat the steps until we reach the number that we’re calculating the factorial for.

  1. Create a file called handling-repetition.js and run it with node --watch handling-repetition.js.

    handling-repetition.js
    // Calculating Factorials
    let number = 5; // Some number that we will use for factorials
  2. Let’s think about the logic that we use in performing our calculations. Specifically, we need to think about which steps are the repeating steps in the calculation. As we can see, it is the multiplication of the numbers and the fact that our numbers increment (or decrement) by 1 each time.

    x!=1×(x+1)×(x+2)×(x+3)x! = 1 \times (x + 1) \times (x + 2) \times (x + 3) \cdots

    The steps continue until we reach the number that we want to calculate the factorial for.

  3. Let’s think about what’s controlling the loop: the number of times we need to multiply. We can use a counter for this. Then we can compare that counter to our original number to determine if we need to repeat the process.

    handling-repetition.js
    // Calculating Factorials
    let number = 5;
    let count = 1;
    let answer = 1; // The multiplicative identity (1) is the starting point for our calculation.
    while(count <= number) {
    answer = answer * count;
    count = count + 1; // This is the same as count++
    }
    console.log(`${number}! = ${answer}`); // 5! = 120

Looping is really just that simple. We have a set of steps that are controlled by some condition. What we do in those steps is up to us. We can do any kind of processing we want, and we can even have multiple loops nested inside each other to handle more complex problems.

In our next example - the Fibonacci sequence - we have a different kind of problem. We want to calculate the next number in the sequence based on the previous two numbers. This is a great example of a problem that can be solved with a loop, but it requires us to keep track of more than one value as we loop through the calculations.

This time, we’ll use a for loop to handle the repetition. The for loop is ideal for this problem because we know how many times we want to repeat the steps (the number of terms in the sequence that we want to calculate).

  1. The Fibonacci sequence is a series of numbers where each number is the sum of the two preceding ones. The sequence starts with 0 and 1, and then continues indefinitely.

    F(n)=F(n1)+F(n2)F(n) = F(n-1) + F(n-2)

    The first few numbers in the Fibonacci sequence are:

    0,1,1,2,3,5,8,13,21,0, 1, 1, 2, 3, 5, 8, 13, 21, \ldots
  2. Add another loop to your handling-repetition.js file to calculate the Fibonacci sequence up to a certain number of terms.

    handling-repetition.js
    // ... previous code for factorials ...
    // Calculating Fibonacci Sequence
    let terms = 10; // Number of terms to calculate
    let a = 0, b = 1, temp;
    console.log(`Fibonacci Sequence up to ${terms} terms:`);
    for(let i = 1; i <= terms; i++) {
    console.log(a);
    temp = a;
    a = b;
    b = temp + b;
    }

We mentioned before that we can have any types of statements in our looping logic. That includes making decisions with if-else statements. Let’s see how we can use a loop to find out if a given number is prime.

  1. A prime number is a natural number greater than 1 that cannot be formed by multiplying two smaller natural numbers. The first few prime numbers are:

    2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, \ldots
  2. But how do we determine if a number is prime? The clue is built into the descrption of prime numbers: A prime number is only evenly divisible by 1 and itself.

    We can again use our counting loop to go from 2 to the number we’re checking. Then, inside the loop, we can use the modulus operator (%) and check if the result is 0. If we ever encounter a case where the result is 0, we know the number is not prime.

  3. Add another loop to your handling-repetition.js file to calculate prime numbers up to a certain limit.

    handling-repetition.js
    // ... previous code for factorials and Fibonacci ...
    // Determining Prime Numbers
    let someNumber = 87; // Is this prime?
    let isPrime = true; // Assume it's prime until we find a divisor
    for(let count = 2; count < someNumber; count++) {
    if(someNumber % count === 0) {
    isPrime = false;
    break;
    }
    }
    console.log(`${someNumber} is ${isPrime ? 'prime' : 'not prime'}`);

We can take our investigation of prime numbers a step further by generating a list of prime numbers up to a certain limit. This will require us to use nested loops: an outer loop to go through the numbers we want to check, and an inner loop to check if each number is prime.

  1. Add another loop to your handling-repetition.js file to generate a list of prime numbers up to a certain limit. We’ll break this logic down into several steps to make it easier to follow.

    handling-repetition.js
    // ... previous code for factorials, Fibonacci, and prime checking ...
    // Generating a List of Prime Numbers
    let limit = 100; // Generate primes up to this number
    console.log(`Prime numbers up to ${limit}:`);
    // This outer loop goes through each number from 2 to the limit
    for(let num = 2; num <= limit; num++) {
    let isPrime = true; // Assume the number is prime until we find a divisor
    }
  2. Inside the outer loop, we need another loop to check if the current number (num) is prime. This inner loop will go from 2 to num - 1 and check if num is divisible by any of those numbers.

    handling-repetition.js
    // ... previous code for factorials, Fibonacci, and prime checking ...
    // Generating a List of Prime Numbers
    let limit = 100; // Generate primes up to this number
    console.log(`Prime numbers up to ${limit}:`);
    // This outer loop goes through each number from 2 to the limit
    for(let num = 2; num <= limit; num++) {
    let isPrime = true;
    // This inner loop checks if the current number is prime
    for(let count = 2; count < num; count++) {
    if(num % count === 0) {
    isPrime = false;
    break;
    }
    }
    }
  3. Finally, after the inner loop, we can check if isPrime is still true. If it is, we can print the number as a prime number.

    handling-repetition.js
    // ... previous code for factorials, Fibonacci, and prime checking ...
    // Generating a List of Prime Numbers
    let limit = 100; // Generate primes up to this number
    console.log(`Prime numbers up to ${limit}:`);
    // This outer loop goes through each number from 2 to the limit
    for(let num = 2; num <= limit; num++) {
    let isPrime = true;
    // This inner loop checks if the current number is prime
    for(let count = 2; count < num; count++) {
    if(num % count === 0) {
    isPrime = false;
    break;
    }
    }
    if(isPrime) {
    console.log('\t', num);
    }
    }

Our first examples of loops were pretty basic. They were designed to illustrate the concept of repetition and how we can use loops to solve problems. But there are many ways we can improve our code to make it more efficient, more readable, and more maintainable. Practice improving your loops by trying to solve the following problems:

  1. For the Factorial example, re-write it to use the for loop instead of the while loop. Which one do you find easier to read and understand?

  2. For the Fibonacci example, modify it to calculate the Fibonacci sequence up to a certain number (instead of a certain number of terms). This will require you to change the logic of your loop and the way you check for the stopping condition.

  3. For determining if a number is prime, how might you optimize the loop to reduce the number of iterations?

    Expand for a hint only after you try it yourself Your first optimization could be to only loop up to half of the number you’re checking. But you can do even better than that by only looping up to the square root of the number.

    Can you explain why that works? If you can, then you have a good understanding of the properties of prime numbers and how to optimize your code to check for them.