// Problem Forge, Problem of the Month, rungs 06 and 07: the rule. CC0 1.0 (public domain). // Vertices i < j are joined when the first bit of SHA-256(K, i, j) is 1, // with K as its 32 bytes and i, j as 8-byte big-endian numbers. // Build: c++ -std=c++17 rule.cpp -lcrypto Use: ./a.out KEY i j (prints 1 if joined, else 0) #include #include #include #include #include #include bool joined(const std::array & key, std::uint64_t i, std::uint64_t j) { if (i > j) { std::swap(i, j); } unsigned char msg[48], out[32]; for (int b = 0; b < 32; ++b) { msg[b] = key[b]; } for (int b = 0; b < 8; ++b) { msg[32 + b] = static_cast(i >> (56 - 8 * b)); msg[40 + b] = static_cast(j >> (56 - 8 * b)); } SHA256(msg, sizeof msg, out); return out[0] & 0x80; } int main(int argc, char ** argv) { if (argc != 4) { return 2; } std::array key{}; for (int b = 0; b < 32; ++b) { key[b] = static_cast(std::stoi(std::string(argv[1] + 2 * b, 2), nullptr, 16)); } std::cout << joined(key, std::stoull(argv[2]), std::stoull(argv[3])) << "\n"; }