Programming, problem solving, and algorithms

CPSC 203, 2025 W2

January 21, 2026

Announcements

The Bracelet

A bracelet contains a list of beads and has a radius.

This is composition: a Bracelet contains Beads.

Creating a Bracelet

# First, create some beads
b1 = Bead(radius=5.0, colour=(255, 0, 0))
b2 = Bead(radius=3.0, colour=(0, 255, 0))
b3 = Bead(radius=4.0, colour=(0, 0, 255))

# Then, create a bracelet with those beads
my_bracelet = Bracelet(radius=20.0, beads=[b1, b2, b3])

# Access the beads
print(len(my_bracelet.beads))           # 3
print(my_bracelet.beads[0].radius)      # 5.0
print(my_bracelet.beads[1].colour)      # (0, 255, 0)

Does it fit?

The beads fit on the bracelet if the sum of their diameters is less than or equal to the circumference.

import math

@dataclass
class Bracelet:
    radius: float
    beads: list[Bead]

    def circumference(self) -> float:
        return 2 * math.pi * self.radius

    def fits(self) -> bool:
        total = 0
        for bead in self.beads:
            total += bead.diameter()
        return total <= self.circumference()

Your turn: Does it fit?

b1 = Bead(radius=5.0, colour=(255, 0, 0))
b2 = Bead(radius=3.0, colour=(0, 255, 0))
b3 = Bead(radius=4.0, colour=(0, 0, 255))

bracelet1 = Bracelet(radius=20.0, beads=[b1, b2, b3])
bracelet2 = Bracelet(radius=3.0, beads=[b1, b2, b3])

What do bracelet1.fits() and bracelet2.fits() return?

02:00

How much slack?

@dataclass
class Bracelet:
    radius: float
    beads: list[Bead]

    def circumference(self) -> float:
        return 2 * math.pi * self.radius

    def fits(self) -> bool:
        total = 0
        for bead in self.beads:
            total += bead.diameter()
        return total <= self.circumference()

    def slack(self) -> float:
        total = 0
        for bead in self.beads:
            total += bead.diameter()
        return self.circumference() - total

Drawing the bracelet

The bracelet decides where each bead goes (around the circle).

def draw(self) -> None:
    if not self.fits():
        print("Beads don't fit!")
        return

    spacing = self.slack() / len(self.beads)
    arc_position = 0
    for bead in self.beads:
        arc_position += bead.radius + spacing / 2
        angle = arc_position / self.radius
        x = self.radius * math.cos(angle)
        y = self.radius * math.sin(angle)
        bead.draw(ax, x, y)
        arc_position += bead.radius + spacing / 2

The full picture

@dataclass
class Bead:
    radius: float
    colour: tuple[int, int, int]

    def diameter(self) -> float:
        return 2 * self.radius

    def draw(self, ax, x: float, y: float) -> None:
        # implementation uses matplotlib
        ...

@dataclass
class Bracelet:
    radius: float
    beads: list[Bead]

    def circumference(self) -> float: ...
    def fits(self) -> bool: ...
    def slack(self) -> float: ...
    def draw(self) -> None: ...

Your turn: Experiment

Try the bracelet code on PrairieLearn!

  1. Create beads of different sizes and colors
  2. Make a bracelet and check if it fits
  3. Try adding more beads until it doesn’t fit
  4. What’s the largest bead you could still add?
10:00

Design Strategies

  1. Identify the objects in your problem (nouns)

  2. List the data each object needs (attributes)

  3. List the operations each object supports (methods)

  4. Decide which object is responsible for what

  5. Implement and test incrementally

What you learned about bracelets

  • Dataclasses let us define custom types with attributes
  • Methods are functions that belong to a class
  • Composition: objects can contain other objects
  • Design: who owns what data and behavior matters!

Now let’s apply these ideas to a new domain…

Back to handcraft

A quilt in different colours—green and pink—and patterns—paisley and flowers.

A white doily with a spiral pattern on a wooden surface.

A pen made from pinecone.

A vibrant woven textile with intricate geometric patterns in various colours the main being red, displayed against a mossy wooden background.

A violin made from intricately quilled green paper with a bow.

A bicycle covered in crocheted yarn in various colours.

Where are we?

A teal knitted dishcloth with a basketweave pattern and two red knitting needles resting on it.

A 2D grid with one square extended, showing it as a smaller grid pattern that repeats across the larger grid.

Program design

A chevron knitting pattern with zigzag lines.

A knitting pattern with diagonal stripes.

A knitting pattern with diagonal stripes.

A handcraft is a collection of __________. Every __________ has a __________, and a collection of __________. Every __________ is a collection of __________. Every __________ is either “knit” or “purl,” and is drawn as a __________.

Classes in Python

Mechanism for creating user-defined types.

Used to identify attributes with an object. Associates functionality with the relevant objects.

Example:

@dataclass
class color:
  """
  color: simply gathers color components
  """
  red: int = 120
  green: int = 120
  blue: int = 120

Using a Data Class

@dataclass
class color:
  """
  color: simply gathers color components
  """
  red: int = 120
  green: int = 120
  blue: int = 120

Declaring an object of type color():


Accessing the data of an object of type color():

Design Strategies

  1. Decompose a problem into classes

  2. List the data associated with each class

  3. Write the “driver” code that illustrates the functionality you expect from each class.

  4. Implement the functions you expect.

  5. Run the driver code to test your functionality.

Which classes?

A 2D grid with one square extended, showing it as a smaller grid pattern that repeats across the larger grid.

Handcraft:

Block:

Row:

Stitch:

Image:

Let’s Write

https://us.prairielearn.com/pl/course_instance/193300/assessment/2588207