aocpp/knothash/src/knothash.cpp
2022-11-24 12:52:37 -08:00

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("knothash library") {
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);
CHECK(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);
CHECK(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