From 4582d3e71204526bc52bf1a8328bd74b10ff96cb Mon Sep 17 00:00:00 2001 From: SaifulJnU Date: Thu, 18 Jun 2026 12:46:36 +0200 Subject: [PATCH 1/5] Solve Lab 1: Smart Survey Onboarding Engine Capture user profile, cast inputs, assign clearance tier via if-elif-else, and print an f-string summary. Includes solution logic markdown. --- Lab-Exercises/Solutions/lab1_smart_survey.py | 21 +++++++++++++++ Lab-Exercises/Solutions/lab1_solution.md | 28 ++++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 Lab-Exercises/Solutions/lab1_smart_survey.py create mode 100644 Lab-Exercises/Solutions/lab1_solution.md diff --git a/Lab-Exercises/Solutions/lab1_smart_survey.py b/Lab-Exercises/Solutions/lab1_smart_survey.py new file mode 100644 index 0000000..876112c --- /dev/null +++ b/Lab-Exercises/Solutions/lab1_smart_survey.py @@ -0,0 +1,21 @@ +# Lab 1: The Smart Survey Onboarding Engine + +# 1. Capture inputs from user (Name, Age, Developer Status) +name = input("Enter your name: ") +age = int(input("Enter your age: ")) # Cast to int for numeric comparison +is_developer = input("Are you a developer? (yes/no): ").strip().lower() == "yes" + +# 2. Evaluate conditional logic to determine the clearance tier +if age < 18: + tier = "Tier 3: Guest" +elif is_developer: + tier = "Tier 1: Admin Infrastructure Access" +else: + tier = "Tier 2: Standard Executive Access" + +# 3. Print out the final profile card using an f-string +print(f"\n--- Profile Configuration Summary ---") +print(f"Name: {name}") +print(f"Age: {age}") +print(f"Developer: {'Yes' if is_developer else 'No'}") +print(f"Clearance: {tier}") diff --git a/Lab-Exercises/Solutions/lab1_solution.md b/Lab-Exercises/Solutions/lab1_solution.md new file mode 100644 index 0000000..bcb262e --- /dev/null +++ b/Lab-Exercises/Solutions/lab1_solution.md @@ -0,0 +1,28 @@ +# Lab 1 Solution Logic: The Smart Survey Onboarding Engine + +## Goal +Interview a user, capture their profile, and assign a clearance tier based on age +and developer status. + +## Step-by-step Logic + +1. **Capture inputs** — `input()` always returns a string. + - `name` stays a string. + - `age` is cast with `int()` so it can be compared numerically. + - The developer answer is normalized with `.strip().lower()` and compared to + `"yes"`, producing a clean boolean (`is_developer`). + +2. **Tier decision (`if-elif-else`)** — order matters here: + - Check `age < 18` **first**. If true, the user is a Guest regardless of + developer status. + - Only if they are 18+ do we look at `is_developer`: + - Developer → `Tier 1: Admin Infrastructure Access`. + - Not a developer → `Tier 2: Standard Executive Access`. + - Because each branch is mutually exclusive, exactly one tier is assigned. + +3. **Output** — an f-string builds a readable profile card. A nested + `{'Yes' if is_developer else 'No'}` converts the boolean back to friendly text. + +## Why this works +The age gate is evaluated before the developer check, which matches the rule that +under-18 users can never reach Tier 1, even if they are developers. From 62dd225ea68f6086a4ce913bea1c69f0dc49bf21 Mon Sep 17 00:00:00 2001 From: SaifulJnU Date: Thu, 18 Jun 2026 12:47:23 +0200 Subject: [PATCH 2/5] Solve Lab 2: Multi-Cluster IP Audit Tool Loop-count active nodes from a nested dict, compute utilization percentage, and print a formatted audit report. Includes solution logic markdown. --- Lab-Exercises/Solutions/lab2_ip_audit.py | 27 +++++++++++++++++++++++ Lab-Exercises/Solutions/lab2_solution.md | 28 ++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 Lab-Exercises/Solutions/lab2_ip_audit.py create mode 100644 Lab-Exercises/Solutions/lab2_solution.md diff --git a/Lab-Exercises/Solutions/lab2_ip_audit.py b/Lab-Exercises/Solutions/lab2_ip_audit.py new file mode 100644 index 0000000..8c13713 --- /dev/null +++ b/Lab-Exercises/Solutions/lab2_ip_audit.py @@ -0,0 +1,27 @@ +# Lab 2: The Multi-Cluster IP Audit Tool + +cluster_config = { + "cluster_name": "dhaka-prod-east", + "total_max_slots": 8, + "active_nodes": ["10.0.1.15", "10.0.1.16", "10.0.1.17", "10.0.1.18", "10.0.1.19"] +} + +def calculate_capacity(config): + # Count how many items are in the active_nodes list using a loop + active_count = 0 + for _node in config["active_nodes"]: + active_count += 1 + + total_slots = config["total_max_slots"] + + # Run the mathematical formula to find utilization percentage + utilization = (active_count / total_slots) * 100 + + # Print the status statement + print(f"--- Capacity Audit: {config['cluster_name']} ---") + print(f"Active Nodes : {active_count}") + print(f"Total Slots : {total_slots}") + print(f"Utilization : {utilization:.1f}%") + +# Execute the audit tool +calculate_capacity(cluster_config) diff --git a/Lab-Exercises/Solutions/lab2_solution.md b/Lab-Exercises/Solutions/lab2_solution.md new file mode 100644 index 0000000..b1b9e2d --- /dev/null +++ b/Lab-Exercises/Solutions/lab2_solution.md @@ -0,0 +1,28 @@ +# Lab 2 Solution Logic: The Multi-Cluster IP Audit Tool + +## Goal +Parse a nested cluster config, count the active nodes with a loop, and report +the cluster utilization percentage. + +## Step-by-step Logic + +1. **Access nested data** — `cluster_config` is a dictionary. We read values by + key: `config["active_nodes"]` (a list) and `config["total_max_slots"]` (an int). + +2. **Count with a loop** — the task explicitly asks for a `for` loop, so instead of + `len()` we iterate over `active_nodes` and increment `active_count` once per + element. The loop variable is named `_node` because we only care about the + count, not the value. + +3. **Utilization formula** + ``` + Utilization % = (Active Nodes / Total Max Slots) * 100 + ``` + With 5 active nodes and 8 slots: `(5 / 8) * 100 = 62.5%`. + +4. **Report** — an f-string prints a clean summary. `{utilization:.1f}` formats the + percentage to one decimal place so the output stays tidy. + +## Why this works +Dictionary key lookups give direct access to the structured config, and the manual +counter demonstrates loop-based aggregation that the lab is practicing. From 7640258c2ddc6efca0ccda8da8f1c9cf9c1f1fae Mon Sep 17 00:00:00 2001 From: SaifulJnU Date: Thu, 18 Jun 2026 12:48:47 +0200 Subject: [PATCH 3/5] Solve Lab 3: Deployment Budget Optimizer Compute 720-hour monthly cost in a function and return APPROVED/REJECTED against the budget cap. Includes solution logic markdown. --- .../Solutions/lab3_budget_optimizer.py | 17 ++++++++++ Lab-Exercises/Solutions/lab3_solution.md | 32 +++++++++++++++++++ 2 files changed, 49 insertions(+) create mode 100644 Lab-Exercises/Solutions/lab3_budget_optimizer.py create mode 100644 Lab-Exercises/Solutions/lab3_solution.md diff --git a/Lab-Exercises/Solutions/lab3_budget_optimizer.py b/Lab-Exercises/Solutions/lab3_budget_optimizer.py new file mode 100644 index 0000000..8b72d25 --- /dev/null +++ b/Lab-Exercises/Solutions/lab3_budget_optimizer.py @@ -0,0 +1,17 @@ +# Lab 3: The Deployment Budget Optimizer + +def estimate_deployment_cost(instance_count, hourly_rate, budget_cap): + # Calculate total monthly cost (30 days * 24 hours = 720 hours of uptime) + HOURS_PER_MONTH = 720 + total_cost = instance_count * hourly_rate * HOURS_PER_MONTH + + # Compare against the budget cap and return the appropriate message + if total_cost > budget_cap: + overage = total_cost - budget_cap + return f"REJECTED: Budget Exceeded by ${overage:.2f}!" + else: + return f"APPROVED: Total Estimated Cost is ${total_cost:.2f}." + +# Test Cases to verify your execution: +print(estimate_deployment_cost(instance_count=5, hourly_rate=0.45, budget_cap=1500.00)) +print(estimate_deployment_cost(instance_count=12, hourly_rate=0.85, budget_cap=5000.00)) diff --git a/Lab-Exercises/Solutions/lab3_solution.md b/Lab-Exercises/Solutions/lab3_solution.md new file mode 100644 index 0000000..0a9b775 --- /dev/null +++ b/Lab-Exercises/Solutions/lab3_solution.md @@ -0,0 +1,32 @@ +# Lab 3 Solution Logic: The Deployment Budget Optimizer + +## Goal +Estimate the monthly cost of a server group and approve or reject it against a +budget cap. + +## Step-by-step Logic + +1. **Function signature** — `estimate_deployment_cost(instance_count, hourly_rate, + budget_cap)` accepts the three required inputs and **returns** a string (rather + than printing), so callers can reuse the result. + +2. **Cost formula** — a standard billing month is fixed at + `30 days * 24 hours = 720 hours`: + ``` + total_cost = instance_count * hourly_rate * 720 + ``` + +3. **Budget check (`if/else`)** + - If `total_cost > budget_cap`: compute the overage (`total_cost - budget_cap`) + and return a `REJECTED` message. + - Otherwise: return an `APPROVED` message with the total cost. + +4. **Clean number injection** — `{value:.2f}` formats dollars to two decimal places. + +## Worked test cases +- `5 * 0.45 * 720 = 1620.00` vs cap `1500.00` → exceeds by `120.00` → **REJECTED**. +- `12 * 0.85 * 720 = 7344.00` vs cap `5000.00` → exceeds by `2344.00` → **REJECTED**. + +## Why this works +Pulling the 720-hour constant into a named variable keeps the formula readable, and +returning strings keeps the function pure and testable. From 58e087963217e91614a8c9916764d0b92005a4b9 Mon Sep 17 00:00:00 2001 From: SaifulJnU Date: Thu, 18 Jun 2026 12:49:13 +0200 Subject: [PATCH 4/5] Solve Lab 4: Profile Text Normalization Pipeline Loop over raw inputs, strip+lowercase each, and append to a sanitized list. Includes solution logic markdown. --- Lab-Exercises/Solutions/lab4_solution.md | 25 +++++++++++++++++++ .../Solutions/lab4_text_normalization.py | 12 +++++++++ 2 files changed, 37 insertions(+) create mode 100644 Lab-Exercises/Solutions/lab4_solution.md create mode 100644 Lab-Exercises/Solutions/lab4_text_normalization.py diff --git a/Lab-Exercises/Solutions/lab4_solution.md b/Lab-Exercises/Solutions/lab4_solution.md new file mode 100644 index 0000000..f716479 --- /dev/null +++ b/Lab-Exercises/Solutions/lab4_solution.md @@ -0,0 +1,25 @@ +# Lab 4 Solution Logic: The Profile Text Normalization Pipeline + +## Goal +Clean a list of messy survey strings into a normalized list ready for production. + +## Step-by-step Logic + +1. **Iterate** — loop over each `record` in `raw_survey_inputs`. + +2. **Chain string methods** — for every record: + - `.strip()` removes leading/trailing whitespace (the erratic outer spaces). + - `.lower()` forces consistent lowercase casing. + - Chaining (`record.strip().lower()`) applies both in one expression because each + method returns a new string. + +3. **Build a new list** — `sanitized_records.append(cleaned)` stores each result. + The original `raw_survey_inputs` is left untouched (strings are immutable, and we + never reassign into it), so we can print a before/after comparison. + +4. **Verify** — print both lists to visually confirm the transformation. + +## Note +`.strip()` only trims the *outer* whitespace; spaces inside an item (e.g. +`"alice smith"`) and characters like commas/underscores are preserved on purpose, +since those are part of the actual content. diff --git a/Lab-Exercises/Solutions/lab4_text_normalization.py b/Lab-Exercises/Solutions/lab4_text_normalization.py new file mode 100644 index 0000000..ff8f31b --- /dev/null +++ b/Lab-Exercises/Solutions/lab4_text_normalization.py @@ -0,0 +1,12 @@ +# Lab 4: The Profile Text Normalization Pipeline + +raw_survey_inputs = [" ALICE SMITH ", " dhaka, BANGLADESH ", " mLOpS_ENGineer ", " LIAM,MAYA "] +sanitized_records = [] + +# Clean each string: strip surrounding whitespace, then force lowercase +for record in raw_survey_inputs: + cleaned = record.strip().lower() + sanitized_records.append(cleaned) + +print(f"Raw Input: {raw_survey_inputs}") +print(f"Sanitized Production Input: {sanitized_records}") From 23958ffd23ea852dcdfe04463efd5014abf49bdb Mon Sep 17 00:00:00 2001 From: SaifulJnU Date: Thu, 18 Jun 2026 12:49:58 +0200 Subject: [PATCH 5/5] Solve Lab 5: System Alert Flag Evaluator Combine telemetry flags into one compound boolean (down OR overloaded-prod) and branch the verdict. Includes solution logic markdown. --- .../Solutions/lab5_alert_evaluator.py | 15 ++++++++ Lab-Exercises/Solutions/lab5_solution.md | 35 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 Lab-Exercises/Solutions/lab5_alert_evaluator.py create mode 100644 Lab-Exercises/Solutions/lab5_solution.md diff --git a/Lab-Exercises/Solutions/lab5_alert_evaluator.py b/Lab-Exercises/Solutions/lab5_alert_evaluator.py new file mode 100644 index 0000000..e59411a --- /dev/null +++ b/Lab-Exercises/Solutions/lab5_alert_evaluator.py @@ -0,0 +1,15 @@ +# Lab 5: System Alert Flag Evaluator + +# Change these values to verify different execution paths! +is_active = True +cpu_percent = 94.5 +is_production = True + +# Build the compound logical matching condition statement. +# Alert if the server is down, OR if CPU is critically high in production. +should_alert = (not is_active) or (cpu_percent > 90.0 and is_production) + +if should_alert: + print("[ALERT] Urgent dispatch! System needs manual intervention.") +else: + print("[OK] System operating within safe margin bounds.") diff --git a/Lab-Exercises/Solutions/lab5_solution.md b/Lab-Exercises/Solutions/lab5_solution.md new file mode 100644 index 0000000..9c7db39 --- /dev/null +++ b/Lab-Exercises/Solutions/lab5_solution.md @@ -0,0 +1,35 @@ +# Lab 5 Solution Logic: System Alert Flag Evaluator + +## Goal +Combine three telemetry flags into one boolean that decides whether to page an +engineer. + +## Step-by-step Logic + +The alert rule is the **OR** of two independent failure conditions: + +1. **Server down** — `not is_active`. If the server is not active, alert + immediately, no matter the CPU. + +2. **Overloaded production** — `cpu_percent > 90.0 and is_production`. High CPU is + only urgent when it happens in a production environment. Both parts must be true + (`and`). + +Combined: +```python +should_alert = (not is_active) or (cpu_percent > 90.0 and is_production) +``` + +## Operator precedence +Python evaluates `not` first, then `and`, then `or`, so the parentheses are not +strictly required — but they make the two failure conditions explicit and readable. + +## Trace of the sample values +`is_active=True`, `cpu_percent=94.5`, `is_production=True`: +- `not is_active` → `False` +- `94.5 > 90.0 and True` → `True` +- `False or True` → **`True`** → prints the `[ALERT]` line. + +## Why this works +Grouping the CPU + production check together ensures a high CPU on a non-production +box won't wake anyone up, while a downed server always will.