Advent of Code 2024: Day 1 — Historian Hysteria

This year, I’m diving into Advent of Code for the first time, and I couldn’t be more excited! As a newcomer to this coding challenge, I wasn’t sure what to expect, but Day 1 proved to be the perfect introduction. The puzzles were engaging yet approachable, providing a fantastic opportunity to flex my problem-solving muscles while building confidence in my skills.


Day 1 Puzzle: Reconciling Historians’ Notes

The scenario for Day 1 was intriguing: two mismatched lists of location IDs needed to be reconciled to help a group of Elvish Senior Historians track down their missing Chief Historian. The task was split into two parts:

  1. Calculate the total distance between the two lists by pairing the numbers from smallest to largest and summing their absolute differences.
  2. Determine a similarity score by calculating how many times each number from the first list appears in the second and summing weighted contributions.

Pseudocode for My Solutions

Here’s how I approached each part of the puzzle:

Part 1: Total Distance

1. Parse Input

Split the raw input into two separate lists of integers.

Function: parse_input(input_string)
    Initialize list1 and list2
    For each line in input_string:
        If line is not empty:
            Split the line into two numbers
            Append the first number to list1
            Append the second number to list2
    Return list1 and list2

2. Sort the Lists:

Sorting ensures that the smallest numbers from each list are paired together.

Function: sort_list(list)
    Return list sorted in ascending order

3. Compute Total Distance:

For each index, compute the absolute difference between paired numbers and sum them.

Function: calculate_total_distance(list1, list2)
    Initizialize total_distance to 0
    For i from 0 to length of list1:
        Calculate absolute difference between list1[i] and list2[i]
        Add difference to total_distance
    Return total_distance

Part 2: Similarity Score

Calculate Occurrence Similarity:

1. Count how many times each number in the first list appears in the second list and create a list.

Function: similarity_list(list1, list2)
    Initialize similarity_list as empty
    For each num1 in list1:
        Count occurrences of num1 in list 2
        Append count to similarity_list
    Return similarity_list

2. Use these counts to compute the weighted similarity score.

Function: similarity_score(list1, similarity_list)
    Initialize similarity_score to 0
    For i from 0 to length of list1:
        similarity_score += list1[i] * similarity_list{i}
    Return similarity_score

Implementing with TDD

For both parts, I used Test-Driven Development (TDD) to structure my work:

1. Write Tests First:

Before writing any functional code, I created tests for each function. For example:

  • parse_input should correctly parse the input into two lists
  • calculate_total_distance should compute the correct total for paired absolute differences
  • similarity_list should return the correct count of occurrences for each number

Example test for part 2:

def test_similarity_score():
    list1 = [1, 2, 3, 4, 5]
    list2 = [1, 2, 1, 1, 0]
    expected_similarity_score = 1 + 4 + 3 + 4 + 0
    assert similarity_score(list1, similarity_list(list1, list2)) == expected_similarity_score

2. Develop Code to Pass Tests:

Functions were implemented iteratively, ensuring each passed its corresponding tests before moving on.

3. Refactor for Clarity:

Once all tests passed, I revisited the code to clean up and optimize where possible.

4. Continuous Testing

I ran tests frequently to catch errors early and verify that new changes didn’t break existing functionality.


Lessons from Day 1

  • TDD Keeps You Focused: Writing tests first clarified my goals and made debugging easier.
  • Breaking Down Problems Helps: Writing pseudocode and taking the problem step by step reduced overwhelm.
  • Python is a Great Tool for Problem-Solving: Its readability and powerful standard library made implementation smooth.

Final Thoughts

Participating in Advent of Code for the first time has already been both challenging and rewarding. Day 1 taught me the value of a systematic approach, and I can’t wait to see what the rest of the month holds. Whether you’re a seasoned Advent of Code participant or just starting like me, I’d love to hear about your experiences!

Are you taking part in Advent of Code this year? Let me know in the comments!

Developing Procedural Terrain for Sim Firefighter

Hey everyone! I’m so excited to share what I’ve been working on for Sim Firefighter: procedurally generated terrain! As you know, this game is still in its early stages, but one of the key features I’m tackling is creating dynamic maps that feel natural and engaging. Terrain isn’t just a backdrop in Sim Firefighter — it’s a major gameplay element that impacts fire behavior and player strategy.

To make this happen, I’ve been diving into Perlin Noise, an amazing tool for generating smooth, organic patterns. The process has been challenging but so rewarding, and I’m thrilled to take you behind the scenes and show you how it all works!


What is Perlin Noise?

Perlin Noise creates smooth gradients of random values, perfect for generating terrains, clouds, or even fire spread patterns. It’s widely used in games because it avoids the harsh randomness of pure noise, resulting in more natural-looking outputs.


How I’m Using Perlin Noise in Sim Firefighter

The goal is to procedurally generate a map where each tile is assigned a terrain type — like grass, shrubs, or water — based on Perlin Noise values. Here’s how I’m building it:

1. Choosing the Right Tool

To generate Perlin Noise, I’m using the noisejs library. It’s a straightforward JavaScript implementation of Perlin Noise that supports 2D and 3D noise and allows for seeding — important for creating reproducible maps during development.

2. Generating the Noise Grid

The terrain map in Sim Firefighter is structured as a grid. Each grid cell represents a tile, and I use Perlin Noise to assign values to each cell. Lower values might represent water, mid-range values, grass, and higher values trees. Here’s a pseudocode example of how the noise grid is generated:

    Initialize PerlinNoise with width, height, scale, and seed
    For each Y coordinate in the grid:
        For each X coordinate in the grid:
            Generate Perlin noise value at position (X, Y)
            Store the noise value in the grid
    End For

    3. Mapping Noise to Terrain

    The generated Perlin Noise value range for -1 to 1. We map these values to terrain types like water, grass, and trees. Here’s how the mapping is done:

    For each value in the noise grid:
        If value < -0.5: Assign "water"
        Else if value < 0: Assign "grass"
        Else if value < 0.5: Assign "shrub"
        Else: Assign "tree"
    End For

    4. Rendering the Map

    Once the terrain is generated, the next step is to render it visually. Each tile corresponds to a terrain type, and we render the corresponding graphic for each tile.

    For each tile in the terrain grid:
        Create a sprite at (X, Y)
        Assign the terrain image based on the tile type (water, grass, etc.)
    End For

    What I’m Learning Along the Way

    1. Tuning Noise Parameters:

    The scale and noise thresholds have a huge impact on the map’s look. Fine-tuning these values is a key part of the process.

    2. Debugging with Visualization:

    Visualizing the noise grid as colors or grayscale tiles has made it easier to identify issues with the terrain generation.

    3. Reproducibility with Seeds:

    Using a seed ensures I can regenerate the same map, which has been essential for testing.


    What’s Next?

    Sim Firefighter is still in its early stages, so there’s a lot more to do. Next steps for procedural terrain include:

    • Making the tiles interactive so players can inspect and interact with different terrain types.
    • Exploring layered noise techniques to create more complex and realistic landscapes.
    • Improving the map generation performance for larger grids.

    Implementing Perlin Noise has been a rewarding challenge, and I’m excited to see how this feature evolves as the game develops further!


    Thanks for following along with this journey! And as always, here’s a cat pic for good luck:

    My bengal cat, Cider, went on an adventure to the grocery store parking lot recently and was loving watching all the activity around us.

    Mapping Out Wildfire Territory: The Art of Map Generation in Sim Firefighter

    Hey everyone! For the last few weeks, I’ve been deep into the magic of map generation for Sim Firefighter. In this post, I’m excited to take you behind the scenes of what goes into building a realistic, challenging environment where wildfire management is anything but predictable.

    To start with, map generation is essential because our game relies on dynamic terrains that influence fire behavior and player strategy. With so many unpredictable elements, like fire spreading differently across dry grass vs. dense forest, the map needs to capture real-life elements while keeping gameplay interesting and challenging.

    The first step in creating our map is procedural generation with something called Perlin noise. Think of it as a way to give the map a natural flow, so it feels continuous rather than looking like a patchwork quilt. With Perlin noise, we can create smooth transitions between terrains like forests, dry grasslands, and even water bodies that can act as natural firebreaks. For example, areas with low elevation and less moisture might turn into dry grasslands, ready to fuel fast-spreading fires, while higher, denser regions become forests that slow down the fire a bit but burn with greater intensity.

    Next up is a tool called Binary Space Partitioning (BSP), which helps divide the map into structured regions. BSP is amazing for organizing areas like roads, firebreaks, and water bodies. This not only adds variety to the map but also gives players strategic points they can use to slow down or contain fires. Imagine trying to stop a fire on one side of a lake or along a road — those natural barriers can really be a game-changer!

    To make things even more realistic, we use Cellular Automata for organic terrain generation. This is where we get those beautiful, irregular patches of forests and dry grass that look more natural than anything we could create by hand. Each cell on the gird changes based on its neighbors, so you end up with clusters that mimic real-life landscapes. When these organic areas catch fire, the flames spread in ways that feel true to life, creating intense but strategic gameplay.

    Then there’s the final layer of complexity: Dijkstra Maps for fire spread dynamics. These maps calculate the distance from fire origins to various points on the map, simulating how fires spread based on proximity to fuel sources. So, if a fire starts near a forest cluster, the game calculates its spread toward dry grasslands, keeping players on their toes as the flames change direction and intensity with each moment.

    Once all these steps come together, we finalize the map by storing each cell’s properties — from terrain type to how fast it will burn. It’s a bit like setting up a giant chessboard where every square holds different risks and advantages, making each game session unique.

    So, that’s a peek into what map generation looks like in Sim Firefighter! It’s a mix of science and art, and every layer adds something special to the gameplay. I can’t wait to see how it evolves as we start testing it out.

    And, of course, no post is complete without a cat picture. We’re switching it up a bit this time. Below is a picture of my parents’ pets: Opal (the cat) and Pacie (the dog). They are the softest, sweetest animals and I love when I get to see them!

    New Beginnings: Shifting Gears to Sim Firefighter!

    Hey everyone! If you remember my last update, I was all in with my team on the Parchment project. Well, hold onto your keyboards, because things have taken an unexpected twist! We’ve packed up our notes and ideas from Parchment and are now diving into a whole new capstone project: Sim Firefighter.

    So what’s Sim Firefighter all about? Picture this: you’re leading a team within the National Interagency Coordination Center, managing wildfire responses, strategizing fire suppression, and making some serious on-the-spot decisions about fighting fires across different terrains. It’s a massive shift from Parchment, but one I’m really excited about. This new project is packed with challenges, like figuring out realistic fire behavior and integrating techniques that real wildfire managers would us. I never thought I’d be reading up on wildfire data for a project, but here we are!

    Now, I’m working with a slightly smaller, more focused team of four, which is Kaitlyn, Aidan, Tyler, and me. Each of us has our own focus, whether it’s hosting the app, creating maps, managing player data, or developing fire-spreading mechanics. The change has brought some new energy, and it’s been incredible to see how quickly we’ve all adapted. As much as I loved the vision behind Parchment, Sim Firefighter felt like a unique chance to challenge ourselves in totally different ways.

    We’re still just getting started, but I can already feel the potential in this project. Next up, we’re diving into map generation and working on making the fire behavior as close to real life as we can manage. Plus, we’ve got plans to integrate player achievements for those who master the tactics of wildfire management. Who knew wildfire management could be this fun?

    And of course, because I know you’re all here for the cat photos, here’s a shot of my two older babies, Maggie (the larger and younger of the two) and Cider (my teeny tiny Bengal baby who just turned 9 years old!)

    That’s all for now! Stay tuned for more Sim Firefighter updates, I can’t wait to share how this journey unfolds!

    Capstone Project Update: Parchment with Captured Sun!

    It’s happening, folks! The fall term is in full swing, and I’ve officially kicked off my capstone project. I’m excited to announce that my team and I are working on a project called Parchment with a startup based in Austin, Texas, called Captured Sun. This project is ambitious and exciting, pushing us to explore new ways of interacting with our computers.

    Our team has seven talented seniors from OSU’s eCampus, and each of us brings something unique to the table. During our first meeting with the folks at Captured Sun, we dove right into planning and discussing how to tackle the project. I’ve been using Obsidian to keep notes and ideas organized, and it’s already been a game changer.

    I won’t lie, the term has been a whirlwind. Between classes, working on my portfolio, and now this project, it’s been busy. But it’s the kind of busy that keeps you on your toes in the best way possible. It’s starting to feel like everything I’ve learned so far is coming together, and despite the workload, I’m more motivated than ever to make this experience count.

    My goals for this capstone? I’m looking forward to diving into new technologies and learning from both my team and our mentors at Captured Sun. It’s a fantastic opportunity, and I’m eager to see where this journey takes us!

    That’s where things stand for now. The team is fired up, and I can’t wait to see how this project evolves over the coming weeks. I’ll definitely keep you all posted with updates as we tackle this challenge together.

    And as promised, here’s a little something to make you smile — a picture of one of my cats, Maggie, from the day I brought her home 8 years ago! 🐱