80 lines
1.8 KiB
C++
80 lines
1.8 KiB
C++
|
#include <knothash.hpp>
|
||
|
|
||
|
#include <numeric>
|
||
|
#include <iomanip>
|
||
|
#include <sstream>
|
||
|
|
||
|
#include <doctest.h>
|
||
|
|
||
|
namespace knothash {
|
||
|
|
||
|
auto hash(std::string key) -> std::array<std::uint8_t, 16>
|
||
|
{
|
||
|
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<std::uint8_t, 16> 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<std::uint8_t, 16> 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<std::uint8_t, 9> v {0,1,2,3,4,5,6,7,8};
|
||
|
|
||
|
SUBCASE("more left") {
|
||
|
std::array<std::uint8_t, 9> expect {1,0,8,7,4,5,6,3,2};
|
||
|
reverser(v, 7, 6);
|
||
|
REQUIRE(v == expect);
|
||
|
}
|
||
|
|
||
|
SUBCASE("more right") {
|
||
|
std::array<std::uint8_t, 9> expect {6,5,2,3,4,1,0,8,7};
|
||
|
reverser(v, 5, 6);
|
||
|
REQUIRE(v == expect);
|
||
|
}
|
||
|
|
||
|
SUBCASE("middle") {
|
||
|
std::array<std::uint8_t, 9> expect {0,1,5,4,3,2,6,7,8};
|
||
|
reverser(v, 2, 4);
|
||
|
CHECK(v == expect);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
TEST_CASE("knot example") {
|
||
|
std::array<std::size_t, 4> lengths {3, 4, 1, 5};
|
||
|
auto result = hash_ex<5>(1, lengths.begin(), lengths.end());
|
||
|
std::array<std::uint8_t, 5> 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
|