{ "cells": [ { "cell_type": "markdown", "id": "1e3007e1", "metadata": {}, "source": [ "# Lesson 05 activity solution\n", "\n", "In this activity, you'll solve four problems that build on what you've learned about conditional statements and loops in Lesson 05. These problems will require you to **think creatively**, **combine concepts**, and **explore** different approaches to solving problems with loops and conditionals.\n", "\n", "## Instructions:\n", "- Each problem has a clear objective\n", "- You may need to research, experiment, or combine multiple concepts\n", "- Test your solutions in the code cells provided\n", "- There are multiple ways to solve each problem - be creative!" ] }, { "cell_type": "markdown", "id": "c0839fd4", "metadata": {}, "source": [ "---\n", "## Problem 1: The password checker\n", "\n", "**Objective:** Check whether a list of passwords meets security criteria using loops and conditionals.\n", "\n", "**Given:**\n", "```python\n", "passwords = ['Pass123', 'password123', 'PASSWORD123', 'Password', 'Password123']\n", "```\n", "\n", "**Your Task:**\n", "Write code that loops through each password and checks if it meets these rules:\n", "- At least 8 characters long\n", "- Contains at least one uppercase letter\n", "- Contains at least one lowercase letter\n", "- Contains at least one digit (0-9)\n", "\n", "For each password, print a message for each rule that is not met. If all rules are met, print `'Password is valid!'`.\n", "\n", "**Expected output (first two passwords):**\n", "```\n", "Checking: Pass123\n", " Password must be at least 8 characters long\n", "\n", "Checking: password123\n", " Password must contain at least one uppercase letter\n", "```\n", "\n", "**Hints:**\n", "- Use a `for` loop to iterate over each character in the password\n", "- Use boolean flags like `has_upper`, `has_lower`, `has_digit` to track which criteria are met\n", "- Use string methods like `.isupper()`, `.islower()`, `.isdigit()`\n", "- Reset your flags at the start of each password check" ] }, { "cell_type": "code", "execution_count": 1, "id": "f0896a9f", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Checking: Pass123\n", " Password must be at least 8 characters long\n", "\n", "Checking: password123\n", " Password must contain at least one uppercase letter\n", "\n", "Checking: PASSWORD123\n", " Password must contain at least one lowercase letter\n", "\n", "Checking: Password\n", " Password must contain at least one digit\n", "\n", "Checking: Password123\n", " Password is valid!\n" ] } ], "source": [ "# Problem 1: Your solution here\n", "\n", "passwords = ['Pass123', 'password123', 'PASSWORD123', 'Password', 'Password123']\n", "\n", "for password in passwords:\n", " print(f'\\nChecking: {password}')\n", "\n", " # Reset flags for each password\n", " has_upper = False\n", " has_lower = False\n", " has_digit = False\n", "\n", " # Loop through each character to check requirements\n", " for char in password:\n", "\n", " if char.isupper():\n", " has_upper = True\n", "\n", " if char.islower():\n", " has_lower = True\n", "\n", " if char.isdigit():\n", " has_digit = True\n", "\n", " # Check each criterion and print messages\n", " is_valid = True\n", "\n", " if len(password) < 8:\n", " print(' Password must be at least 8 characters long')\n", " is_valid = False\n", "\n", " if not has_upper:\n", " print(' Password must contain at least one uppercase letter')\n", " is_valid = False\n", "\n", " if not has_lower:\n", " print(' Password must contain at least one lowercase letter')\n", " is_valid = False\n", "\n", " if not has_digit:\n", " print(' Password must contain at least one digit')\n", " is_valid = False\n", "\n", " if is_valid:\n", " print(' Password is valid!')\n" ] }, { "cell_type": "markdown", "id": "7e5027de", "metadata": {}, "source": [ "---\n", "## Problem 2: The number pattern printer\n", "\n", "**Objective:** Create a triangle number pattern using nested loops.\n", "\n", "**Your Task:**\n", "Write code that prints this triangle pattern for `n = 5` rows:\n", "```\n", "1 \n", "1 2 \n", "1 2 3 \n", "1 2 3 4 \n", "1 2 3 4 5 \n", "```\n", "\n", "Then change `n` to `3` and `4` to verify the pattern scales correctly.\n", "\n", "**Hints:**\n", "- Use nested loops: an outer loop for each row, and an inner loop for the numbers in each row\n", "- The outer loop runs from `1` to `n` (inclusive)\n", "- The inner loop runs from `1` to the current row number (inclusive)\n", "- Use `print(col, end=' ')` to print numbers on the same line\n", "- Use `print()` with no arguments to move to the next line after each row" ] }, { "cell_type": "code", "execution_count": 2, "id": "fa826b52", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "\n", "Triangle with 3 rows:\n", "1 \n", "1 2 \n", "1 2 3 \n", "\n", "Triangle with 4 rows:\n", "1 \n", "1 2 \n", "1 2 3 \n", "1 2 3 4 \n", "\n", "Triangle with 5 rows:\n", "1 \n", "1 2 \n", "1 2 3 \n", "1 2 3 4 \n", "1 2 3 4 5 \n" ] } ], "source": [ "# Problem 2: Your solution here\n", "\n", "for n in [3, 4, 5]:\n", " print(f'\\nTriangle with {n} rows:')\n", "\n", " # Outer loop for each row\n", " for row in range(1, n + 1):\n", "\n", " # Inner loop for each number in the row\n", " for col in range(1, row + 1):\n", " print(col, end=' ')\n", "\n", " print() # New line after each row\n" ] }, { "cell_type": "markdown", "id": "34e25af5", "metadata": {}, "source": [ "---\n", "## Problem 3: The prime number finder\n", "\n", "**Objective:** Find all prime numbers in a given range using nested loops and conditionals.\n", "\n", "**Background:**\n", "A prime number is a number greater than 1 that has no positive divisors other than 1 and itself. For example, 2, 3, 5, 7, and 11 are prime numbers.\n", "\n", "**Your Task:**\n", "Write code that finds all prime numbers between `start = 1` and `end = 20`:\n", "- Use a loop to check each number in the range\n", "- For each number, use an inner loop to test whether it has any divisors\n", "- Collect all prime numbers in a list called `primes`\n", "- Print the list and the total count\n", "\n", "**Expected output:**\n", "```\n", "Primes from 1 to 20:\n", "[2, 3, 5, 7, 11, 13, 17, 19]\n", "Found 8 prime numbers\n", "```\n", "\n", "**Hints:**\n", "- A number is prime if it is not divisible by any number from `2` to its square root\n", "- Use the modulo operator `%` to check divisibility: if `num % divisor == 0`, it is not prime\n", "- Use a boolean flag `is_prime` and set it to `False` when a divisor is found\n", "- Use `break` to stop checking once you know a number is not prime\n", "- Use `int(num ** 0.5) + 1` as the upper bound of the inner loop for efficiency" ] }, { "cell_type": "code", "execution_count": 3, "id": "1f8e4c22", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Primes from 1 to 20:\n", "[2, 3, 5, 7, 11, 13, 17, 19]\n", "Found 8 prime numbers\n" ] } ], "source": [ "# Problem 3: Your solution here\n", "\n", "start = 1\n", "end = 20\n", "\n", "primes = []\n", "\n", "for num in range(start, end + 1):\n", "\n", " # Skip numbers less than 2\n", " if num < 2:\n", " continue\n", "\n", " # Assume the number is prime until proven otherwise\n", " is_prime = True\n", "\n", " # Check for divisors from 2 up to the square root of num\n", " for divisor in range(2, int(num ** 0.5) + 1):\n", "\n", " if num % divisor == 0:\n", " is_prime = False\n", " break # No need to check further\n", "\n", " if is_prime:\n", " primes.append(num)\n", "\n", "print(f'Primes from {start} to {end}:')\n", "print(primes)\n", "print(f'Found {len(primes)} prime numbers')\n" ] }, { "cell_type": "markdown", "id": "947a421a", "metadata": {}, "source": [ "---\n", "## Problem 4: Fixing buggy loops and conditionals\n", "\n", "**Objective:** Debug and fix code snippets that contain common loop and conditional errors.\n", "\n", "**Your Task:**\n", "Below are three code snippets that contain bugs. For each one:\n", "1. Identify the error\n", "2. Fix the code\n", "3. Test that it works correctly\n", "4. Add a comment explaining what was wrong\n", "\n", "Run each fixed snippet to verify it works!" ] }, { "cell_type": "markdown", "id": "513ba425", "metadata": {}, "source": [ "### Bug 1\n", "\n", "This code is supposed to print numbers from 1 to 5.\n", "\n", "**Expected output:** \n", "```\n", "1\n", "2\n", "3\n", "4\n", "5\n", "```" ] }, { "cell_type": "code", "execution_count": 4, "id": "4656b1c9", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "1\n", "2\n", "3\n", "4\n", "5\n" ] } ], "source": [ "# Bug 1: Fix the code below\n", "\n", "counter = 1\n", "\n", "while counter <= 5:\n", " print(counter)\n", " counter += 1 # This line was missing, causing an infinite loop!" ] }, { "cell_type": "markdown", "id": "37c5263e", "metadata": {}, "source": [ "### Bug 2\n", "\n", "This code should print even numbers from 2 to 10.\n", "\n", "**Expected output:**\n", "```\n", "2\n", "4\n", "6\n", "8\n", "10\n", "```" ] }, { "cell_type": "code", "execution_count": 5, "id": "a80eac78", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2\n", "4\n", "6\n", "8\n", "10\n" ] } ], "source": [ "# Bug 2: Fix the code below\n", "\n", "for i in range(2, 11, 2): # The third step argument was missing, and the end value should be 11 to include 10\n", " print(i)" ] }, { "cell_type": "markdown", "id": "f385db24", "metadata": {}, "source": [ "### Bug 3\n", "\n", "This code should classify grades scores according to:\n", "- A: 90-100\n", "- B: 80-89\n", "- C: 70-79\n", "- D: 60-69\n", "- F: below 60\n", "\n", "For `score = 85`:\n", "\n", "**Expected output:** `Score: 85, Grade: B`\n", "\n", "**Current (wrong) output:** `Score: 85, Grade: F`" ] }, { "cell_type": "code", "execution_count": 6, "id": "dc024ddc", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Score: 85, Grade: B\n" ] } ], "source": [ "# Bug 3: Fix the code below\n", "\n", "score = 85\n", "\n", "if score >= 90:\n", " grade = 'A'\n", "\n", "elif score >= 80:\n", " grade = 'B'\n", "\n", "elif score >= 70:\n", " grade = 'C'\n", "\n", "elif score >= 60:\n", " grade = 'D'\n", "\n", "else:\n", " grade = 'F'\n", "\n", "print(f'Score: {score}, Grade: {grade}')\n" ] }, { "cell_type": "markdown", "id": "0a952a4f", "metadata": {}, "source": [ "The three conditionals for B, C and D were incorrectly using `if` instead of `elif`, which causes all conditions to be checked independently, leading to incorrect grade assignment.\n", "\n", "### Alternate solution: dictionary lookup\n", "\n", "You can also use a dictionary to map score ranges to grades. Instead of a chain of conditionals, divide the score by 10 to get a key into the lookup table:" ] }, { "cell_type": "code", "execution_count": 7, "id": "114f9ecb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Score: 85, Grade: B\n" ] } ], "source": [ "grades = {10: 'A', 9: 'A', 8: 'B', 7: 'C', 6: 'D'}\n", "\n", "score = 85\n", "\n", "grade = grades.get(score // 10, 'F')\n", "print(f'Score: {score}, Grade: {grade}')\n" ] }, { "cell_type": "markdown", "id": "2194a85b", "metadata": {}, "source": [ "---\n", "## __Reflection questions__\n", "\n", "After completing the challenges, answer these questions:\n", "\n", "1. Which problem required the most nested loops? How did you keep track of the logic?\n", "2. How did you decide when to use a `for` loop vs a `while` loop?\n", "3. What was the most challenging aspect of combining loops and conditionals?\n", "4. Did you use `break` or `continue` statements? If so, where and why?\n", "5. What debugging strategies did you use when your loops weren't working as expected?" ] }, { "cell_type": "markdown", "id": "91b74fca", "metadata": {}, "source": [ "1. **Problem 3 (prime number finder)** required the most nested loops, with an outer loop to iterate through each number in the range and an inner loop to check divisibility. I kept track of the logic using clear variable names (`is_prime`, `divisor`) and comments to explain each step. The key insight: the outer loop asks \"which number are we checking?\" while the inner loop asks \"does this number have a divisor?\"\n", "\n", "2. I used **`for` loops** when I knew the exact number of iterations needed (like iterating over a range of numbers or characters in a string) and **`while` loops** when the condition was more dynamic (like in Bug 1, where the loop needed to continue until a counter reached a value). For loops are cleaner for sequences; while loops suit conditional repetition.\n", "\n", "3. The most challenging aspect was **managing the flow of multiple conditions within loops**, especially in Problem 3. I had to think carefully about when to set the `is_prime` flag and when to break out of the inner loop early for efficiency.\n", "\n", "4. Yes, I used **`break`** in Problem 3 to exit the inner loop as soon as a divisor was found; once we know a number is not prime, there is no need to keep checking. I also used **`continue`** to skip numbers less than 2. These statements made the code more efficient and easier to read.\n", "\n", "5. My debugging strategies included:\n", " - Adding print statements to see what values variables held at different points\n", " - Testing with simple inputs first (like small ranges) before trying larger ones\n", " - Breaking down complex conditions into smaller steps with intermediate variables\n", " - Reading error messages carefully to understand what Python was reporting\n", " - Running code incrementally, testing each part before moving to the next\n" ] } ], "metadata": { "kernelspec": { "display_name": ".venv", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.12.3" } }, "nbformat": 4, "nbformat_minor": 5 }