Skip to content

Advent of Code. Year 2015. Day 12

Published: (2 min read)

--- Day 12: JSAbacusFramework.io ---

In today’s challenge we have to help Santa’s Accounting-Elves. They have a JSON document which contains a variety of things: arrays ([1,2,3]), objects ({"a":1, "b":2}), numbers, and strings.

Table of Contents

Open Table of Contents

Part 1

In the first part, we need to find the sum of all numbers in JSON. To solve this part, we used Regex.Matches to get all numbers from JSON string. Then we just iterated through all of them to get the resulting sum.

public string Part1(IEnumerable<string> lines)
{
  var input = GetInput(lines);
  var matches = Regex.Matches(input, @"-?\d+");
  var sum = 0;
  foreach (Match match in matches)
  {
    if (int.TryParse(match.Value, out var result))
      sum += result;
    else
      throw new Exception("Bad string");
  }
  return sum.ToString();
}

Part 2

In the second part, we also need to find the sum of all numbers in JSON but this time we need to ignore any object and all of its children which has any value "red".

This time we can’t just parse all numbers, so we have to parse JSON itself. To do that, we used a library called Json.NET. We created a method that can figure out which method should be called with a given token. For example, if the token is object, then ProcessObject method will be called.

private static int ProcessToken(JToken token)
{
  switch (token)
  {
    case JArray array:
      return ProcessArray(array);
    case JObject jObject:
      return ProcessObject(jObject);
    case JValue value:
      return ProcessValue(value);
  }

  return 0;
}
private static int ProcessArray(JArray array)
{
  return array.Children().Sum(ProcessToken);
}
private static int ProcessValue(JValue value)
{
  return int.TryParse(value.Value.ToString(), out var elem) ? elem : 0;
}
private static int ProcessObject(JObject jObject)
{
  foreach (var jProperty in jObject.Properties())
  {
    if (!(jProperty.Value is JValue jValue))
      continue;

    if (jValue.Value.ToString() == "red")
      return 0;
  }

  return jObject.Properties().Sum(jProperty => ProcessToken(jProperty.Value));
}

The final piece is to parse the input and call ProcessArray on it.

public string Part2(IEnumerable<string> lines)
{
  var input = GetInput(lines);
  return ProcessArray(JArray.Parse(input)).ToString();
}

Links:

Other posts