Assignment 2.5 - kleinay/arieloop2026 GitHub Wiki

Assignment 2.5 - Understanding Python Data Types

This assignment will walk you through Python’s core data types list, tuple, set, and dict not only by using them, but by experiencing the differences from Java.

Each section explains why the Pythonic version is simpler or more expressive, and then gives you a short practical task.


1. Lists - Python’s Flexible, Everyday Container

In Java, you think in terms of ArrayList<Integer> or ArrayList<String>. You must pick a type, and resizing requires internal mechanics you don't see. In Python, a list is much more fluid:

  • No type restriction. A single list can hold an int, a string, a float - Python doesn’t care. This allows rapid experimentation.
  • Negative indexing. Python lets you access elements from the end using -1, -2, etc. This becomes incredibly intuitive in practice. For example:
numbers = [10, 20, 30, 40]
print(numbers[-1])  # 40 (the last element)
print(numbers[-2])  # 30

Because lists are dynamic and ordered, negative indexing is useful when you don’t want to compute len(list) - 1.

Slicing

Slicing in Python allows you to extract parts of a list, tuple, or string using: sequence[start:end:step]

  • start → where to begin (inclusive)
  • end → where to stop (exclusive)
  • step → jump size (optional)

It feels natural because:

  • You get exactly what you mean
  • It has built-in support for negative indices
  • No loops required

Examples:

nums = [10, 20, 30, 40, 50]

print(nums[1:4])     # [20, 30, 40]  (from index 1 up to but not including 4)
print(nums[:3])      # [10, 20, 30]  (from start)
print(nums[-3:])     # [30, 40, 50]  (last 3 elements)
print(nums[::-1])    # [50, 40, 30, 20, 10] reverse list

Task 1 - Parsing and Cleaning a Messy Log Line Using Python Lists

You are writing a small tool that processes messy log lines coming from a monitoring system. Each log entry is a long string with mixed information separated by spaces. Your goal is to extract the useful parts using Python list operations.


Given Log Line

2025-11-16 17:42:10 WARNING User:moshe-m-ofer Action:PasswordAttempt Status:Failed Attempts:3 IP:192.168.1.77 Location:IL-TLV

Your Task

Using Python lists and their operations (split, slicing, negative indexing, etc.):

  1. Split the log string into a list using .split().

  2. Use negative indexing to extract the last two fields (IP and Location).

  3. Use slicing to extract the middle part of the log — everything after the timestamp and before the final two fields.

  4. Each item in the middle part has the form key:value. For each of them:

    • split on :
    • clean the value if needed (e.g., user names may contain dashes)
  5. Store all parsed fields in a list called parsed_fields as (key, value) pairs.

  6. Print a clean structured summary of the log.


Expected Output Format (example)

User = ...
Action = ...
Status = ...
Attempts = ...
IP = ...
Location = ...

2. Tuples - Lightweight Immutable Structures

In Java, immutability requires effort: final fields, no setters, private constructors… In Python, immutability is as simple as using parentheses:

point = (3, 4)

A tuple gives you:

  • A guarantee nothing will change
  • Very cheap memory footprint
  • Fast unpacking:
x, y = point

Trying to modify a tuple will immediately show you the difference:

point[0] = 10   # ❌ TypeError

Task 2 - Game Stats Function (tuple as multi-value return)

Imagine you are writing a very small game engine. For a given list of damage values that a player dealt in a level, you want to compute three things at once:

  • total damage
  • average damage per hit
  • max hit

Requirements:

  1. Implement a function: analyze_damage(hits: list[int]) -> tuple[int, float, int] that returns (total, average, maximum) as a TUPLE.
  2. Call this function with a sample list of hits.
  3. Unpack the returned tuple into three variables and print a nice report, e.g.: "Total: 310, Avg: 44.3, Max: 90"
  4. Add a comment explaining why the tuple + unpacking feels lighter in Python.

from typing import List, Tuple

def analyze_damage(hits: List[int]) -> Tuple[int, float, int]:
    # TODO: compute total, average, and max; return them as a tuple
    # example return: return total, average, maximum


def demo_damage():
    hits = [10, 45, 90, 12, 70, 83]
    # TODO: call analyze_damage and unpack result
    # TODO: print the report line
    # Comment: in Java I would probably ...


if __name__ == "__main__":
    demo_damage()

3. Sets - Simplicity for Uniqueness

If you want a unique collection in Java, you think: HashSet, constructors, perhaps even Collections.addAll. In Python:

items = {1, 2, 3}

That’s it - literal syntax. Python automatically removes duplicates:

s = {1, 1, 2, 3}
print(s)   # {1, 2, 3}

Sets are extremely fast for membership testing (in) because they’re hash-based, just like Java’s HashSet, but easier to write.

Task 3: "Unique Visitors Tracker"

You are managing a simple website and want to track unique visitors during the day. A set is perfect for this job because it automatically removes duplicates.

Your Goals

  1. Create an empty set named visitors.

  2. Add the following user IDs to it:

    101, 202, 303, 101, 404, 202

    Notice some users appear more than once - the set should handle that.

  3. Print how many unique visitors the site had.

  4. Create another set called premium_users:

    {202, 555, 777}
  5. Print:

    • All users who visited and are premium users.
    • All users who visited but are not premium users.
Hints
  • Use .add() to add items to a set.

  • Use len() to count elements.

  • Use set operations like:

    visitors & premium_users   # intersection
    visitors - premium_users   # difference

4. Dictionaries - Human-Friendly Key–Value Data

Where Java uses:

HashMap<String, Integer> map = new HashMap<>();

Python simply uses:

student = {"id": 123, "name": "Dana", "grades": [90, 95]}

Python’s literal syntax makes dictionaries natural to read, almost like JSON. You’ll be surprised how many real-world problems become trivial when you represent them with a dict.

Accessing and modifying values is direct:

print(student["name"])  # Dana
student["email"] = "[email protected]"

Task 4

Python encourages building small, flexible structures. A common pattern is a list of dictionaries, each containing sets, lists, and other dictionaries.

Example:

products = [
    {"name": "Tea", "price": 12.5, "tags": {"drink", "hot"}},
    {"name": "Apple", "price": 3.0, "tags": {"fruit", "food"}},
]

This structure takes one line of code, whereas in Java it would require classes, constructors, and getters. Write a function that receives this list and returns all products that contain a given tag, and test it.

# def get_products_with_tag(products, tag):
#     ...

Submission Requirements

Submit a single .py file containing:

  • All tasks fully implemented
  • Short explanations (as Python comments) next to your code

Write clean, simple, Python code.

⚠️ **GitHub.com Fallback** ⚠️