AoC 2015 Puzzle 12

Info

I solved this puzzle. You can find the code here, but I have yet to write a good explanation of the solution here. I will do this shortly, thank you for your patience.

Day 12: JSAbacusFramework.io

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?

Part 2

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.

Complete Solution

@Override
public String part1(List<String> input) {
    String json = input.get(0);

    Pattern pattern = Pattern.compile("-?[0-9]+");
    Matcher matcher = pattern.matcher(json);

    int sum = 0;
    while (matcher.find()) {
        String match = matcher.group();
        sum += Integer.parseInt(match);
    }
    return String.valueOf(sum);
}

boolean isRed(JsonNode node) {
    Iterator<JsonNode> it = node.iterator();
    while (it.hasNext()) {
        if ("red".equals(it.next().asText())) {
            return true;
        }
    }
    return false;
}

int doJsonSum(JsonNode node, int sum) {
    int res = 0;

    if (node.isInt()) {
        res += sum + node.asInt();
    }

    if (node.isArray()) {
        for (JsonNode n : node) {
            res += doJsonSum(n, sum);
        }
    }

    if (node.isObject() && !isRed(node)) {
        Iterator<JsonNode> it = node.elements();
        while (it.hasNext()) {
            JsonNode next = it.next();
            res += doJsonSum(next, sum);
        }
    }
    return res;
}

@Override
public String part2(List<String> input) {

    ObjectMapper mapper = new ObjectMapper();
    try {
        JsonNode js = mapper.readTree(input.get(0));
        return String.valueOf(doJsonSum(js, 0));
    } catch (Exception ex) {
        ex.printStackTrace();
    }

    return "0";
}