aocpp/knothash/include/knothash.hpp
2022-11-24 12:10:08 -08:00

56 lines
1.4 KiB
C++

#ifndef KNOTHASH_HPP_
#define KNOTHASH_HPP_
#include <cstddef>
#include <array>
#include <algorithm>
#include <string>
namespace knothash {
template <std::size_t N>
auto reverser(std::array<std::uint8_t, N> & result, std::size_t cursor, std::size_t len) -> void {
auto leftside = N - cursor;
auto start = result.begin() + cursor;
if (len <= leftside) {
std::reverse(start, start + len);
} else {
auto rightside = len - leftside;
if (leftside < rightside) {
std::swap_ranges(start, result.end(), result.rend() - rightside);
std::reverse(result.begin(), result.begin() + (rightside-leftside));
} else {
std::swap_ranges(result.rend() - rightside, result.rend(), start);
std::reverse(result.end() - (leftside-rightside), result.end());
}
}
}
auto hash(std::string key) -> std::array<std::uint8_t, 16>;
auto render(std::array<std::uint8_t, 16> const& hash) -> std::string;
template <std::size_t N, typename It>
auto hash_ex(std::size_t cycles, It begin, It end)
-> std::array<std::uint8_t, N>
{
std::size_t cursor = 0;
std::size_t skip = 0;
std::array<std::uint8_t, N> result;
for (std::size_t i = 0; i < N; i++) { result[i] = i; }
for (std::size_t i = 0; i < cycles; i++) {
std::for_each(begin, end, [&](std::size_t len) {
reverser(result, cursor, len);
cursor += skip + len;
cursor %= N;
skip++;
});
}
return result;
}
} // namespace
#endif