import math def instructions(): print(""" ~~~Instructions~~~ 1. Select your shape from the list. 2. Choose what to find (perimeter/circumference or area). 3. Enter your values. 4. Read your answer! """) def float_check(question): """Runs until the user enters a positive number between 0.1 and 1e40.""" while True: try: value = float(input(question)) if value < 0.01: print("Sorry, this is too small. Please try again.") elif value > 3e8: print("Sorry, this is too large. Please try again.") else: return value except ValueError: print("Oops - please enter a number.") def string_check(question, valid_answers, num_letters): """Accepts the full word or its first num_letters characters.""" while True: response = input(question).lower().strip() for item in valid_answers: if response == item or response == item[:num_letters]: return item abbrevs = [item[:num_letters] for item in valid_answers] print(f"Please choose from {valid_answers} (or {abbrevs})") def display_results(fields: dict): """Prints a neatly aligned table of label -> value pairs.""" label_width = max(len(k) for k in fields) + 1 print() for label, value in fields.items(): print(f" {label + ':':<{label_width}} {value:.2f}") print() shape_ans = ["square", "triangle", "rectangle", "circle"] format_ans = ["perimeter", "area"] yes_no = ["yes", "no"] if string_check("Would you like to see the instructions? ", yes_no, 1) == "yes": instructions() while True: print() shape = string_check("What shape? (square, triangle, rectangle, circle) ", shape_ans, 2) # Circles have fixed set of outputs — skip perimeter/area choice if shape == "circle": radius = float_check("Radius: ") diameter = radius * 2 circumference = 2 * math.pi * radius area = math.pi * radius ** 2 display_results({ "Radius": radius, "Diameter": diameter, "Circumference": circumference, "Area": area, }) else: fmt = string_check("Perimeter or area? ", format_ans, 1) # Collect dimensions if shape == "square": side = float_check("Side length: ") base = height = side else: base = float_check("Base: ") height = float_check("Height: ") side3 = None if shape == "triangle" and fmt == "perimeter": side3 = float_check("Third side: ") # Calculate and display result if fmt == "area": if shape == "triangle": result = 0.5 * base * height else: result = base * height display_results({f"{shape.capitalize()} area": result}) else: # perimeter if shape == "square": result = base * 4 elif shape == "rectangle": result = (base + height) * 2 else: # triangle result = base + height + side3 display_results({f"{shape.capitalize()} perimeter": result}) if string_check("Calculate another shape? ", yes_no, 1) == "no": print("Goodbye!") break