Advent of Code — Day 2

Onwards! To day 2.

(at least until the rest of the end-of-year things start getting in the way — which normally happens at around day 6)

Started reading this one thinking we'd be getting in to probabilities — thankfully that's not the case, yet.

Part 1

For today's puzzle, we're given the following input:

Game 1: 3 blue, 4 red; 1 red, 2 green, 6 blue; 2 green  
Game 2: 1 blue, 2 green; 3 green, 4 blue, 1 red; 1 green, 1 blue  
Game 3: 8 green, 6 blue, 20 red; 5 blue, 4 red, 13 green; 5 green, 1 red  
Game 4: 1 green, 3 red, 6 blue; 3 green, 6 red; 3 green, 15 blue, 14 red  
Game 5: 6 red, 1 blue, 3 green; 2 blue, 1 red, 2 green

Each line, represents a game, and each segment (separated by a ;) represents a round in that game. Where, in each round, a set of cubes are pulled from a bag.

We're tasked with finding out, which games can be played with only the following cubes: 12 red cubes, 13 green cubes, and 14 blue cubes, then, sum the game number to find our answer.

For this one, I first wanted to add some structure to each game. Parsing each one in to a hash would then mean when I want to do some poking at each game, I could reason about each bit.

So for that, there's this method:

def build_games(input)  
  input.map do |line|  
    id = line.scan(/(\d+)[:]/).flatten.first.to_i  
    game = line.gsub("Game #{id}: ", "").split(";")  
    rounds = game.map do |reveal|  
      red = reveal.scan(/(\d+) red/).flatten.first&.to_i || 0  
      green = reveal.scan(/(\d+) green/).flatten.first&.to_i || 0  
      blue = reveal.scan(/(\d+) blue/).flatten.first&.to_i || 0  

      {  
        red: red,  
        green: green,  
        blue: blue  
      }  
    end  

    {  
      id: id,  
      rounds: rounds  
    }  
  end  
end

Which returns an array of games in the following shape:

game = {  
  id: 0,  
  rounds: [  
    red: 0,  
    green: 0,  
    blue: 0,  
  ]  
}

So then, it was just a matter of rejecting the games that exceeded our cube limit, and summing the IDs:

result = games.reject do |game|  
  game[:rounds].any? { |round|  
    round[:red] > 12 ||  
      round[:green] > 13 ||  
      round[:blue] > 14  
  }  
end  

result.map{|r| r[:id]}.inject(:+)

⭐️ Success!

Part 2

Thankfully, today's part 2 was free of gotchas!

In part 2, we need to work out what is the minimum number of balls we would need to be able to play each game. Then, multiply the number of balls for each colour, to get the power of the game. Sum all the powers, and that's our answer!

So for each game, we can work out the minimum number of required cubes with something like:

min_red = game[:rounds]  
            .map{|r| r[:red].zero? ? nil : r[:red] }  
            .compact  
            .max

for each cube colour (making sure to remove 0s so we don't multiply by 0).

N.B — this could have been solved by also making the number of cubes optional in our game hash.

Then it's just a matter of multiplying the cube counts, summing everything up and we're done for day 2!

⭐️ Success!

Day 2: https://github.com/dNitza/advent-of-code/tree/main/2023/02

Published

by Daniel Nitsikopoulos

in posts

Tagged

© 2010 - 2024 Daniel Nitsikopoulos. All rights reserved.

🕸💍  →