Unit 2 - Notes

INT108

Unit 2: Conditional statements; Iterative statements

1. The Modulus Operator

The modulus operator works on integers (and floats) and yields the remainder when the first operand is divided by the second. In Python, the modulus operator is the percent sign (%).

Syntax and Functionality

  • Expression: a % b
  • Result: The remainder of a / b.

Common Use Cases

  1. Checking Parity (Even/Odd):
    • If x % 2 == 0, x is Even.
    • If x % 2 == 1, x is Odd.
  2. Extracting Digits:
    • x % 10 yields the right-most digit of a number (e.g., 123 % 10 returns 3).
    • (x // 10) % 10 yields the second right-most digit.
  3. Cyclic Operations:
    • Useful for wrapping around values (e.g., 24-hour clock arithmetic or array indexing).

PYTHON
print(7 % 3)   # Output: 1 (3 goes into 7 twice, remainder 1)
print(10 % 2)  # Output: 0 (No remainder)
print(5 % 10)  # Output: 5 (10 cannot go into 5)


2. Random Numbers

Computer programs are generally deterministic (the same input produces the same output). To simulate non-determinism for games, simulations, or cryptography, Python provides the random module to generate pseudorandom numbers.

The random Module

You must import the module before use: import random.

Key Functions

  1. random.random():
    • Returns a floating-point number between 0.0 (inclusive) and 1.0 (exclusive).
  2. random.randint(a, b):
    • Returns a random integer such that (inclusive of both endpoints).
  3. random.choice(sequence):
    • Selects a random element from a non-empty sequence (like a list or string).

PYTHON
import random

prob = random.random()      # e.g., 0.4532...
die_roll = random.randint(1, 6)  # 1, 2, 3, 4, 5, or 6


3. Boolean Expressions

A Boolean expression is an expression that is either true or false. Python uses the bool type to represent these values.

Boolean Values

  • True
  • False
  • Note: Capitalization matters in Python.

Relational (Comparison) Operators

These operators compare two values and return a Boolean result:

Operator Meaning Example
== Equal to 5 == 5 (True)
!= Not equal to 5 != 3 (True)
> Greater than 5 > 10 (False)
< Less than 2 < 6 (True)
>= Greater than or equal to 5 >= 5 (True)
<= Less than or equal to 5 <= 4 (False)

Common Error: Confusing the assignment operator (=) with the equality operator (==).


4. Logic Operators

Logical operators allow you to combine multiple Boolean expressions. There are three distinct operators in Python:

1. and

  • Returns True only if both operands are True.
  • Short-circuit evaluation: If the first operand is False, Python stops evaluating because the whole expression must be False.

2. or

  • Returns True if at least one of the operands is True.
  • Short-circuit evaluation: If the first operand is True, Python stops evaluating because the whole expression is guaranteed to be True.

3. not

  • Negates the boolean value. not True becomes False.
  • Has lower precedence than mathematical operators but higher precedence than and/or.

PYTHON
x = 5
print(x > 0 and x < 10)  # True
print(x > 10 or x % 2 != 0) # True (second part is True)
print(not (x == 5))      # False


5. Conditional Statements

Conditional statements allow the program to change its behavior based on the state of variables.

The if Statement

The simplest form of selection.

PYTHON
if condition:
    # Code block executed only if condition is True
    statement

Alternative Execution (if...else)

Provides two possibilities and the condition determines which one executes.

PYTHON
x = 4
if x % 2 == 0:
    print("Even")
else:
    print("Odd")

Chained Conditionals (if...elif...else)

Used when there are more than two possibilities. Only the first branch with a True condition executes.

PYTHON
if x < y:
    print("x is less than y")
elif x > y:
    print("x is greater than y")
else:
    print("x and y are equal")


6. Nested Conditionals

A conditional statement can be nested inside another conditional statement. This is often used to check specific sub-conditions.

Structure

Indentation is critical to define the hierarchy of the conditions.

PYTHON
x = 10
y = 5

if x == y:
    print("Equal")
else:
    if x < y:
        print("Less")
    else:
        print("Greater")

Note: Deeply nested conditionals can become hard to read. Logical operators (and) can often simplify nested if structures.


7. While Statements (Indefinite Iteration)

A while loop repeatedly executes a block of code as long as a specific condition remains True. It is called "indefinite" because the number of iterations isn't necessarily known before the loop starts.

Syntax

PYTHON
while condition:
    # Body of the loop
    # Must modify variables to eventually make condition False

Components of a Loop

  1. Initialization: Setting loop control variables before the loop.
  2. Condition: Checked before every iteration.
  3. Update: Modifying the control variable inside the loop to prevent infinite loops.

Infinite Loops

If the condition never becomes False, the loop runs forever (or until memory runs out/interrupted).

PYTHON
n = 5
while n > 0:
    print(n)
    n = n - 1  # Decrement variable
print("Blastoff!")

Break and Continue

  • break: Terminates the loop immediately.
  • continue: Skips the rest of the current iteration and jumps back to the condition check.

8. For Loop Statement (Definite Iteration)

A for loop iterates over a specific sequence of items (like a list, string, or range). It is "definite" because the number of iterations is determined by the length of the sequence.

Syntax

PYTHON
for variable in sequence:
    # statement

The range() Function

Commonly used with for loops to generate a sequence of numbers.

  • range(stop): 0 to stop-1.
  • range(start, stop): start to stop-1.
  • range(start, stop, step): start to stop-1, incrementing by step.

PYTHON
# Prints 0, 2, 4
for i in range(0, 6, 2):
    print(i)


9. Nested For Loops

A loop inside another loop. For every single iteration of the outer loop, the inner loop runs to completion.

Complexity

If the outer loop runs times and the inner loop runs times, the total executions are .

Example: Grid or Matrix Traversal

PYTHON
# Generates coordinates (0,0), (0,1), (1,0), (1,1)
for x in range(2):         # Outer loop
    for y in range(2):     # Inner loop
        print(f"({x}, {y})")


10. Nested While Loops

Similar logic to nested for loops, but using while structures. These are more complex to manage because the reset logic for the inner loop variable must be handled explicitly.

Example

PYTHON
i = 1
while i <= 3:
    j = 1
    while j <= 3:
        print(i * j, end=" ")
        j += 1
    print() # Newline
    i += 1


11. Random Numbers in Loops

Combining loops and random numbers allows for simulations, such as Monte Carlo methods or game loops.

Example: Guessing Game

A classic use of while loops with random numbers.

PYTHON
import random

target = random.randint(1, 10)
guess = 0

while guess != target:
    guess = int(input("Guess a number: "))
    if guess < target:
        print("Too low")
    elif guess > target:
        print("Too high")

print("Correct!")

Example: Random Walk

Simulating a process that proceeds in random steps.

PYTHON
position = 0
steps = 10
for i in range(steps):
    step = random.choice([-1, 1]) # Move left or right
    position += step


12. Encapsulation and Generalization

These are fundamental software engineering principles, often introduced alongside loops to write cleaner, reusable code.

Encapsulation

Definition: Wrapping a piece of code (like a loop or logic block) into a function.
Benefits:

  • Isolates the logic.
  • Makes the main program cleaner.
  • Allows you to name a process (e.g., draw_square()).

Code before Encapsulation:

PYTHON
for i in range(4):
    t.forward(100)
    t.left(90)

Code after Encapsulation:

PYTHON
def draw_square():
    for i in range(4):
        t.forward(100)
        t.left(90)

draw_square()

Generalization

Definition: Taking an encapsulated piece of code and making it versatile by replacing specific values (literals like 100 or 4) with variables (parameters).
Goal: To make the function applicable to a wider range of scenarios.

Generalizing the Square Function:

PYTHON
def draw_square(length):    # 'length' is a parameter
    for i in range(4):
        t.forward(length)   # Use parameter instead of 100
        t.left(90)

draw_square(50)
draw_square(150)

Further Generalization (Polygons):

PYTHON
def polygon(n, length):
    angle = 360 / n
    for i in range(n):
        t.forward(length)
        t.left(angle)