2023-01-03 — 2 min read

Advent of Code 2015, Day 12 – In Ruby

Let’s see the 12th puzzle of 2015!

The first half of the puzzle

Santa’s Accounting-Elves need help balancing the books after a recent order. Unfortunately, their accounting software uses a peculiar storage format. That’s where you come in.

They have a JSON document which contains a variety of things: arrays ([1,2,3]), objects ({“a”:1, “b”:2}), numbers, and strings. Your first job is to simply find all of the numbers throughout the document and add them together.

For example:

  • [1,2,3] and {“a”:2,”b”:4} both have a sum of 6.
  • [[[3]]] and {“a”:{“b”:4},”c”:-1} both have a sum of 3.
  • {“a”:[-1,1]} and [-1,{“a”:1}] both have a sum of 0.
  • [] and {} both have a sum of 0.

You will not encounter any strings containing numbers.

What is the sum of all numbers in the document?

The solution:

#!/usr/bin/env ruby

sum = ARGF.read.gsub(/[^-0-9]+/, ' ').split.map(&:to_i).reduce(:+)

puts "The sum of all numbers is #{sum}"

Step-by-step explanation:

This will work due to the premise that none of the strings will contain numbers: we can simply ‘erase’ everything that’s not a number, and add the numbers that remain.

The second half of the puzzle

Uh oh - the Accounting-Elves have realized that they double-counted everything red.

Ignore any object (and all of its children) which has any property with the value “red”. Do this only for objects ({…}), not arrays ([…]).

  • [1,2,3] still has a sum of 6.
  • [1,{“c”:”red”,”b”:2},3] now has a sum of 4, because the middle object is ignored.
  • {“d”:”red”,”e”:[1,2,3,4],”f”:5} now has a sum of 0, because the entire structure is ignored.
  • [1,”red”,5] has a sum of 6, because “red” in an array has no effect.

The solution:

#!/usr/bin/env ruby

require 'json'

input = JSON.parse(ARGF.read)
$sum = 0

def count(i)
  return if i.is_a? Hash and i.values.include?('red')

  (i.is_a?(Array) ? i : i.values).each { |y| count(y) } if i.class.method_defined? :each
  $sum += i if i.is_a? Integer
end

count(input)
puts "The sum of all numbers excluding red is #{$sum}"

This time there’s no shortcut, we need to parse the input with Ruby’s json module. The solution needs to be recursive, because arrays and hashes can be nested in each other in the input.

In the count method, we first check whether the input is a Hash which contains the value red anywhere. If it is, we ignore this object (return early).

The next step depends on the type of the input:

The code with my input text is available in the GitHub repo.

Thanks for reading! If you have any comments, additions, or corrections, feel free to reach me via e-mail.

Copyright © 2023 csm.hu
Contact