#include #include #include #include #include namespace knothash { auto hash(std::string key) -> std::array { key += 17; key += 31; key += 73; key += 47; key += 23; auto sparse = hash_ex<256>(64, key.begin(), key.end()); std::size_t offset = 0; std::array dense; for (auto & x : dense) { x = std::reduce(sparse.begin()+offset, sparse.begin()+offset+16, 0, std::bit_xor()); offset += 16; } return dense; } auto render(std::array const& hash) -> std::string { std::ostringstream out; out << std::hex << std::setfill('0'); for (int const x : hash) { out << std::setw(2) << int(x); } return out.str(); } TEST_SUITE("knot hash") { TEST_CASE("reverser") { std::array v {0,1,2,3,4,5,6,7,8}; SUBCASE("more left") { std::array expect {1,0,8,7,4,5,6,3,2}; reverser(v, 7, 6); REQUIRE(v == expect); } SUBCASE("more right") { std::array expect {6,5,2,3,4,1,0,8,7}; reverser(v, 5, 6); REQUIRE(v == expect); } SUBCASE("middle") { std::array expect {0,1,5,4,3,2,6,7,8}; reverser(v, 2, 4); CHECK(v == expect); } } TEST_CASE("knot example") { std::array lengths {3, 4, 1, 5}; auto result = hash_ex<5>(1, lengths.begin(), lengths.end()); std::array expected {3, 4, 2, 1, 0}; CHECK(result == expected); } TEST_CASE("hash examples") { CHECK(render(hash("")) == "a2582a3a0e66e6e86e3812dcb672a272"); CHECK(render(hash("AoC 2017")) == "33efeb34ea91902bb2f59c9920caa6cd"); CHECK(render(hash("1,2,3")) == "3efbe78a8d82f29979031a4aa0b16a9d"); CHECK(render(hash("1,2,4")) == "63960835bcdc130f0b66d7ff4f6a5a8e"); } } } // namespace