0% found this document useful (0 votes)
3 views89 pages

Python Assignment 5-2

This document outlines a Python programming assignment focused on file handling, specifically creating and manipulating text files containing names. It includes code for a GUI application that allows users to create, overwrite, and preview files, as well as append names either manually or randomly. Additionally, it provides a second program to preview the first five lines of a chosen file and compute basic metrics.

Uploaded by

Joshua Kimmich
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views89 pages

Python Assignment 5-2

This document outlines a Python programming assignment focused on file handling, specifically creating and manipulating text files containing names. It includes code for a GUI application that allows users to create, overwrite, and preview files, as well as append names either manually or randomly. Additionally, it provides a second program to preview the first five lines of a chosen file and compute basic metrics.

Uploaded by

Joshua Kimmich
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

1

Python Programming
Assignment 5
Due not later than 11:59 PM on Sunday

On my honor as a student, I have neither given nor received any unauthorized aid on this
assignment/exam.
2

Program 1. Read and Write From a File


Question 1a: Code
#!/usr/bin/env python3

# Question 1a — Create two files:

# Imports

import sys # Platform-specific open/reveal


behavior

import os # Spawn OS-native open

from pathlib import Path # Cross-platform file handling

import tkinter as tk # Base Tkinter GUI toolkit

from tkinter import ttk, messagebox, simpledialog # Themed widgets

from typing import List # hints

import random # For "Append Random" name feature

# Visual theme

APP_TITLE = "Create Friends Files"

WINDOW_GEOMETRY = "860x560"

# Calm midnight palette

COL_BG = "#0b1b2b" # deep blue

COL_PANEL = "#0f2538" # panel blue

COL_TEXT = "#e6edf3" # light text

COL_MUTED = "#9fb3c8" # muted label

COL_PRIMARY = "#3fb7ff" # bright accent

COL_SECOND = "#c084fc" # violet accent

# Files & seed data

PATH_A = Path("[Link]") # must be < 5 names

PATH_B = Path("[Link]") # must be 5–7 names

SEED_A: List[str] = ["Noah", "Ada", "Mila", "Zane"] #


4 names
3

SEED_B: List[str] = ["Rowan", "Ivy", "Kai", "Serena", "Otis", "Leona"] #


6 names

# Pool for creative "Append Random" button

POOL_NAMES: List[str] = [

"Aria", "Theo", "Nova", "Jasper", "Elise", "Kian", "Mira", "Zuri",

"Felix", "Nya", "Hugo", "Ari", "Skye", "Enzo", "Lena", "Orion"

# Helper functions

# Create both files with their seed name sets

def create_or_overwrite_samples() -> None:

PATH_A.write_text("\n".join(SEED_A) + "\n", encoding="utf-8")

PATH_B.write_text("\n".join(SEED_B) + "\n", encoding="utf-8")

# Confirm both files are available

def ensure_samples_exist() -> None:

if not PATH_A.exists():

PATH_A.write_text("\n".join(SEED_A) + "\n", encoding="utf-8")

if not PATH_B.exists():

PATH_B.write_text("\n".join(SEED_B) + "\n", encoding="utf-8")

# Return the file contents as text

def read_text_or_hint(p: Path) -> str:

return p.read_text(encoding="utf-8") if [Link]() else f"{[Link]}


not found."

# Append a single name to file p

def append_single_name(p: Path, name: str) -> None:

current = p.read_text(encoding="utf-8").splitlines() if [Link]()


else []

[Link](name)

p.write_text("\n".join(current) + "\n", encoding="utf-8")

# Open the file Notepad Raises FileNotFoundError if no file

def open_with_default_app(p: Path) -> None:


4

if not [Link]():

raise FileNotFoundError(p)

if [Link]("win"):

[Link](p) # type: ignore[attr-defined]

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(p))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(p))

# Reveal the file's folder

def reveal_in_explorer(p: Path) -> None:

folder = [Link]()

if [Link]("win"):

[Link](folder)

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(folder))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(folder))

# UI components (custom)

# A [Link]

class AccentButton([Link]):

def __init__(self, master: [Link], **kwargs):

super().__init__(master, style="[Link]", **kwargs)

class Header([Link]): # Colorful section header

def __init__(self, master: [Link], text: str):

super().__init__(master, text=text, style="[Link]")

# Main window (distinct design)

# Two side panels for [Link] & [Link] with preview and
actions

class FriendsFilesApp([Link]):
5

def __init__(self) -> None:

super().__init__()

[Link](APP_TITLE)

[Link](WINDOW_GEOMETRY)

[Link](bg=COL_BG)

# ttk styles for the theme

style = [Link](self)

try:

style.theme_use("clam")

except [Link]:

pass

[Link](".", background=COL_BG, foreground=COL_TEXT)

[Link]("TFrame", background=COL_BG)

[Link]("TLabel", background=COL_BG, foreground=COL_TEXT)

[Link]("[Link]", foreground=COL_MUTED,
background=COL_BG)

[Link]("[Link]", font=("Segoe UI", 14, "bold"),

foreground=COL_PRIMARY, background=COL_BG)

[Link]("[Link]", padding=(10, 6), font=("Segoe


UI", 10, "bold"))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_PRIMARY)])

[Link]("[Link]", padding=(8, 5))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_SECOND)])

# Header text

Header(self, text="Create required friends


files").pack(anchor="w", padx=14, pady=(12, 6))
6

[Link](self, text="[Link] (<5 names) and [Link]


(5–7 names).",

style="[Link]").pack(anchor="w", padx=14,
pady=(0, 10))

# Action bar

bar = [Link](self); [Link](fill="x", padx=12, pady=(0, 10))

AccentButton(bar, text="Create / Overwrite Both",


command=self._make_both).pack(side="left")

[Link](bar, text="Create If Missing",


command=self._ensure_both, style="[Link]").pack(side="left", padx=8)

[Link](bar, text="Preview Both", command=self._preview_both,


style="[Link]").pack(side="left")

# Two panels

panels = [Link](self); [Link](fill="both", expand=True,


padx=12, pady=(0, 12))

self.left_panel = self._build_panel(panels, PATH_A, "[Link]


(must be < 5 names)")

self.right_panel = self._build_panel(panels, PATH_B,


"[Link] (must be 5–7 names)")

[Link](0, weight=1)

[Link](1, weight=1)

# Initial nudge

[Link](self, text="Tip: Click “Create / Overwrite Both”, then


Preview to verify.",

style="[Link]").pack(anchor="w", padx=14)

# panel builder

# panel for a single file with its controls and preview box.

def _build_panel(self, parent: [Link], path: Path, caption: str) -


> [Link]:

frame = [Link](parent)

col = 0 if path == PATH_A else 1

pad = (0, 10) if path == PATH_A else (10, 0)

[Link](row=0, column=col, sticky="nsew", padx=pad)


7

[Link](frame, text=caption, font=("Segoe UI", 11,


"bold")).pack(anchor="w", pady=(0, 6))

# Buttons row

row = [Link](frame); [Link](fill="x", pady=(0, 6))

[Link](row, text="Preview", command=lambda p=path:


self._preview(p), style="[Link]").pack(side="left")

[Link](row, text="Open Editor", command=lambda p=path:


self._open(p), style="[Link]").pack(side="left", padx=6)

[Link](row, text="Reveal Folder", command=lambda p=path:


self._reveal(p), style="[Link]").pack(side="left")

# Append row

add = [Link](frame); [Link](fill="x", pady=(6, 6))

[Link](add, text="Append Name…", command=lambda p=path:


self._append_manual(p)).pack(side="left")

[Link](add, text="Append Random", command=lambda p=path:


self._append_random(p)).pack(side="left", padx=6)

# Preview area

txt = [Link](frame, height=16, wrap="word", bg=COL_PANEL,


fg=COL_TEXT,

insertbackground=COL_TEXT, relief="flat")

[Link](fill="both", expand=True)

# Store reference

setattr(self, f"box_{'A' if path == PATH_A else 'B'}", txt)

return frame

# ---------- actions

# Create both files with the seed sets

def _make_both(self) -> None:

create_or_overwrite_samples()

[Link]("Created", "[Link] and [Link]


were (re)created.")

self._preview(PATH_A); self._preview(PATH_B)

# Confirm both files are present


8

def _ensure_both(self) -> None:

ensure_samples_exist()

[Link]("Ready", "Both files now exist. Existing


files were not changed.")

self._preview(PATH_A); self._preview(PATH_B)

# Load file text to preview box

def _preview(self, p: Path) -> None:

text = read_text_or_hint(p)

target = self.box_A if p == PATH_A else self.box_B

[Link]("1.0", "end")

[Link]("1.0", text)

# previews for both files

def _preview_both(self) -> None:

self._preview(PATH_A); self._preview(PATH_B)

# Prompt for a name and append

def _append_manual(self, p: Path) -> None:

name = [Link]("Append Name", f"Enter a name to


append to {[Link]}:")

if name:

append_single_name(p, [Link]())

self._preview(p)

# Append a random name from the pool

def _append_random(self, p: Path) -> None:

append_single_name(p, [Link](POOL_NAMES))

self._preview(p)

# Open file in the OS default

def _open(self, p: Path) -> None:

try:

open_with_default_app(p)

except Exception as e:
9

[Link]("Open Error", str(e))

# Reveal containing folder in the OS file explorer

def _reveal(self, p: Path) -> None:

try:

reveal_in_explorer(p)

except Exception as e:

[Link]("Reveal Error", str(e))

# Program Launcher

if __name__ == "__main__":

app = FriendsFilesApp()

[Link]()

Results

Question 1b
# Question 1b — Preview first five lines of a chosen file

# Imports

import sys
1
0
import os # Launch OS-native
open/explorer commands

from pathlib import Path # Cross-platform paths

import tkinter as tk # Tkinter GUI toolkit

from tkinter import ttk, filedialog, messagebox # Themed widgets +


dialogs

# Visual theme

APP_TITLE = "Preview First Five Lines"

WINDOW_GEOMETRY = "860x560"

COL_BG = "#0b1b2b" # deep blue

COL_PANEL = "#0f2538" # panel blue

COL_TEXT = "#e6edf3" # light text

COL_MUTED = "#9fb3c8" # muted label

COL_PRIMARY = "#3fb7ff" # bright accent

COL_SECOND = "#c084fc" # violet accent

# Offer quick choices that match Question 1a filenames

QUICK_FILES = ["[Link]", "[Link]"]

# Helper functions

def first_n_lines(p: Path, n: int = 5) -> str:

"""

Return up to the first n lines of a UTF-8 text file.

Args:

p: The file path to read.

n: Number of lines to preview (default 5; assignment requires 5).

Returns:

A string containing up to n lines joined by newlines, or a


friendly

message if the file is empty.

Raises:

FileNotFoundError: If the file does not exist.


1
1
UnicodeDecodeError: If the file is not UTF-8 decodable.

"""

if not [Link]():

raise FileNotFoundError(f"File not found: {p}")

lines = p.read_text(encoding="utf-8").splitlines()

if not lines:

return "(File is empty)"

return "\n".join(lines[:n])

# Compute simple metrics for a text file

# Return (line_count, char_count)

def file_metrics(p: Path) -> tuple[int, int]:

text = p.read_text(encoding="utf-8")

return (len([Link]()), len(text))

# Open the file

def open_with_default_app(p: Path) -> None:

if not [Link]():

raise FileNotFoundError(p)

if [Link]("win"):

[Link](p) # type: ignore[attr-defined]

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(p))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(p))

# Open the OS file

def reveal_in_explorer(p: Path) -> None:

folder = [Link]()

if [Link]("win"):

[Link](folder)

elif [Link] == "darwin":


1
2
[Link](os.P_NOWAIT, "open", "open", str(folder))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(folder))

# Small UI components

# colorful section header

class Header([Link]):

"""colorful section header."""

def __init__(self, master: [Link], text: str):

super().__init__(master, text=text, style="[Link]")

class AccentButton([Link]): # A [Link]

def __init__(self, master: [Link], **kwargs):

super().__init__(master, style="[Link]", **kwargs)

# Main window

class FirstFivePreviewApp([Link]):

"""

Main GUI:

• Filename entry with quick-pick dropdown and Browse…

• 'Preview First 5' button (assignment requirement)

• File metrics (line count, character count)

• Convenience actions: Open Editor, Reveal Folder, Clear

"""

def __init__(self) -> None:

super().__init__()

[Link](APP_TITLE)

[Link](WINDOW_GEOMETRY)

[Link](bg=COL_BG)

# ttk styles

style = [Link](self)

try:
1
3
style.theme_use("clam")

except [Link]:

pass

[Link](".", background=COL_BG, foreground=COL_TEXT)

[Link]("TFrame", background=COL_BG)

[Link]("TLabel", background=COL_BG, foreground=COL_TEXT)

[Link]("[Link]", foreground=COL_MUTED,
background=COL_BG)

[Link]("[Link]", font=("Segoe UI", 14, "bold"),

foreground=COL_PRIMARY, background=COL_BG)

[Link]("[Link]", padding=(10, 6), font=("Segoe


UI", 10, "bold"))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_PRIMARY)])

[Link]("[Link]", padding=(8, 5))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_SECOND)])

# Header

Header(self, text="Preview first five lines of a


file").pack(anchor="w", padx=14, pady=(12, 6))

[Link](self, text="Tip: Use the dropdown or Browse… to select


a file.",

style="[Link]").pack(anchor="w", padx=14,
pady=(0, 10))

# File selection row

select = [Link](self); [Link](fill="x", padx=12, pady=(0,


8))

[Link](select, text="File:").pack(side="left")

self.file_var = [Link](value=QUICK_FILES[0])
1
4
self.file_entry = [Link](select, textvariable=self.file_var,
width=52)

self.file_entry.pack(side="left", padx=6, fill="x", expand=True)

self.quick_combo = [Link](select, values=QUICK_FILES,


state="readonly", width=18)

self.quick_combo.set("Pick a sample…")

self.quick_combo.pack(side="left", padx=6)

self.quick_combo.bind("<<ComboboxSelected>>",
self._on_quick_pick)

[Link](select, text="Browse…", command=self._browse,


style="[Link]").pack(side="left")

# Actions row

actions = [Link](self); [Link](fill="x", padx=12,


pady=(0, 8))

AccentButton(actions, text="Preview First 5",


command=self._preview).pack(side="left")

[Link](actions, text="Open Editor",


command=self._open_editor, style="[Link]").pack(side="left", padx=6)

[Link](actions, text="Reveal Folder", command=self._reveal,


style="[Link]").pack(side="left")

[Link](actions, text="Clear", command=self._clear,


style="[Link]").pack(side="left", padx=6)

# Metrics panel

metrics = [Link](self); [Link](fill="x", padx=12,


pady=(0, 8))

self.lines_var = [Link](value="Lines: -")

self.chars_var = [Link](value="Characters: -")

[Link](metrics, textvariable=self.lines_var).pack(side="left",
padx=(0, 12))

[Link](metrics, textvariable=self.chars_var).pack(side="left")

# Output area

[Link] = [Link](self, height=22, wrap="word", bg=COL_PANEL,


fg=COL_TEXT,
1
5
insertbackground=COL_TEXT, relief="flat")

[Link](fill="both", expand=True, padx=12, pady=(0, 12))

# Footer note

[Link](self,

text="Assignment note: The preview shows only the first


five lines (or the entire file if <5).",

style="[Link]").pack(anchor="w", padx=14)

# Event handlers

# update the entry box

def _on_quick_pick(self, _event=None) -> None:

choice = self.quick_combo.get()

if choice:

self.file_var.set(choice)

# Open a platform-native file dialog

def _browse(self) -> None:

path = [Link](

title="Select a text file",

filetypes=[("Text Files", "*.txt"), ("All Files", "*.*")],

if path:

self.file_var.set(path)

# Read and display up to five lines; if the file has fewer than 5
lines,

# display the entire file. Also update metrics

def _preview(self) -> None:

try:

p = Path(self.file_var.get().strip())
1
6
text = first_n_lines(p, n=5) # requirement: five-line
preview

[Link]("1.0", "end")

[Link]("1.0", text)

# Update metrics

line_count, char_count = file_metrics(p)

self.lines_var.set(f"Lines: {line_count}")

self.chars_var.set(f"Characters: {char_count}")

except FileNotFoundError as e:

[Link]("Not Found", str(e))

except UnicodeDecodeError:

[Link]("Encoding Error", "Unable to decode file


as UTF-8.")

except Exception as exc:

[Link]("Error", str(exc))

# Open the selected file

def _open_editor(self) -> None:

try:

p = Path(self.file_var.get().strip())

open_with_default_app(p)

except Exception as exc:

[Link]("Open Error", str(exc))

# Reveal the selected file's folder in the OS file explorer

def _reveal(self) -> None:

try:

p = Path(self.file_var.get().strip())

reveal_in_explorer(p)

except Exception as exc:

[Link]("Reveal Error", str(exc))

# Clear the output and reset


1
7
def _clear(self) -> None:

[Link]("1.0", "end")

self.lines_var.set("Lines: -")

self.chars_var.set("Characters: -")

# Program Launcher

if __name__ == "__main__":

app = FirstFivePreviewApp()

[Link]()

Results

Program 2. Counting Names


Question 2a
# Question 2a — Create [Link] with the required 20 names

# Imports
1
8
import sys # For platform-specific

import os # For launching OS-native

from pathlib import Path # Cross-platform filesystem


paths

import tkinter as tk # Tkinter GUI toolkit

from tkinter import ttk, messagebox # Themed widgets + standard


dialogs

from typing import List # hints

import random # "Shuffle Preview"

# Visual Theme

APP_TITLE = "Create [Link] (20 Required Names)"

WINDOW_GEOMETRY = "820x560"

COL_BG = "#0b1b2b" # deep blue background

COL_PANEL = "#0f2538" # panel background

COL_TEXT = "#e6edf3" # light text

COL_MUTED = "#9fb3c8" # muted label text

COL_PRIMARY = "#3fb7ff" # bright accent

COL_SECOND = "#c084fc" # violet accent

# File Path & Required Data

NAMES_FILE = Path("[Link]") # must be created by this program

REQUIRED_NAMES: List[str] = [

"Liam", "Emma", "Noah", "Olivia", "William", "Ava", "James",


"Isabella",

"Oliver", "Sophia", "Benjamin", "Charlotte", "Elijah", "Mia",


"Lucas",

"Amelia", "Mason", "Harper", "Logan", "Evelyn"

# Helper Functions

def write_required_names(overwrite: bool = True) -> None:

"""
1
9
Write the exact required list to [Link].

Args:

overwrite: If True, always rewrite; if False, only create when


missing.

"""

if overwrite or not NAMES_FILE.exists():

NAMES_FILE.write_text("\n".join(REQUIRED_NAMES) + "\n",
encoding="utf-8")

# Return the contents of [Link]

def read_names_text() -> str:

return NAMES_FILE.read_text(encoding="utf-8") if NAMES_FILE.exists()


else "[Link] not found."

# Open the txt file

def open_with_default_app(p: Path) -> None:

if not [Link]():

raise FileNotFoundError(p)

if [Link]("win"):

[Link](p) # type: ignore[attr-defined]

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(p))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(p))

# Reveal the containing folder

def reveal_in_explorer(p: Path) -> None:

folder = [Link]()

if [Link]("win"):

[Link](folder)

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(folder))

else:
2
0
[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(folder))

# UI Components

# header for visual hierarchy

class Header([Link]):

def __init__(self, master: [Link], text: str):

super().__init__(master, text=text, style="[Link]")

# A [Link]

class AccentButton([Link]):

def __init__(self, master: [Link], **kwargs):

super().__init__(master, style="[Link]", **kwargs)

# Main GUI Application

class NamesPadApp([Link]):

"""

Professional Tkinter app for Question 2a:

• "Write Required " — writes exactly the 20 names

• "Create If Missing" — writes only if [Link] doesn't exist.

• "Preview"

• Extras: Open Editor, Reveal Folder, Copy to Clipboard, Shuffle


Preview (display-only).

"""

def __init__(self) -> None:

super().__init__()

[Link](APP_TITLE)

[Link](WINDOW_GEOMETRY)

[Link](bg=COL_BG)

# ----- ttk styles for this theme

style = [Link](self)

try:

style.theme_use("clam")
2
1
except [Link]:

pass

[Link](".", background=COL_BG, foreground=COL_TEXT)

[Link]("TFrame", background=COL_BG)

[Link]("TLabel", background=COL_BG, foreground=COL_TEXT)

[Link]("[Link]", background=COL_BG,
foreground=COL_MUTED)

[Link]("[Link]", font=("Segoe UI", 14, "bold"),

foreground=COL_PRIMARY, background=COL_BG)

[Link]("[Link]", padding=(10, 6), font=("Segoe


UI", 10, "bold"))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_PRIMARY)])

[Link]("[Link]", padding=(8, 5))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_SECOND)])

# Header & tip

Header(self, text="Create [Link] with required


names").pack(anchor="w", padx=14, pady=(12, 6))

[Link](self, text="This tool writes exactly the 20-name list


specified in the assignment.",

style="[Link]").pack(anchor="w", padx=14,
pady=(0, 10))

# Action bar

actions = [Link](self); [Link](fill="x", padx=12,


pady=(0, 10))

AccentButton(actions, text="Write Required (Overwrite)",


command=self._write_overwrite).pack(side="left")
2
2
[Link](actions, text="Create If Missing",
command=self._create_if_missing, style="[Link]").pack(side="left",
padx=8)

[Link](actions, text="Preview", command=self._preview,


style="[Link]").pack(side="left")

# Extra utilities

utils = [Link](self); [Link](fill="x", padx=12, pady=(0,


6))

[Link](utils, text="Open Editor", command=self._open_editor,


style="[Link]").pack(side="left")

[Link](utils, text="Reveal Folder", command=self._reveal,


style="[Link]").pack(side="left", padx=6)

[Link](utils, text="Copy to Clipboard", command=self._copy,


style="[Link]").pack(side="left", padx=6)

[Link](utils, text="Shuffle Preview",


command=self._shuffle_preview, style="[Link]").pack(side="left")

# Output text area

[Link] = [Link](self, height=22, wrap="word", bg=COL_PANEL,


fg=COL_TEXT,

insertbackground=COL_TEXT, relief="flat")

[Link](fill="both", expand=True, padx=12, pady=(4, 12))

[Link](self, text="Note: 'Shuffle Preview' is for display only


— it does not change [Link].",

style="[Link]").pack(anchor="w", padx=14)

# Event Handlers

# Write the exact required list to [Link]

def _write_overwrite(self) -> None:

try:

write_required_names(overwrite=True)

[Link]("Done", "Wrote the required 20 names to


[Link].")

self._preview()
2
3
except Exception as exc:

[Link]("Error", str(exc))

# Create [Link] with the required

def _create_if_missing(self) -> None:

try:

write_required_names(overwrite=False)

[Link]("Ready", "Ensured [Link] exists with


the required names.")

self._preview()

except Exception as exc:

[Link]("Error", str(exc))

def _preview(self) -> None: # Load and show [Link]

[Link]("1.0", "end")

[Link]("1.0", read_names_text())

def _open_editor(self) -> None: # Open [Link]

try:

open_with_default_app(NAMES_FILE)

except Exception as exc:

[Link]("Open Error", str(exc))

# Reveal the folder where [Link] live

def _reveal(self) -> None:

try:

reveal_in_explorer(NAMES_FILE)

except Exception as exc:

[Link]("Reveal Error", str(exc))

def _copy(self) -> None: # Copy current preview text

try:

text = [Link]("1.0", "end").strip()

self.clipboard_clear()
2
4
self.clipboard_append(text)

[Link]("Copied", "Preview text copied to


clipboard.")

except Exception as exc:

[Link]("Copy Error", str(exc))

def _shuffle_preview(self) -> None: # Show a randomized order

shuffled = REQUIRED_NAMES[:]

[Link](shuffled)

[Link]("1.0", "end")

[Link]("1.0", "\n".join(shuffled))

# Program Launcher

if __name__ == "__main__":

app = NamesPadApp()

[Link]()

Results
2
5

Question2b
#!/usr/bin/env python3

# Question 2b — Count names in [Link]

# Imports (all commented)

import sys # Platform checks for


open/reveal

import os # Launch OS-native


open/explorer commands

from pathlib import Path # Cross-platform file paths

import tkinter as tk # Tkinter GUI toolkit

from tkinter import ttk, messagebox # Themed widgets + dialogs

# Visual theme

APP_TITLE = "Count Names in [Link]"

WINDOW_GEOMETRY = "780x520"
2
6
COL_BG = "#0b1b2b" # deep blue

COL_PANEL = "#0f2538" # panel blue

COL_TEXT = "#e6edf3" # light text

COL_MUTED = "#9fb3c8" # muted label

COL_PRIMARY = "#3fb7ff" # bright accent

COL_SECOND = "#c084fc" # violet accent

# File path

NAMES_FILE = Path("[Link]") # Created by 2a

# Core logic (exact spec)

# Count lines in a UTF-8 file using the priming-read + while approach

def count_names_priming_while(file_path: Path) -> int:

# a) Variables: counter and line sentinel

count = 0

line = '' # two single quotes = empty string (EOF sentinel)

# b) Open the file (manual open/close to mirror step e)

f = file_path.open("r", encoding="utf-8")

try:

# c) Priming read (read first line BEFORE the loop)

line = [Link]()

# d) While loop until there are no more lines

while line != '':

count += 1

line = [Link]()

finally:

# e) Close the file

[Link]()

# f) Return count so caller can display it

return count

# Helpers
2
7
# Return file contents

def read_names_text() -> str:

return NAMES_FILE.read_text(encoding="utf-8") if NAMES_FILE.exists()


else "[Link] not found. Run 2a first."

# Open the file in the system's default editor

def open_with_default_app(p: Path) -> None:

if not [Link]():

raise FileNotFoundError(p)

if [Link]("win"):

[Link](p) # type: ignore[attr-defined]

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(p))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(p))

# Reveal the file’s folder

def reveal_in_explorer(p: Path) -> None:

folder = [Link]()

if [Link]("win"):

[Link](folder) # type: ignore[attr-defined]

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(folder))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(folder))

# UI components

# header for visual hierarchy

class Header([Link]):

def __init__(self, master: [Link], text: str):

super().__init__(master, text=text, style="[Link]")

class AccentButton([Link]): # A [Link]


2
8
def __init__(self, master: [Link], **kwargs):

super().__init__(master, style="[Link]", **kwargs)

# Main GUI

class NamesCountApp([Link]):

"""

Professional GUI:

• 'Count Names' uses the priming-read + while logic

• 'Preview' shows the file

• Open Editor / Reveal Folder shortcuts

"""

def __init__(self) -> None:

super().__init__()

[Link](APP_TITLE)

[Link](WINDOW_GEOMETRY)

[Link](bg=COL_BG)

# Theme

style = [Link](self)

try:

style.theme_use("clam")

except [Link]:

pass

[Link](".", background=COL_BG, foreground=COL_TEXT)

[Link]("TFrame", background=COL_BG)

[Link]("TLabel", background=COL_BG, foreground=COL_TEXT)

[Link]("[Link]", foreground=COL_MUTED,
background=COL_BG)

[Link]("[Link]", font=("Segoe UI", 14, "bold"),

foreground=COL_PRIMARY, background=COL_BG)

[Link]("[Link]", padding=(10, 6), font=("Segoe


UI", 10, "bold"))
2
9
[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_PRIMARY)])

[Link]("[Link]", padding=(8, 5))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_SECOND)])

# Header

Header(self, text="Count names in [Link]").pack(anchor="w",


padx=14, pady=(12, 6))

[Link](self, text="Uses priming read + while loop (exact steps


a–f).",

style="[Link]").pack(anchor="w", padx=14,
pady=(0, 10))

# Action bar

actions = [Link](self); [Link](fill="x", padx=12,


pady=(0, 8))

AccentButton(actions, text="Count Names",


command=self._count).pack(side="left")

[Link](actions, text="Preview", command=self._preview,


style="[Link]").pack(side="left", padx=6)

[Link](actions, text="Open Editor",


command=self._open_editor, style="[Link]").pack(side="left")

[Link](actions, text="Reveal Folder", command=self._reveal,


style="[Link]").pack(side="left", padx=6)

# Result label

self.result_var = [Link](value="Total names: -")

[Link](self, textvariable=self.result_var, font=("Segoe UI",


11)).pack(anchor="w", padx=14, pady=(6, 6))

# Preview area

[Link](self, text="[Link] preview:").pack(anchor="w",


padx=14)
3
0
[Link] = [Link](self, height=18, wrap="word",
bg=COL_PANEL, fg=COL_TEXT,

insertbackground=COL_TEXT, relief="flat")

[Link](fill="both", expand=True, padx=12, pady=(2,


12))

[Link](self, text="Tip: Run 2a to create [Link] if it


doesn't exist.",

style="[Link]").pack(anchor="w", padx=14)

# handlers

# Count names and update the UI

def _count(self) -> None:

try:

if not NAMES_FILE.exists():

raise FileNotFoundError("[Link] not found. Please run


2a first.")

total = count_names_priming_while(NAMES_FILE)

self.result_var.set(f"Total names: {total}")

self._preview()

except Exception as exc:

[Link]("Error", str(exc))

# Show file contents

def _preview(self) -> None:

[Link]("1.0", "end")

[Link]("1.0", read_names_text())

# Open the txt file using notepad

def _open_editor(self) -> None:

try:

open_with_default_app(NAMES_FILE)

except Exception as exc:

[Link]("Open Error", str(exc))


3
1
# Reveal the file's folder

def _reveal(self) -> None:

try:

reveal_in_explorer(NAMES_FILE)

except Exception as exc:

[Link]("Reveal Error", str(exc))

# Program Launcher

if __name__ == "__main__":

app = NamesCountApp()

[Link]()

Results

Question 3. Getting a Total


Question 3a
3
2
#!/usr/bin/env python3

# Question 3a — Create [Link]

# Imports

import sys # Platform checks for


open/reveal actions

import os # Launch OS-native

from pathlib import Path # Cross-platform file paths

import tkinter as tk # Base Tkinter GUI toolkit

from tkinter import ttk, messagebox # Themed widgets and dialogs

from typing import List # hints

# Visual Theme

APP_TITLE = "Create [Link] (Required Integers)"

WINDOW_GEOMETRY = "740x500"

COL_BG = "#0b1b2b" # deep blue

COL_PANEL = "#0f2538" # panel blue

COL_TEXT = "#e6edf3" # light text

COL_MUTED = "#9fb3c8" # muted label

COL_PRIMARY = "#3fb7ff" # bright accent

COL_SECOND = "#c084fc" # violet accent

# File Path & Required Data

NUMBERS_FILE = Path("[Link]") # File to create

REQUIRED_NUMBERS: List[int] = [75, 63, -8, -99]

# Helper Functions (each documented)

def write_required_numbers(overwrite: bool = True) -> None:

if overwrite or not NUMBERS_FILE.exists():

text = "\n".join(str(n) for n in REQUIRED_NUMBERS) + "\n"

NUMBERS_FILE.write_text(text, encoding="utf-8")

def read_numbers_text() -> str: # Return [Link]


3
3
return NUMBERS_FILE.read_text(encoding="utf-8") if
NUMBERS_FILE.exists() else "[Link] not found."

def open_with_default_app(p: Path) -> None:

"""

Open the file in the system's default editor

Else, FileNotFoundError

"""

if not [Link]():

raise FileNotFoundError(p)

if [Link]("win"):

[Link](p) # type: ignore[attr-defined]

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(p))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(p))

def reveal_in_explorer(p: Path) -> None: # Reveal file's folder

folder = [Link]()

if [Link]("win"):

[Link](folder) # type: ignore[attr-defined]

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(folder))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(folder))

# Small UI Components

# header for visual hierarchy

class Header([Link]):

def __init__(self, master: [Link], text: str):

super().__init__(master, text=text, style="[Link]")

class AccentButton([Link]): # A [Link]


3
4
def __init__(self, master: [Link], **kwargs):

super().__init__(master, style="[Link]", **kwargs)

# Main GUI Application

class NumbersPadApp([Link]):

"""

Professional Tkinter app for Question 3a:

• "Write Required (Overwrite)

• "Create If Missing"

• "Preview"

• Utilities: Open Editor, Reveal Folder, Clear.

"""

def __init__(self) -> None:

super().__init__()

[Link](APP_TITLE)

[Link](WINDOW_GEOMETRY)

[Link](bg=COL_BG)

# -ttk styles

style = [Link](self)

try:

style.theme_use("clam")

except [Link]:

pass

[Link](".", background=COL_BG, foreground=COL_TEXT)

[Link]("TFrame", background=COL_BG)

[Link]("TLabel", background=COL_BG, foreground=COL_TEXT)

[Link]("[Link]", background=COL_BG,
foreground=COL_MUTED)

[Link]("[Link]", font=("Segoe UI", 14, "bold"),

foreground=COL_PRIMARY, background=COL_BG)
3
5
[Link]("[Link]", padding=(10, 6), font=("Segoe
UI", 10, "bold"))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_PRIMARY)])

[Link]("[Link]", padding=(8, 5))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_SECOND)])

# Header & tip

Header(self, text="Create [Link] with required


integers").pack(anchor="w", padx=14, pady=(12, 6))

[Link](self, text="Writes exactly 75, 63, -8, and -99 (one per
line).",

style="[Link]").pack(anchor="w", padx=14,
pady=(0, 10))

# Action bar

actions = [Link](self); [Link](fill="x", padx=12,


pady=(0, 10))

AccentButton(actions, text="Write Required (Overwrite)",


command=self._write_overwrite).pack(side="left")

[Link](actions, text="Create If Missing",


command=self._create_if_missing, style="[Link]").pack(side="left",
padx=8)

[Link](actions, text="Preview", command=self._preview,


style="[Link]").pack(side="left")

# Utilities

utils = [Link](self); [Link](fill="x", padx=12, pady=(0,


6))

[Link](utils, text="Open Editor", command=self._open_editor,


style="[Link]").pack(side="left")

[Link](utils, text="Reveal Folder", command=self._reveal,


style="[Link]").pack(side="left", padx=6)
3
6
[Link](utils, text="Clear Preview", command=self._clear,
style="[Link]").pack(side="left", padx=6)

# Output text area

[Link] = [Link](self, height=18, wrap="word", bg=COL_PANEL,


fg=COL_TEXT,

insertbackground=COL_TEXT, relief="flat")

[Link](fill="both", expand=True, padx=12, pady=(4, 12))

[Link](self, text="Note: 3b will read this file and compute


the total.",

style="[Link]").pack(anchor="w", padx=14)

# Event Handlers

# required list to [Link]

def _write_overwrite(self) -> None:

try:

write_required_numbers(overwrite=True)

[Link]("Done", "Wrote the required integers to


[Link].")

self._preview()

except Exception as exc:

[Link]("Error", str(exc))

def _create_if_missing(self) -> None: # Create [Link]

try:

write_required_numbers(overwrite=False)

[Link]("Ready", "Ensured [Link] exists with


the required integers.")

self._preview()

except Exception as exc:

[Link]("Error", str(exc))

def _preview(self) -> None: # Load and show [Link]

[Link]("1.0", "end")
3
7
[Link]("1.0", read_numbers_text())

def _open_editor(self) -> None: # Open [Link]

try:

open_with_default_app(NUMBERS_FILE)

except Exception as exc:

[Link]("Open Error", str(exc))

def _reveal(self) -> None: # Reveal the file's folder

try:

reveal_in_explorer(NUMBERS_FILE)

except Exception as exc:

[Link]("Reveal Error", str(exc))

def _clear(self) -> None: # Clear the preview

[Link]("1.0", "end")

# Program Launcher

if __name__ == "__main__":

app = NumbersPadApp()

[Link]()

Results
3
8

Question 3b
#!/usr/bin/env python3

# Question 3b — Read [Link] and output the total

# Imports (
3
9
import sys # Platform checks for
open/reveal

import os # Launch OS-native

from pathlib import Path # Cross-platform file


handling

import tkinter as tk # Base Tkinter GUI toolkit

from tkinter import ttk, messagebox # Themed widgets + dialogs

# Visual theme

APP_TITLE = "Total of [Link] (Priming Read + FOR)"

WINDOW_GEOMETRY = "780x520"

COL_BG = "#0b1b2b" # deep blue

COL_PANEL = "#0f2538" # panel blue

COL_TEXT = "#e6edf3" # light text

COL_MUTED = "#9fb3c8" # muted label

COL_PRIMARY = "#3fb7ff" # bright accent

COL_SECOND = "#c084fc" # violet accent

# File path

NUMBERS_FILE = Path("[Link]") # Created by Question 3a

# Core logic (ex

def compute_total_priming_for(file_path: Path) -> float:

"""

Compute the total of all numeric lines in [Link] using:

- 'line' sentinel (initialized to '')

- 'number' as float

- priming read for the first row

- FOR loop for remaining rows

- explicit close at the end

Returns:

The total as a float.

"""
4
0
# a) Create 'line' and set to empty string

line: str = ''

# b) Create 'number' as float

number: float = 0.0

# c) Create 'total'

total: float = 0.0

# Open the file

f = file_path.open("r", encoding="utf-8")

try:

# d) Priming read: read the first row BEFORE the loop

line = [Link]()

# If we actually got a line, process it

if line != '':

stripped = [Link]()

if stripped != '':

number = float(stripped) # ensure float datatype

total += number

# d) FOR loop to process remaining lines

for line in f:

stripped = [Link]()

if stripped == '':

continue # skip blank lines safely (optional)

number = float(stripped) # ensure float datatype

total += number

finally:

# e) Close the file

[Link]()

# f) Return result so caller can display it

return total
4
1
# Helpers (UI convenience)

# Return [Link] contents

def read_numbers_text() -> str:

return NUMBERS_FILE.read_text(encoding="utf-8") if
NUMBERS_FILE.exists() else "[Link] not found. Run 3a first."

def open_with_default_app(p: Path) -> None: # Open file

if not [Link]():

raise FileNotFoundError(p)

if [Link]("win"):

[Link](p) # type: ignore[attr-defined]

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(p))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(p))

def reveal_in_explorer(p: Path) -> None: # Reveal file's folder

folder = [Link]()

if [Link]("win"):

[Link](folder) # type: ignore[attr-defined]

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(folder))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(folder))

# UI components

# header for visual hierarchy

class Header([Link]):

def __init__(self, master: [Link], text: str):

super().__init__(master, text=text, style="[Link]")

class AccentButton([Link]): # A [Link]

def __init__(self, master: [Link], **kwargs):


4
2
super().__init__(master, style="[Link]", **kwargs)

# Main GUI

class NumbersTotalApp([Link]):

"""

Professional GUI:

• 'Compute Total' uses priming read + FOR loop logic

• 'Preview' shows [Link]

• Shortcuts: Open Editor, Reveal Folder

"""

def __init__(self) -> None:

super().__init__()

[Link](APP_TITLE)

[Link](WINDOW_GEOMETRY)

[Link](bg=COL_BG)

# Theme

style = [Link](self)

try:

style.theme_use("clam")

except [Link]:

pass

[Link](".", background=COL_BG, foreground=COL_TEXT)

[Link]("TFrame", background=COL_BG)

[Link]("TLabel", background=COL_BG, foreground=COL_TEXT)

[Link]("[Link]", foreground=COL_MUTED,
background=COL_BG)

[Link]("[Link]", font=("Segoe UI", 14, "bold"),

foreground=COL_PRIMARY, background=COL_BG)

[Link]("[Link]", padding=(10, 6), font=("Segoe


UI", 10, "bold"))

[Link]("[Link]",
4
3
foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_PRIMARY)])

[Link]("[Link]", padding=(8, 5))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_SECOND)])

# Header

Header(self, text="Compute total of


[Link]").pack(anchor="w", padx=14, pady=(12, 6))

[Link](self, text="Uses priming read + FOR loop (steps a–f).",

style="[Link]").pack(anchor="w", padx=14,
pady=(0, 10))

# Action bar

actions = [Link](self); [Link](fill="x", padx=12,


pady=(0, 8))

AccentButton(actions, text="Compute Total",


command=self._compute).pack(side="left")

[Link](actions, text="Preview", command=self._preview,


style="[Link]").pack(side="left", padx=6)

[Link](actions, text="Open Editor",


command=self._open_editor, style="[Link]").pack(side="left")

[Link](actions, text="Reveal Folder", command=self._reveal,


style="[Link]").pack(side="left", padx=6)

# Result label

self.result_var = [Link](value="Total = -")

[Link](self, textvariable=self.result_var, font=("Segoe UI",


11)).pack(anchor="w", padx=14, pady=(6, 6))

# Preview area

[Link](self, text="[Link] preview:").pack(anchor="w",


padx=14)

[Link] = [Link](self, height=18, wrap="word",


bg=COL_PANEL, fg=COL_TEXT,

insertbackground=COL_TEXT, relief="flat")
4
4
[Link](fill="both", expand=True, padx=12, pady=(2,
12))

[Link](self, text="Tip: Run 3a to create [Link] if it


doesn't exist.",

style="[Link]").pack(anchor="w", padx=14)

# handlers

# Compute total and update the UI

def _compute(self) -> None:

try:

if not NUMBERS_FILE.exists():

raise FileNotFoundError("[Link] not found. Please


run 3a first.")

total = compute_total_priming_for(NUMBERS_FILE)

self.result_var.set(f"Total = {total}")

self._preview()

except ValueError as exc:

[Link]("Value Error", f"Non-numeric line


encountered: {exc}")

except Exception as exc:

[Link]("Error", str(exc))

def _preview(self) -> None: # Show file contents

[Link]("1.0", "end")

[Link]("1.0", read_numbers_text())

def _open_editor(self) -> None: # Open the file

try:

open_with_default_app(NUMBERS_FILE)

except Exception as exc:

[Link]("Open Error", str(exc))

def _reveal(self) -> None: # Reveal the file's folder

try:
4
5
reveal_in_explorer(NUMBERS_FILE)

except Exception as exc:

[Link]("Reveal Error", str(exc))

# Program Launcher

if __name__ == "__main__":

app = NumbersTotalApp()

[Link]()

Results

Question 4. Random Number Generator


Question 4
import random

#!/usr/bin/env python3

# Question 4 — Random Number Generator → [Link]

# Imports
4
6
import sys # Platform checks

import os # Launch OS-native

from pathlib import Path # Cross-platform file paths

import tkinter as tk # Tkinter GUI toolkit

from tkinter import ttk, messagebox # Themed widgets and


standard dialogs

# Visual Theme

APP_TITLE = "Q4a — Random Numbers to [Link]"

WINDOW_GEOMETRY = "820x540"

COL_BG = "#0b1b2b" # deep blue

COL_PANEL = "#0f2538" # panel blue

COL_TEXT = "#e6edf3" # light text

COL_MUTED = "#9fb3c8" # muted label

COL_PRIMARY = "#3fb7ff" # bright accent

COL_SECOND = "#c084fc" # violet accent

# File Path

OUT_FILE = Path("[Link]") # output text file created by this


program

# Helper Functions

def parse_count(text: str) -> int:

"""

Convert an entry string to a positive integer count.

Args:

text: Raw text from the count Entry.

Returns:

int: Positive integer.

Raises:

ValueError: If not a positive whole number.

"""

s = [Link]()
4
7
if not [Link]():

raise ValueError("Please enter a positive whole number.")

n = int(s)

if n <= 0:

raise ValueError("Count must be greater than 0.")

return n

def write_randoms_to_file(count: int) -> None: # write them to


[Link]

"""

Generate 'count' random integers in [1, 350] and write them to


[Link].

Args:

count: Number of integers to generate; must be > 0.

"""

with OUT_FILE.open("w", encoding="utf-8") as f:

for _ in range(count):

[Link](f"{[Link](1, 350)}\n") # inclusive bounds

def read_output_text() -> str: # Read

return OUT_FILE.read_text(encoding="utf-8") if OUT_FILE.exists() else


"[Link] not found."

def open_with_default_app(p: Path) -> None: # Open a file else


FileNotFoundError

if not [Link]():

raise FileNotFoundError(p)

if [Link]("win"):

[Link](p) # type: ignore[attr-defined]

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(p))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(p))


4
8
def reveal_in_explorer(p: Path) -> None: # Reveal the file's folder

folder = [Link]()

if [Link]("win"):

[Link](folder) # type: ignore[attr-defined]

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(folder))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(folder))

# GUI Components

# header with theme styling

class Header([Link]):

"""Large section header with theme styling."""

def __init__(self, master: [Link], text: str):

super().__init__(master, text=text, style="[Link]")

class AccentButton([Link]): # Button style

def __init__(self, master: [Link], **kwargs):

super().__init__(master, style="[Link]", **kwargs)

# Main GUI Application

class RandomNumbersApp([Link]):

"""

Tkinter app for Question 4a:

• Input: "How many numbers?"

• Action: Generate & Save → writes integers to [Link]

• Utilities: Preview, Open, Reveal, Clear

"""

def __init__(self) -> None:

super().__init__()

[Link](APP_TITLE)

[Link](WINDOW_GEOMETRY)
4
9
[Link](bg=COL_BG)

# ttk theme setup

style = [Link](self)

try:

style.theme_use("clam")

except [Link]:

pass

[Link](".", background=COL_BG, foreground=COL_TEXT)

[Link]("TFrame", background=COL_BG)

[Link]("TLabel", background=COL_BG, foreground=COL_TEXT)

[Link]("[Link]", background=COL_BG,
foreground=COL_MUTED)

[Link]("[Link]", font=("Segoe UI", 14, "bold"),

foreground=COL_PRIMARY, background=COL_BG)

[Link]("[Link]", padding=(10, 6), font=("Segoe


UI", 10, "bold"))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_PRIMARY)])

[Link]("[Link]", padding=(8, 5))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_SECOND)])

# Header

Header(self, text="Generate random numbers into


[Link]").pack(anchor="w", padx=14, pady=(12, 6))

[Link](self, text="Each line will be a random integer between


1 and 350.",

style="[Link]").pack(anchor="w", padx=14,
pady=(0, 8))

# Input row
5
0
row = [Link](self); [Link](fill="x", padx=12, pady=(0, 10))

[Link](row, text="How many numbers?").pack(side="left")

self.count_var = [Link](value="10") # sensible default

[Link](row, textvariable=self.count_var,
width=10).pack(side="left", padx=8)

# Actions

actions = [Link](self); [Link](fill="x", padx=12,


pady=(0, 8))

AccentButton(actions, text="Generate & Save",


command=self._generate).pack(side="left")

[Link](actions, text="Preview", command=self._preview,


style="[Link]").pack(side="left", padx=6)

[Link](actions, text="Open Editor", command=self._open,


style="[Link]").pack(side="left")

[Link](actions, text="Reveal Folder", command=self._reveal,


style="[Link]").pack(side="left", padx=6)

[Link](actions, text="Clear", command=self._clear,


style="[Link]").pack(side="left", padx=6)

# Output area

[Link] = [Link](self, height=22, wrap="word", bg=COL_PANEL,


fg=COL_TEXT,

insertbackground=COL_TEXT, relief="flat")

[Link](fill="both", expand=True, padx=12, pady=(2, 12))

[Link](self, text="Tip: After Generate & Save, click Preview


and take a screenshot for your report.",

style="[Link]").pack(anchor="w", padx=14)

# Event Handlers

# Validate count, write random numbers, and auto-preview

def _generate(self) -> None:

try:

n = parse_count(self.count_var.get())
5
1
write_randoms_to_file(n)

[Link]("Success", f"Wrote {n} numbers to


{OUT_FILE.name}.")

self._preview()

except Exception as exc:

[Link]("Error", str(exc))

def _preview(self) -> None: # Show [Link]

[Link]("1.0", "end")

[Link]("1.0", read_output_text())

def _open(self) -> None: # Open [Link]

try:

open_with_default_app(OUT_FILE)

except Exception as exc:

[Link]("Open Error", str(exc))

def _reveal(self) -> None: # Reveal the folder

try:

reveal_in_explorer(OUT_FILE)

except Exception as exc:

[Link]("Reveal Error", str(exc))

def _clear(self) -> None: #Clear the preview

[Link]("1.0", "end")

# Program Launcher

if __name__ == "__main__":

app = RandomNumbersApp()

[Link]()

Results
5
2
5
3
Question 5. Golf Scores
Question 5
#!/usr/bin/env python3

# Question 5a — Golf Scores: write records to [Link]

# Imports

import sys # Platform-specific


open/reveal behavior

import os # Launch OS-native

from pathlib import Path # Cross-platform file paths

import tkinter as tk # Base Tkinter GUI toolkit

from tkinter import ttk, messagebox # Themed widgets and dialogs

from typing import List, Tuple # hints

# Visual theme

APP_TITLE = "Q5a — Write Golf Scores to [Link]"

WINDOW_GEOMETRY = "860x560"

COL_BG = "#0b1b2b" # deep blue

COL_PANEL = "#0f2538" # panel blue

COL_TEXT = "#e6edf3" # light text

COL_MUTED = "#9fb3c8" # muted label

COL_PRIMARY = "#3fb7ff" # bright accent

COL_SECOND = "#c084fc" # violet accent

# File path & required data

GOLF_FILE = Path("[Link]")

# Required dataset (name, score) per assignment

REQUIRED_SAMPLE: List[Tuple[str, int]] = [

("John", 78),

("Paul", 82),

("George", 73),
5
4
("Ringo", 85),

("Pete", 101),

# Helper functions

# Convert a score string to int. Raises ValueError if invalid

def parse_score(text: str) -> int:

s = [Link]()

if s == "":

raise ValueError("Score cannot be empty.")

return int(s)

e_records(records: List[Tuple[str, int]]) -> None:

"""

Write records to [Link] with two lines per record:

line 1: name

line 2: score

"""

lines: List[str] = []

for name, score in records:

[Link](str(name))

[Link](str(score))

GOLF_FILE.write_text("\n".join(lines) + "\n", encoding="utf-8")

def read_golf_text() -> str: # Read entire [Link] for preview

return GOLF_FILE.read_text(encoding="utf-8") if GOLF_FILE.exists()


else "[Link] not found."

def open_with_default_app(p: Path) -> None: # Open a file

if not [Link]():

raise FileNotFoundError(p)

if [Link]("win"):

[Link](p) # type: ignore[attr-defined]


5
5
elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(p))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(p))

def reveal_in_explorer(p: Path) -> None: # eveal the file's folder

folder = [Link]()

if [Link]("win"):

[Link](folder) # type: ignore[attr-defined]

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(folder))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(folder))

# GUI components

class Header([Link]): # header for visual hierarchy

def __init__(self, master: [Link], text: str):

super().__init__(master, text=text, style="[Link]")

class AccentButton([Link]): # accent color button

def __init__(self, master: [Link], **kwargs):

super().__init__(master, style="[Link]", **kwargs)

# Main GUI

class GolfWriterApp([Link]):

"""

Tkinter GUI for Question 5a:

• Choose number of records (default 5).

• FOR loop reads (name, score) per iteration and writes to


[Link].

• Utilities: Fill Required Sample (inputs), Write Required Sample


(file),

Preview, Open, Reveal.

"""
5
6
def __init__(self) -> None:

super().__init__()

[Link](APP_TITLE)

[Link](WINDOW_GEOMETRY)

[Link](bg=COL_BG)

# ttk theme setup

style = [Link](self)

try: style.theme_use("clam")

except [Link]: pass

[Link](".", background=COL_BG, foreground=COL_TEXT)

[Link]("TFrame", background=COL_BG)

[Link]("TLabel", background=COL_BG, foreground=COL_TEXT)

[Link]("[Link]", background=COL_BG,
foreground=COL_MUTED)

[Link]("[Link]", font=("Segoe UI", 14, "bold"),

foreground=COL_PRIMARY, background=COL_BG)

[Link]("[Link]", padding=(10, 6), font=("Segoe


UI", 10, "bold"))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)], background=[("!


disabled", COL_PRIMARY)])

[Link]("[Link]", padding=(8, 5))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)], background=[("!


disabled", COL_SECOND)])

# Header

Header(self, text="Write golfer records to


[Link]").pack(anchor="w", padx=14, pady=(12, 6))

[Link](self, text="Enter name & score for each record; default


count is 5.",

style="[Link]").pack(anchor="w", padx=14,
pady=(0, 8))
5
7
# Record count + actions

top = [Link](self); [Link](fill="x", padx=12, pady=(0, 10))

[Link](top, text="Number of records:").pack(side="left")

self.count_var = [Link](value="5")

self.count_box = [Link](top, from_=1, to=20,


textvariable=self.count_var, width=6, command=self._rebuild_rows)

self.count_box.pack(side="left", padx=8)

AccentButton(top, text="Write Entered Records",


command=self._write_entered).pack(side="left")

[Link](top, text="Fill Required Sample (inputs)",


command=self._fill_required, style="[Link]").pack(side="left",
padx=6)

[Link](top, text="Write REQUIRED Sample (file)",


command=self._write_required_file, style="[Link]").pack(side="left",
padx=6)

[Link](top, text="Preview", command=self._preview,


style="[Link]").pack(side="left", padx=6)

# Open/Reveal

util = [Link](self); [Link](fill="x", padx=12, pady=(0, 8))

[Link](util, text="Open Editor", command=lambda:


open_with_default_app(GOLF_FILE), style="[Link]").pack(side="left")

[Link](util, text="Reveal Folder", command=lambda:


reveal_in_explorer(GOLF_FILE), style="[Link]").pack(side="left",
padx=6)

# Input rows

self.rows_frame = [Link](self, text="Enter Player Records


(Name + Score)")

self.rows_frame.configure(style="TFrame")

self.rows_frame.pack(fill="x", padx=12, pady=(0, 10))

[Link]: List[Tuple[[Link], [Link]]] = []

self._rebuild_rows() # build default rows

# Preview area
5
8
[Link](self, text="[Link] preview:").pack(anchor="w",
padx=14)

[Link] = [Link](self, height=16, wrap="word", bg=COL_PANEL,


fg=COL_TEXT,

insertbackground=COL_TEXT, relief="flat")

[Link](fill="both", expand=True, padx=12, pady=(2, 12))

# handlers

# Rebuild the input rows

def _rebuild_rows(self) -> None:

for child in self.rows_frame.winfo_children(): [Link]()

[Link]()

try: n = int(self.count_var.get())

except ValueError: n = 5; self.count_var.set("5")

for i in range(n):

row = [Link](self.rows_frame); [Link](fill="x", pady=4)

[Link](row, text=f"Record {i+1} —


Name:").pack(side="left")

name_var = [Link]()

[Link](row, textvariable=name_var,
width=18).pack(side="left", padx=6)

[Link](row, text="Score:").pack(side="left")

score_var = [Link]()

[Link](row, textvariable=score_var,
width=8).pack(side="left", padx=6)

[Link]((name_var, score_var))

def _fill_required(self) -> None: # Fill the first 5 input rows with
the required sample

self.count_var.set("5"); self._rebuild_rows()

for i, (name, score) in enumerate(REQUIRED_SAMPLE):

[Link][i][0].set(name)

[Link][i][1].set(str(score))
5
9
def _write_required_file(self) -> None:

write_records(REQUIRED_SAMPLE)

[Link]("Success", "Wrote required sample to


[Link].")

self._preview()

def _write_entered(self) -> None:

"""

Validate inputs and write to [Link] using a FOR loop:

FOR i in range(n): read name and score (two separate items) each
iteration.

"""

try:

n = int(self.count_var.get())

if n <= 0: raise ValueError("Number of records must be


positive.")

if len([Link]) != n:

self._rebuild_rows()

[Link]("Rebuilt", "Rows were rebuilt to


match the requested count. Please re-enter values.")

return

records: List[Tuple[str, int]] = []

# -FOR LOOP per requirement

for i in range(n):

name = [Link][i][0].get().strip()

score_str = [Link][i][1].get().strip()

if not name:

raise ValueError(f"Record {i+1}: name cannot be


empty.")

score = parse_score(score_str) # ensure integer

[Link]((name, score))

write_records(records)
6
0
[Link]("Done", f"Wrote {n} records to
[Link].")

self._preview()

except ValueError as exc:

[Link]("Input Error", str(exc))

except Exception as exc:

[Link]("Error", str(exc))

def _preview(self) -> None: # Show [Link]

[Link]("1.0", "end")

[Link]("1.0", read_golf_text())

# Program Launcher

if __name__ == "__main__":

app = GolfWriterApp()

[Link]()

Result
6
1

Question5b
#!/usr/bin/env python3

# Question 5b — Read [Link] and display the records

# Imports

import sys # For platform-specific


open/reveal behavior

import os # To launch the OS default


editor / file explorer

from pathlib import Path # Cross-platform path


handling

import tkinter as tk # Tkinter GUI toolkit

from tkinter import ttk, messagebox # Themed widgets and


standard dialogs

from typing import List, Tuple # hints

# Visual theme
6
2
APP_TITLE = "Q5b — Display Golf Scores"

WINDOW_GEOMETRY = "740x520"

COL_BG = "#0b1b2b" # deep blue background

COL_PANEL = "#0f2538" # panel background

COL_TEXT = "#e6edf3" # light text

COL_MUTED = "#9fb3c8" # muted helper text

COL_PRIMARY = "#3fb7ff" # bright accent

COL_SECOND = "#c084fc" # secondary accent

# File path

GOLF_FILE = Path("[Link]") # Written by 5a

# Core helpers (

def read_records() -> List[Tuple[str, int]]:

"""

Read (name, score) records from [Link] where each record spans 2
lines.

Returns:

List of tuples (name, score).

Raises:

FileNotFoundError: If [Link] is missing.

ValueError: If a score line cannot be parsed as an integer.

"""

if not GOLF_FILE.exists():

raise FileNotFoundError("[Link] not found. Please run 5a to


create it.")

lines = GOLF_FILE.read_text(encoding="utf-8").splitlines()

pairs: List[Tuple[str, int]] = []

# Walk the list two lines at a time: (name, score)

for i in range(0, len(lines), 2):

if i + 1 >= len(lines):

# If there's an odd trailing line, ignore it


6
3
break

name = lines[i].strip()

score = int(lines[i + 1].strip()) # ensure integer

[Link]((name, score))

return pairs

def open_with_default_app(p: Path) -> None: # Open a file

if not [Link]():

raise FileNotFoundError(p)

if [Link]("win"):

[Link](p) # type: ignore[attr-defined]

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(p))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(p))

def reveal_in_explorer(p: Path) -> None: # Reveal the file's folder

folder = [Link]()

if [Link]("win"):

[Link](folder) # type: ignore[attr-defined]

elif [Link] == "darwin":

[Link](os.P_NOWAIT, "open", "open", str(folder))

else:

[Link](os.P_NOWAIT, "xdg-open", "xdg-open", str(folder))

# UI components

# header for visual hierarchy

class Header([Link]):

"""Large section header for visual hierarchy."""

def __init__(self, master: [Link], text: str):

super().__init__(master, text=text, style="[Link]")

class AccentButton([Link]): # A [Link]


6
4
def __init__(self, master: [Link], **kwargs):

super().__init__(master, style="[Link]", **kwargs)

# Main GUI application

class GolfViewerApp([Link]):

"""

Tkinter GUI:

• 'Read & Display' loads [Link] into (name, score) pairs and
prints "Name: Score".

• Shows total records read.

• Utilities: Open Editor, Reveal Folder, Refresh view.

"""

def __init__(self) -> None:

super().__init__()

[Link](APP_TITLE)

[Link](WINDOW_GEOMETRY)

[Link](bg=COL_BG)

# Theme setup for ttk

style = [Link](self)

try:

style.theme_use("clam")

except [Link]:

pass

[Link](".", background=COL_BG, foreground=COL_TEXT)

[Link]("TFrame", background=COL_BG)

[Link]("TLabel", background=COL_BG, foreground=COL_TEXT)

[Link]("[Link]", background=COL_BG,
foreground=COL_MUTED)

[Link]("[Link]", font=("Segoe UI", 14, "bold"),

foreground=COL_PRIMARY, background=COL_BG)
6
5
[Link]("[Link]", padding=(10, 6), font=("Segoe
UI", 10, "bold"))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)], background=[("!


disabled", COL_PRIMARY)])

[Link]("[Link]", padding=(8, 5))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)], background=[("!


disabled", COL_SECOND)])

# Header & actions

header = [Link](self); [Link](fill="x", padx=12,


pady=(12, 8))

[Link](header, text="Read golfer records from [Link]",


style="[Link]").pack(anchor="w")

bar = [Link](self); [Link](fill="x", padx=12, pady=(0, 8))

AccentButton(bar, text="Read & Display",


command=self._read_display).pack(side="left")

[Link](bar, text="Refresh", command=self._read_display,


style="[Link]").pack(side="left", padx=6)

[Link](bar, text="Open Editor", command=lambda:


open_with_default_app(GOLF_FILE), style="[Link]").pack(side="left")

[Link](bar, text="Reveal Folder", command=lambda:


reveal_in_explorer(GOLF_FILE), style="[Link]").pack(side="left",
padx=6)

# Output text area

[Link] = [Link](self, height=20, wrap="word", bg=COL_PANEL,


fg=COL_TEXT,

insertbackground=COL_TEXT, relief="flat")

[Link](fill="both", expand=True, padx=12, pady=(2, 12))

# Status line

[Link] = [Link](value="Records: -")

[Link](self, textvariable=[Link]).pack(anchor="w",
padx=14)
6
6
[Link](self, text="Tip: Use 5a to create or overwrite
[Link].", style="[Link]").pack(anchor="w", padx=14, pady=6)

# handlers

# Load (name, score) pairs and print them line by line

# updates the 'Records:' status with the count

def _read_display(self) -> None:

try:

pairs = read_records()

[Link]("1.0", "end")

for name, score in pairs:

[Link]("end", f"{name}: {score}\n")

[Link](f"Records: {len(pairs)}")

except Exception as exc:

[Link]("Error", str(exc))

# Program Launcher

if __name__ == "__main__":

app = GolfViewerApp()

[Link]()

Result
6
7
6
8
Question 6. Total Sales
Question 6
#!/usr/bin/env python3

# Question 6 — Total Sales

# Imports

import tkinter as tk # Base Tkinter GUI toolkit

from tkinter import ttk, messagebox # Themed widgets and dialogs

from typing import List # Type hints for readability

# Constants

DAYS: List[str] = [

"Sunday", "Monday", "Tuesday", "Wednesday",

"Thursday", "Friday", "Saturday"

APP_TITLE = "Q6 — Weekly Total Sales"

WINDOW_GEOMETRY = "720x520"

# theme

COL_BG = "#0b1b2b" # deep blue background

COL_PANEL = "#0f2538" # panel background

COL_TEXT = "#e6edf3" # light text

COL_MUTED = "#9fb3c8" # muted helper text

COL_PRIMARY = "#3fb7ff" # bright accent

COL_SECOND = "#c084fc" # secondary accent

# Helpers

def parse_money(text: str) -> float:

"""

Convert a user-entered money-like string to float.

Raises:

ValueError for invalid input.


6
9
"""

s = [Link]().replace(",", "").lstrip("$")

if s == "": # treat blank as zero to be gentle

return 0.0

return float(s)

def fmt_money(x: float) -> str: # Format a float as USD-style currency


with thousands separators and two decimals

return f"${x:,.2f}"

# Small UI components

class Header([Link]): # header for visual

def __init__(self, master: [Link], text: str):

super().__init__(master, text=text, style="[Link]")

class AccentButton([Link]): # accent color Button

def __init__(self, master: [Link], **kwargs):

super().__init__(master, style="[Link]", **kwargs)

# Main GUI Application

class WeeklySalesApp([Link]):

"""

Tkinter GUI for Question 6:

• One entry per day (initialized to "0.0").

• 'Compute' calculates total via a loop, then average/day.

• 'Clear' resets all entries to "0.0".

• Results shown in currency format to match assignment style.

"""

def __init__(self) -> None:

super().__init__()

[Link](APP_TITLE)

[Link](WINDOW_GEOMETRY)

[Link](bg=COL_BG)
7
0
# ttk theme setup for this palette

style = [Link](self)

try:

style.theme_use("clam")

except [Link]:

pass

[Link](".", background=COL_BG, foreground=COL_TEXT)

[Link]("TFrame", background=COL_BG)

[Link]("TLabel", background=COL_BG, foreground=COL_TEXT)

[Link]("[Link]", background=COL_BG,
foreground=COL_MUTED)

[Link]("[Link]", font=("Segoe UI", 14, "bold"),

foreground=COL_PRIMARY, background=COL_BG)

[Link]("[Link]", padding=(10, 6), font=("Segoe


UI", 10, "bold"))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_PRIMARY)])

[Link]("[Link]", padding=(8, 5))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_SECOND)])

# >>> Make [Link] readable on dark theme <<<

[Link](

"[Link]",

fieldbackground=COL_PANEL, # entry box background

foreground=COL_TEXT # entry text color

# note: caret color is platform default for [Link]

[Link](
7
1
"[Link]",

fieldbackground=[("disabled", "#1f2937"), ("readonly",


COL_PANEL)],

foreground=[("disabled", COL_MUTED), ("readonly", COL_TEXT)]

# Title & hint

Header(self, text="Enter sales for each day of the


week").pack(anchor="w", padx=14, pady=(12, 6))

[Link](self, text="Tip: You can type 100, 1234.56, or even


$1,234.56",

style="[Link]").pack(anchor="w", padx=14,
pady=(0, 8))

# Inputs grid

[Link]: List[[Link]] = []

grid = [Link](self); [Link](fill="x", padx=12, pady=(0,


10))

for i, day in enumerate(DAYS):

row = [Link](grid); [Link](row=i//2, column=i%2, padx=8,


pady=6, sticky="w")

[Link](row, text=f"{day}:").pack(side="left", padx=(0, 8))

sv = [Link](value="0.0") # initialize to 0.0 as


required

# Apply the dark entry style so text is visible

[Link](row, textvariable=sv, width=12,


style="[Link]", justify="right").pack(side="left")

[Link](sv)

# Buttons

bar = [Link](self); [Link](fill="x", padx=12, pady=(0, 8))

AccentButton(bar, text="Compute",
command=[Link]).pack(side="left")

[Link](bar, text="Clear", command=self.clear_all,


style="[Link]").pack(side="left", padx=8)
7
2
[Link](bar, text="Fill Sample", command=self.fill_sample,
style="[Link]").pack(side="left")

# Results

self.total_var = [Link](value="Total sales for the week:


$0.00")

self.avg_var = [Link](value="Average sales for the week:


$0.00")

[Link](self, textvariable=self.total_var, font=("Segoe UI",


10)).pack(anchor="w", padx=14, pady=(8, 2))

[Link](self, textvariable=self.avg_var, font=("Segoe UI",


10)).pack(anchor="w", padx=14)

# Event handlers

# Use a FOR loop to accumulate the weekly total.

# Compute the average/day and display both in currency format

def compute(self) -> None:

try:

# Initialize the sales list to 0.0 before reading input


(requirement)

sales: List[float] = [0.0 for _ in DAYS]

# Read and parse each day's entry into the sales list

for i, var in enumerate([Link]):

sales[i] = parse_money([Link]())

# Use a loop to calculate the total

total = 0.0

for value in sales:

total += value

average = total / len(DAYS)

self.total_var.set(f"Total sales for the week:


{fmt_money(total)}")

self.avg_var.set(f"Average sales for the week:


{fmt_money(average)}")

except ValueError:
7
3
[Link]("Invalid input", "Please enter numeric
values .")

except Exception as exc:

[Link]("Error", str(exc))

def clear_all(self) -> None: # Reset all inputs

for v in [Link]:

[Link]("0.0")

self.total_var.set("Total sales for the week: $0.00")

self.avg_var.set("Average sales for the week: $0.00")

def fill_sample(self) -> None: # fill a small sample so you can test
quickly

sample = ["120", "85.5", "210", "0", "199.99", "340.25", "55"]

for v, s in zip([Link], sample):

[Link](s)

# Program Launcher

if __name__ == "__main__":

app = WeeklySalesApp()

[Link]()

Results
7
4

Question 7. Raining
Question 7
#!/usr/bin/env python3

# Question 7 — Raining

# Imports

import tkinter as tk # Base Tkinter GUI toolkit

from tkinter import ttk, messagebox # Themed widgets and dialogs

from typing import List # hints

# Constants / Theme

MONTHS: List[str] = [

"January", "February", "March", "April", "May", "June",

"July", "August", "September", "October", "November", "December"

APP_TITLE = "Q7 — Rainfall by Month"

WINDOW_GEOMETRY = "880x620"
7
5
# Dark palette to match your other files

COL_BG = "#0b1b2b" # deep blue background

COL_PANEL = "#0f2538" # panel background

COL_TEXT = "#e6edf3" # light text

COL_MUTED = "#9fb3c8" # muted helper text

COL_PRIMARY = "#3fb7ff" # bright accent

COL_SECOND = "#c084fc" # secondary accent

# Helpers (parsing/formatting)

def parse_inches(text: str) -> float:

"""

Convert a user-entered rainfall string to float inches.

Accepts blank as 0.0; forbids negative values.

Raises:

ValueError if the value cannot be parsed or is negative.

"""

s = [Link]()

if s == "":

return 0.0

value = float(s)

if value < 0:

raise ValueError("Rainfall cannot be negative.")

return value

def fmt_inches(x: float) -> str:# Format rainfall with 2 decimals and
'in' suffix .

return f"{x:.2f} in"

# GUI components

# header for visual hierarchy


7
6
class Header([Link]):

def __init__(self, master: [Link], text: str):

super().__init__(master, text=text, style="[Link]")

class AccentButton([Link]): # accent colorbutton

def __init__(self, master: [Link], **kwargs):

super().__init__(master, style="[Link]", **kwargs)

# Main GUI Application

class RainfallApp([Link]):

"""

Professional Tkinter app for Question 7:

• 12 entry boxes for monthly rainfall, each initialized to "0.0".

• 'Compute' builds a rainfall list initialized to 0.0, fills from


inputs,

loops to get total, computes average, and finds highest/lowest


months.

• 'Clear' resets inputs and outputs.

"""

def __init__(self) -> None:

super().__init__()

[Link](APP_TITLE)

[Link](WINDOW_GEOMETRY)

[Link](bg=COL_BG)

# ttk theme setup

style = [Link](self)

try:

style.theme_use("clam")

except [Link]:

pass

[Link](".", background=COL_BG, foreground=COL_TEXT)

[Link]("TFrame", background=COL_BG)
7
7
[Link]("TLabel", background=COL_BG, foreground=COL_TEXT)

[Link]("[Link]", background=COL_BG,
foreground=COL_MUTED)

[Link]("[Link]", font=("Segoe UI", 14, "bold"),

foreground=COL_PRIMARY, background=COL_BG)

[Link]("[Link]", padding=(10, 6), font=("Segoe


UI", 10, "bold"))

[Link]("[Link]", foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_PRIMARY)])

[Link]("[Link]", padding=(8, 5))

[Link]("[Link]", foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_SECOND)])

# Make Entry readable on dark theme

[Link](

"[Link]",

fieldbackground=COL_PANEL,

foreground=COL_TEXT,

insertcolor=COL_TEXT

# Title + hint

Header(self, text="Enter monthly rainfall (inches) — decimals


allowed").pack(anchor="w", padx=14, pady=(12, 6))

[Link](self, text="All fields start at 0.0. Negative values


are not allowed.",

style="[Link]").pack(anchor="w", padx=14,
pady=(0, 8))

# Input grid (3 columns × 4 rows)

[Link]: List[[Link]] = []

grid = [Link](self); [Link](fill="x", padx=12, pady=(0,


10))

cols = 3
7
8
for i, month in enumerate(MONTHS):

r, c = divmod(i, cols)

cell = [Link](grid)

[Link](row=r, column=c, padx=10, pady=8, sticky="w")

[Link](cell, text=f"{month}:").pack(side="left", padx=(0,


8))

sv = [Link](value="0.0") # initialize to 0.0 BEFORE


the loop per brief

[Link](cell, textvariable=sv, width=10,


style="[Link]", justify="right").pack(side="left")

[Link](sv)

# Buttons

bar = [Link](self); [Link](fill="x", padx=12, pady=(0, 8))

AccentButton(bar, text="Compute",
command=[Link]).pack(side="left")

[Link](bar, text="Clear", command=self.clear_all,


style="[Link]").pack(side="left", padx=8)

# Output area

self.total_var = [Link](value="Total rainfall for the year


is: 0.00 in")

self.avg_var = [Link](value="Average rainfall per month


is: 0.00 in")

self.high_var = [Link](value="Highest rainfall month(s):


-")

self.low_var = [Link](value="Lowest rainfall month(s):


-")

[Link](self, textvariable=self.total_var, font=("Segoe UI",


10)).pack(anchor="w", padx=14, pady=(8, 2))

[Link](self, textvariable=self.avg_var, font=("Segoe UI",


10)).pack(anchor="w", padx=14, pady=(0, 2))

[Link](self, textvariable=self.high_var, font=("Segoe UI",


10)).pack(anchor="w", padx=14, pady=(0, 2))

[Link](self, textvariable=self.low_var, font=("Segoe UI",


10)).pack(anchor="w", padx=14)
7
9

# Event handlers

def compute(self) -> None:

"""

Build a rainfall list initialized to 0.0, read values, then:

- Use a FOR loop to accumulate total,

- Compute average,

- Determine highest and lowest rainfall months (handle ties).

"""

try:

# Initialize values list to 0.0

rainfall: List[float] = [0.0 for _ in MONTHS]

# Read and validate each entry

for i, var in enumerate([Link]):

rainfall[i] = parse_inches([Link]())

# Loop to compute total (explicit loop per assignment)

total = 0.0

for v in rainfall:

total += v

average = total / len(MONTHS)

# Find highest/lowest values

highest = max(rainfall) if rainfall else 0.0

lowest = min(rainfall) if rainfall else 0.0

# Collect month names for ties

high_months = [m for m, v in zip(MONTHS, rainfall) if v ==


highest]

low_months = [m for m, v in zip(MONTHS, rainfall) if v ==


lowest]

# Update UI
8
0
self.total_var.set(f"Total rainfall for the year is:
{fmt_inches(total)}")

self.avg_var.set(f"Average rainfall per month is:


{fmt_inches(average)}")

self.high_var.set(f"Highest rainfall month(s): {',


'.join(high_months)} ({fmt_inches(highest)})")

self.low_var.set(f"Lowest rainfall month(s): {',


'.join(low_months)} ({fmt_inches(lowest)})")

except ValueError as exc:

[Link]("Input Error", str(exc))

except Exception as exc:

[Link]("Error", str(exc))

def clear_all(self) -> None: # Reset all entries

for v in [Link]:

[Link]("0.0")

self.total_var.set("Total rainfall for the year is: 0.00 in")

self.avg_var.set("Average rainfall per month is: 0.00 in")

self.high_var.set("Highest rainfall month(s): -")

self.low_var.set("Lowest rainfall month(s): -")

# Program Launcher

if __name__ == "__main__":

app = RainfallApp()

[Link]()

Results
8
1
8
2
Question 8. Analysis of numbers in a list
Question 8

Results

Question 9. List items greater than some number


Question 9
#!/usr/bin/env python3

# Question 9 — List items greater than some number

# Imports

import tkinter as tk # Base Tkinter GUI toolkit

from tkinter import ttk, messagebox # Themed widgets and dialogs

from typing import List # hints


8
3

# Visual theme

APP_TITLE = "Q9 — Numbers Greater Than n"

WINDOW_GEOMETRY = "880x520"

COL_BG = "#0b1b2b" # app background

COL_PANEL = "#0f2538" # input field background

COL_TEXT = "#e6edf3" # text color

COL_MUTED = "#9fb3c8" # helper text

COL_PRIMARY = "#3fb7ff" # primary accent

COL_SECOND = "#c084fc" # secondary accent

# Core logic

def parse_number_list(raw: str) -> List[float]:

# Replace common separators with spaces, then split

clean = [Link](",", " ").replace("\n", " ").strip()

if not clean:

return []

tokens = [t for t in [Link](" ") if t] # drop empty splits

return [float(t) for t in tokens]

def greater_than(values: List[float], n: float) -> List[float]:

"""

Return a new list containing only the items from `values` that are >
n.
8
4
This satisfies the assignment requirement: a function that accepts a
list

and a number n and displays numbers greater than n.

"""

return [x for x in values if x > n]

# GUI

class Header([Link]): # header for visual hierarchy

def __init__(self, master: [Link], text: str):

super().__init__(master, text=text, style="[Link]")

class AccentButton([Link]): # action button

def __init__(self, master: [Link], **kwargs):

super().__init__(master, style="[Link]", **kwargs)

# Main GUI Application

class GreaterThanApp([Link]):

"""

Tkinter app:

• Text box to enter a list of numbers.

• Entry to enter the threshold n.

• 'Show > n' runs the greater_than(...) function and prints


results.

• 'Clear' resets inputs and outputs.

"""

def __init__(self) -> None:

super().__init__()

[Link](APP_TITLE)

[Link](WINDOW_GEOMETRY)
8
5
[Link](bg=COL_BG)

# ---- ttk theme setup

style = [Link](self)

try:

style.theme_use("clam")

except [Link]:

pass

[Link](".", background=COL_BG, foreground=COL_TEXT)

[Link]("TFrame", background=COL_BG)

[Link]("TLabel", background=COL_BG, foreground=COL_TEXT)

[Link]("[Link]", background=COL_BG,
foreground=COL_MUTED)

[Link]("[Link]", font=("Segoe UI", 14, "bold"),

foreground=COL_PRIMARY, background=COL_BG)

[Link]("[Link]", padding=(10, 6), font=("Segoe


UI", 10, "bold"))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_PRIMARY)])

[Link]("[Link]", padding=(8, 5))

[Link]("[Link]",

foreground=[("!disabled", COL_TEXT)],

background=[("!disabled", COL_SECOND)])

[Link]("[Link]", fieldbackground=COL_PANEL,
foreground=COL_TEXT, insertcolor=COL_TEXT)

# ---- Title & helper text


8
6
Header(self, text="Enter a list of numbers and a threshold
n").pack(anchor="w", padx=14, pady=(12, 6))

[Link](

self,

text="Tip: Separate numbers with commas, spaces, or newlines.


Example: 1.5, 7, 3, 12",

style="[Link]"

).pack(anchor="w", padx=14, pady=(0, 8))

# ---- Input area

area = [Link](self); [Link](fill="x", padx=14, pady=(0, 8))

# Numbers text box

left = [Link](area); [Link](side="left", fill="both",


expand=True, padx=(0, 8))

[Link](left, text="Numbers:").pack(anchor="w")

[Link] = [Link](left, height=8, bg=COL_PANEL, fg=COL_TEXT,


insertbackground=COL_TEXT, relief="flat", wrap="word")

[Link](fill="both", expand=True, pady=(2, 0))

# Threshold n

right = [Link](area); [Link](side="left", fill="y")

[Link](right, text="n (threshold):").pack(anchor="w")

self.n_var = [Link]()

[Link](right, textvariable=self.n_var, width=16,


style="[Link]", justify="right").pack(anchor="w", pady=(2, 0))

# Options row (sort checkbox)

opts = [Link](self); [Link](fill="x", padx=14, pady=(6, 0))

self.sort_var = [Link](value=True)
8
7
[Link](opts, text="Sort result ascending",
variable=self.sort_var).pack(anchor="w")

# ---- Action buttons

bar = [Link](self); [Link](fill="x", padx=14, pady=(8, 8))

AccentButton(bar, text="Show > n",


command=[Link]).pack(side="left")

[Link](bar, text="Clear", command=self.clear_all,


style="[Link]").pack(side="left", padx=8)

# ---- Results

self.count_var = [Link](value="Count: -")

[Link] = [Link](self, height=8, bg=COL_PANEL, fg=COL_TEXT,


insertbackground=COL_TEXT, relief="flat", wrap="word")

[Link](self, textvariable=self.count_var).pack(anchor="w",
padx=14, pady=(0, 4))

[Link](fill="both", expand=True, padx=14, pady=(0, 12))

# Press Enter to evaluate

[Link]("<Return>", lambda _e: [Link]())

# Event handlers

def evaluate(self) -> None:

"""

Read the numbers and threshold n from the UI, run


greater_than(values, n),

and display the result list (optionally sorted).

"""

try:

# Parse numbers

values = parse_number_list([Link]("1.0", "end"))


8
8
if not values:

raise ValueError("Please enter at least one number in the


list.")

# Parse n

n_str = self.n_var.get().strip()

if n_str == "":

raise ValueError("Please enter a value for n


(threshold).")

n = float(n_str)

# Use the required function

filtered = greater_than(values, n)

# Optionally sort

if self.sort_var.get():

filtered = sorted(filtered)

# Display nicely

self.count_var.set(f"Count: {len(filtered)} (numbers > {n})")

[Link]("1.0", "end")

if filtered:

formatted = ", ".join(f"{x:.2f}" for x in filtered)

[Link]("1.0", formatted)

else:

[Link]("1.0", "No numbers are greater than


n.")

except ValueError as exc:

[Link]("Input Error", str(exc))

except Exception as exc:

[Link]("Error", str(exc))

def clear_all(self) -> None:

[Link]("1.0", "end")

self.n_var.set("")
8
9
self.count_var.set("Count: -")

[Link]("1.0", "end")

# Entrypoint

if __name__ == "__main__":

app = GreaterThanApp()

[Link]()

Results

You might also like