Unable to load image

Day 21 AoC: use Z3 b-words

Post code, boast about it.

13
Jump in the discussion.

No email address required.

Why use fancy solver, when you can just binary search your way through all the possible numbers. And got giga trolled by std::cout presenting doubles as scientific notation. Did it with double first, realized that i need a "proper" number, so switched to int64t. This worked fine for p1. But apparently for p2, if you use int instead of double, there are multiple possible solutions...

So figured out how to set cout to display the double properly and it worked.

p1 runs in 0ms, and p2 in 168ms


#include <iostream>
#include <variant>
#include <unordered_map>
#include <fstream>
#include <string>
#include <ranges>
#include <charconv>
#include <cassert>
#include <string_view>
#include <limits>
#include <chrono>

constexpr std::string_view delim{ ": " };

struct expression {
    std::string lhs;
    std::string rhs;
    char operand;
};

std::ostream& operator<<(std::ostream& os, expression e) {
    os << e.lhs << " " << e.operand << " " << e.rhs;
    return os;
}

typedef long double monkey_number;

typedef std::variant<monkey_number, expression> number_or_expression;

monkey_number do_the_monkey_math(std::string key, std::unordered_map<std::string, number_or_expression>& map) {
    if (const monkey_number* d = std::get_if<monkey_number>(&map[key])) {
        return *d;
    }
    else {
        const expression& exp = std::get<expression>(map[key]);
        monkey_number result{};
        if (exp.operand == '*') result = do_the_monkey_math(exp.lhs, map) * do_the_monkey_math(exp.rhs, map);
        else if (exp.operand == '+') result = do_the_monkey_math(exp.lhs, map) + do_the_monkey_math(exp.rhs, map);
        else if (exp.operand == '/') result = do_the_monkey_math(exp.lhs, map) / do_the_monkey_math(exp.rhs, map);
        else if (exp.operand == '-') result = do_the_monkey_math(exp.lhs, map) - do_the_monkey_math(exp.rhs, map);
        else assert("Panic this shouldn't happen");
        return result;
    }
}

monkey_number do_the_monkey_math_part_two(std::string key, std::unordered_map<std::string, number_or_expression>& map, monkey_number humn) {
    if (key == "humn") {
        return humn;
    }
    else if (key == "root") {
        const expression& exp = std::get<expression>(map[key]);
        return do_the_monkey_math_part_two(exp.lhs, map, humn) - do_the_monkey_math_part_two(exp.rhs, map, humn);
    }
    else if (const monkey_number* d = std::get_if<monkey_number>(&map[key])) {
        if (key == "humn") std::cout << "humn" << *d << '\n';
        return *d;
    }
    else {
        const expression& exp = std::get<expression>(map[key]);
        monkey_number result{};
        if (exp.operand == '*') result = do_the_monkey_math_part_two(exp.lhs, map, humn) * do_the_monkey_math_part_two(exp.rhs, map, humn);
        else if (exp.operand == '+') result = do_the_monkey_math_part_two(exp.lhs, map, humn) + do_the_monkey_math_part_two(exp.rhs, map, humn);
        else if (exp.operand == '/') result = do_the_monkey_math_part_two(exp.lhs, map, humn) / do_the_monkey_math_part_two(exp.rhs, map, humn);
        else if (exp.operand == '-') result = do_the_monkey_math_part_two(exp.lhs, map, humn) - do_the_monkey_math_part_two(exp.rhs, map, humn);
        else assert("Panic this shouldn't happen");
        return result;
    }
}

void load_values(std::unordered_map<std::string, number_or_expression>& map)
{
    std::fstream file("input.txt");
    std::string buffer;

    while (std::getline(file, buffer)) {
        std::string key;
        for (const auto el : std::views::split(buffer, delim)) {
            if (key.size() == 0) key = { el.begin(), el.end() };
            else {
                auto view = std::string_view{ el.begin(), el.end() };
                if (std::isdigit(view[0])) {
                    monkey_number number;
                    std::from_chars(view.data(), view.data() + view.size(), number);
                    map[key] = number;
                }
                else {
                    expression exp;
                    exp.lhs = { view.data(), view.data() + 4 };
                    exp.operand = view[5];
                    exp.rhs = { view.data() + 7, view.data() + view.size() };
                    map[key] = exp;
                }
            }
        }
    }
}

int main()
{
    std::cout << std::fixed;
    std::unordered_map<std::string, number_or_expression> map;

    load_values(map);

    auto a = std::chrono::high_resolution_clock::now();
    std::cout << "Part One: " << do_the_monkey_math("root", map) << '\n';
    auto b = std::chrono::high_resolution_clock::now();

    monkey_number humn = 1;
    monkey_number res = 1;
    monkey_number min = std::numeric_limits<monkey_number>::min();
    monkey_number max = std::numeric_limits<monkey_number>::max();

    while (res != 0) {
        monkey_number mid = (min + max) / 2;
        humn = mid;
        res = do_the_monkey_math_part_two("root", map, humn);
        if (res > 0) min = mid + 1;
        else max = mid - 1;
    }
    std::cout << "Part Two: " << humn << '\n';
    auto c = std::chrono::high_resolution_clock::now();


    auto ba = std::chrono::duration_cast<std::chrono::milliseconds>(b - a);
    auto cb = std::chrono::duration_cast<std::chrono::milliseconds>(c - b);

    std::cout << "Time p1: " << ba << " p2: " << cb << '\n';

}

Jump in the discussion.

No email address required.

This is one of the worst posts I have EVER seen. Delete it.

Jump in the discussion.

No email address required.



Now playing: Donkey Kong December National Anthem.mp3

Link copied to clipboard
Action successful!
Error, please refresh the page and try again.