Advent of Code 2022 day 21

Again, relatively straightforward. Part 2 wasn’t a great deal more complicated. I couldn’t figure out quickly a way to use eval so hand-coded each case for the four different operands, but hey ho.

Part 1

def parse(data, value):
    if value.isnumeric():
        return int(value)
    elif value.count(" ") == 2:
        x, operand, y = value.split(" ")
        if operand == "+":
            return parse(data, data[x]) + parse(data, data[y])
        elif operand == "-":
            return parse(data, data[x]) - parse(data, data[y])
        elif operand == "*":
            return parse(data, data[x]) * parse(data, data[y])
        elif operand == "/":
            return int(parse(data, data[x]) / parse(data, data[y]))

def calculate(data):
    return parse(data, data["root"])

with open("21.txt") as f:
    lines = f.read().splitlines()

data = {
    line.split(": ")[0]: line.split(": ")[1]
    for line in lines
}

print(calculate(data))

Part 2

def in_tree(data, key, looking_for):
    if key == looking_for:
        return True
    elif data[key].count(" ") == 2:
        x, _, y = data[key].split(" ")
        return in_tree(data, x, looking_for) or in_tree(data, y, looking_for)

def parse(data, key):
    if key == "root":
        x, _, y = data[key].split()
        if in_tree(data, x, looking_for="humn"):
            return reverse_calc(data, parse(data, y), x)
        elif in_tree(data, y, looking_for="humn"):
            return reverse_calc(data, parse(data, x), y)
    elif data[key].isnumeric():
        return int(data[key])
    elif data[key].count(" ") == 2:
        x, operand, y = data[key].split(" ")
        if operand == "+":
            return parse(data, x) + parse(data, y)
        elif operand == "-":
            return parse(data, x) - parse(data, y)
        elif operand == "*":
            return parse(data, x) * parse(data, y)
        elif operand == "/":
            return int(parse(data, x) / parse(data, y))

def reverse_calc(data, value, key):
    if key == "humn":
        return value
    elif data[key].isnumeric():
        return int(data[key])
    elif data[key].count(" ") == 2:
        x, operand, y = data[key].split(" ")
        in_x = in_tree(data, x, "humn")
        if operand == "+":
            if in_x:
                return reverse_calc(data, value-parse(data, y), x)
            else:
                return reverse_calc(data, value-parse(data, x), y)
        elif operand == "-":
            if in_x:
                return reverse_calc(data, value+parse(data, y), x)
            else:
                return reverse_calc(data, parse(data, x)-value, y)
        elif operand == "*":
            if in_x:
                return reverse_calc(data, int(value/parse(data, y)), x)
            else:
                return reverse_calc(data, int(value/parse(data, x)), y)
        elif operand == "/":
            if in_x:
                return reverse_calc(data, value*parse(data, y), x)
            else:
                return reverse_calc(data, int(parse(data, x)/value), y)

def calculate(data):
    return parse(data, "root")

with open("21.txt") as f:
    lines = f.read().splitlines()

data = {
    line.split(": ")[0]: line.split(": ")[1]
    for line in lines
}

print(calculate(data))