--- 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
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;
}
- To process array, we need to call
ProcessToken
on all elements of that array.
private static int ProcessArray(JArray array)
{
return array.Children().Sum(ProcessToken);
}
- To process value we need to try parse value to an integer and if that parse succeeds then we are returning it otherwise we are returning
0
.
private static int ProcessValue(JValue value)
{
return int.TryParse(value.Value.ToString(), out var elem) ? elem : 0;
}
- Parsing object a little bit more difficult. First, we need to iterate through all of the properties to check if that property contains the value
"red"
. If"red"
is found we are returning return value0
. Otherwise, we callProcessToken
on all properties and get the sum.
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: