Bridging Music and Coding Part 2


Understanding Stacks and Queues through Chords and Rhythm

Introduction

In the previous post, we explored linked lists through the concept of the C Major scale. Today, we’ll dive into two more fundamental data structures: stacks and queues. These structures are like building blocks that programmers use to organize and manipulate data in specific ways, and they appear often in real-world applications.

Let’s connect these ideas with familiar music concepts: stacks relate to building chords, while queues can be likened to maintaining a rhythmic sequence. By understanding stacks and queues through these musical analogies, we can see how they can be useful in various coding scenarios.


Stacks: Building a Chord

A stack is a data structure that follows a Last-In, First-Out (LIFO) principle—like stacking objects, the last item added is the first one to be removed. Musically, think of building a chord note by note from the bottom up. You add notes on top of each other, but when it’s time to resolve or release the chord, you might play them in reverse order.

In our example, let’s build a C Major chord by pushing notes onto a stack, then releasing them one by one to see the notes in reverse order.

Python Code for Stack (Chord):

# Implementing a stack to build a chord
class ChordStack:
    def __init__(self):
        self.stack = []  # List to hold the chord notes

    def add_note_to_chord(self, note):
        self.stack.append(note)  # Add note to the top of the stack
        print(f"Added {note} to the chord stack.")

    def play_chord(self):
        while self.stack:
            note = self.stack.pop()  # Remove and play the last-added note
            print(f"Playing {note}")

Explanation:

  1. ChordStack Class: This class uses a Python list as a stack to hold notes.
  • add_note_to_chord pushes a note onto the stack, building the chord from the bottom up.
  • play_chord pops notes off the stack one by one, playing the chord in reverse order.

Example of Use:

# Creating the C Major chord stack
chord = ChordStack()
chord.add_note_to_chord("C")
chord.add_note_to_chord("E")
chord.add_note_to_chord("G")

# Playing the chord
chord.play_chord()

Output:

Added C to the chord stack.
Added E to the chord stack.
Added G to the chord stack.
Playing G
Playing E
Playing C

Here, we see the chord is built up as C, E, G but played back in reverse, G, E, C, following the LIFO principle of a stack.


Queues: Keeping a Rhythm

A queue operates on a First-In, First-Out (FIFO) principle—like a line of people where the first person to enter is the first to leave. Musically, think of a rhythm pattern or repeating beat sequence where each beat is added in a specific order and played in that same order.

In this example, we’ll use a queue to represent a 4/4 rhythm pattern, where each beat enters the queue and then exits in the order it was added.

Python Code for Queue (Rhythm Pattern):

from collections import deque

# Implementing a queue to keep a rhythm pattern
class RhythmQueue:
    def __init__(self):
        self.queue = deque()  # Deque to hold the beats

    def add_beat(self, beat):
        self.queue.append(beat)  # Add beat to the end of the queue
        print(f"Added beat: {beat}")

    def play_rhythm(self):
        while self.queue:
            beat = self.queue.popleft()  # Remove and play the first-added beat
            print(f"Playing beat: {beat}")

Explanation:

  1. RhythmQueue Class: This class uses a deque (double-ended queue) to hold beats.
  • add_beat adds each beat to the end of the queue, forming the rhythm in order.
  • play_rhythm removes each beat from the front, playing the rhythm in the order it was added.

Example of Use:

# Creating a 4/4 rhythm pattern queue
rhythm = RhythmQueue()
rhythm.add_beat("1")
rhythm.add_beat("2")
rhythm.add_beat("3")
rhythm.add_beat("4")

# Playing the rhythm pattern
rhythm.play_rhythm()

Output:

Added beat: 1
Added beat: 2
Added beat: 3
Added beat: 4
Playing beat: 1
Playing beat: 2
Playing beat: 3
Playing beat: 4

Each beat is played in the exact order it was added, just like following a rhythm in a song.


Final Thoughts

Stacks and queues offer two unique ways of organizing data. Stacks, like chords, allow us to “push” items onto the stack and “pop” them in reverse order. Queues, like rhythm patterns, let us maintain an orderly sequence and play each element in the same order it was added.

In the next post, we’ll look at Trees and see how they can represent harmonic structures or musical hierarchies. Until then, try experimenting with these concepts and think about other ways music and coding can intersect!


Questions for Reflection and Practice

  1. How might you modify the ChordStack to allow for playing the chord in the same order it was built?
  2. Can you think of other musical sequences that could be represented with a queue?
  3. In what situations would a stack be more useful than a queue for organizing musical elements?
  4. How could you adjust the RhythmQueue to allow looping back to the start of the rhythm once it reaches the end?

Published by Lydia Bandy

Harpist, Pianist, Award Winning Music Teacher, and Software Engineer🎼👨‍💻 Bridging music and technology with 25 years experience as a harpist, pianist, and award-winning instructor! Having 3-4 years as a software engineer and web developer, my goal is to teach coding and music theory to the world🌎🎵 Facebook/Instagram/YouTube: @LydiasPianoStudio

Leave a comment