From bf12e141a63da6a09b7f42e54ab24312dca18d21 Mon Sep 17 00:00:00 2001 From: Thraix Date: Sat, 15 Aug 2026 15:24:22 +0200 Subject: [PATCH] Add solution for 2016 Day 5 - Add Md5 algorithm to library --- res/2016/day05/test_input.txt | 1 + src/2016/Day05.cpp | 54 ++++++++++--- src/common/aoc.h | 1 + src/common/lib/Md5.cpp | 140 ++++++++++++++++++++++++++++++++++ src/common/lib/Md5.h | 17 +++++ 5 files changed, 201 insertions(+), 12 deletions(-) create mode 100644 src/common/lib/Md5.cpp create mode 100644 src/common/lib/Md5.h diff --git a/res/2016/day05/test_input.txt b/res/2016/day05/test_input.txt index e69de29..8baef1b 100644 --- a/res/2016/day05/test_input.txt +++ b/res/2016/day05/test_input.txt @@ -0,0 +1 @@ +abc diff --git a/src/2016/Day05.cpp b/src/2016/Day05.cpp index 3c6ef48..129ded5 100644 --- a/src/2016/Day05.cpp +++ b/src/2016/Day05.cpp @@ -2,30 +2,60 @@ namespace y2016::day05 { - REGISTER_DAY(2016, Day05, std::vector, int); + REGISTER_DAY(2016, Day05, std::string, std::string); - REGISTER_TEST_EXAMPLE(2016, Day05, ExampleInput, 1, 0); - REGISTER_TEST(2016, Day05, Input, 1, 0); - REGISTER_TEST_EXAMPLE(2016, Day05, ExampleInput, 2, 0); - REGISTER_TEST(2016, Day05, Input, 2, 0); + REGISTER_TEST(2016, Day05, Input, 1, "f97c354d"); + REGISTER_TEST(2016, Day05, Input, 2, "863dde27"); READ_INPUT(input) { - std::vector vec; std::string str; - while (getline(input, str)) - { - } - return vec; + getline(input, str); + return str; } OUTPUT1(input) { - return 0; + int i = 0; + std::string result; + while (true) + { + std::string str = input + std::to_string(i); + std::string s = Md5::Hash(str); + if (Helper::StartsWith(s, "00000")) + { + result.push_back(s[5]); + if (result.size() == 8) + return result; + } + i++; + } + return ""; } OUTPUT2(input) { - return 0; + int i = 0; + std::string result{"XXXXXXXX"}; + int replacements = 0; + for (int i = 0;; i++) + { + std::string str = input + std::to_string(i); + std::string s = Md5::Hash(str); + if (Helper::StartsWith(s, "00000")) + { + if (s[5] < '0' || s[5] > '7') + continue; + + if (result[s[5] - '0'] == 'X') + { + result[s[5] - '0'] = s[6]; + replacements++; + } + if (replacements == 8) + return result; + } + } + return ""; } } diff --git a/src/common/aoc.h b/src/common/aoc.h index 5594164..e0d7daa 100644 --- a/src/common/aoc.h +++ b/src/common/aoc.h @@ -30,6 +30,7 @@ #include "common/lib/Json.h" #include "common/lib/Mapper.h" #include "common/lib/Math.h" +#include "common/lib/Md5.h" #include "common/lib/Timer.h" #define TERM_RED "\x1B[31m" diff --git a/src/common/lib/Md5.cpp b/src/common/lib/Md5.cpp new file mode 100644 index 0000000..de8218a --- /dev/null +++ b/src/common/lib/Md5.cpp @@ -0,0 +1,140 @@ +#include "common/lib/Md5.h" + +#include +#include +#include +#include + +uint32_t Md5::BytesToUint32(uint8_t* data) +{ + return ((uint32_t)data[3] << 24) | ((uint32_t)data[2] << 16) | ((uint32_t)data[1] << 8) | (uint32_t)data[0]; +} + +uint32_t Md5::LeftRotate(uint32_t x, uint32_t n) +{ + return (x << n) | (x >> (32 - n)); +} + +void Md5::Transform(uint8_t* data, uint32_t& a0, uint32_t& b0, uint32_t& c0, uint32_t& d0) +{ + // clang-format off + const static std::array K + { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, + 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, + 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, + 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, + 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, + 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, + 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, + 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, + 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391 + }; + const static std::array S + { + 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, + 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, + 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, + 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21 + }; + // clang-format on + + uint32_t A = a0; + uint32_t B = b0; + uint32_t C = c0; + uint32_t D = d0; + + for (int i = 0; i < 64; i++) + { + uint32_t F; + uint32_t g; + if (i < 16) + { + F = (B & C) | ((~B) & D); + g = i; + } + else if (i < 32) + { + F = (D & B) | ((~D) & C); + g = (5 * i + 1) % 16; + } + else if (i < 48) + { + F = B ^ C ^ D; + g = (3 * i + 5) % 16; + } + else + { + F = C ^ (B | (~D)); + g = (7 * i) % 16; + } + F = F + A + K[i] + BytesToUint32(data + g * 4); + A = D; + D = C; + C = B; + B = B + LeftRotate(F, S[i]); + } + a0 += A; + b0 += B; + c0 += C; + d0 += D; +} + +void Md5::PrintUint32(std::ostream& os, uint32_t n) +{ + os << std::hex; + os << std::setw(2) << std::setfill('0') << (n & 0xff); + os << std::setw(2) << std::setfill('0') << ((n >> 8) & 0xff); + os << std::setw(2) << std::setfill('0') << ((n >> 16) & 0xff); + os << std::setw(2) << std::setfill('0') << ((n >> 24) & 0xff); + os << std::dec; +} + +std::string Md5::Hash(std::string str) +{ + str += 0x80; + + uint32_t a0 = 0x67452301; + uint32_t b0 = 0xefcdab89; + uint32_t c0 = 0x98badcfe; + uint32_t d0 = 0x10325476; + + uint64_t size = str.size(); + uint64_t bytesToAdd = (64 + 56 - (size % 64)) % 64; + + // std::cout << str.size() << " " << bytesToAdd << std::endl; + int loops = (size + bytesToAdd + 8) / 64; + if ((size + bytesToAdd + 8) % 64 != 0) + loops++; + uint64_t offset = 0; + for (int i = 0; i < loops - 1; i++) + { + Transform((uint8_t*)(str.c_str() + offset), a0, b0, c0, d0); + offset += 64; + } + + uint8_t data[64]; + std::memset(data, 0x0, 64); + if (str.size() >= offset) + std::memcpy(data, str.c_str() + offset, str.size() - offset); + for (int i = 0; i < 8; i++) + { + data[56 + i] = (((str.size() - 1) * 8) >> (i * 8)) & 0xff; + } + + Transform(data, a0, b0, c0, d0); + + std::stringstream ss{}; + PrintUint32(ss, a0); + PrintUint32(ss, b0); + PrintUint32(ss, c0); + PrintUint32(ss, d0); + return ss.str(); +} diff --git a/src/common/lib/Md5.h b/src/common/lib/Md5.h new file mode 100644 index 0000000..1f8bfbc --- /dev/null +++ b/src/common/lib/Md5.h @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include + +class Md5 +{ +public: + static std::string Hash(std::string str); + +private: + static uint32_t BytesToUint32(uint8_t* data); + static uint32_t LeftRotate(uint32_t x, uint32_t n); + static void Transform(uint8_t* data, uint32_t& a0, uint32_t& b0, uint32_t& c0, uint32_t& d0); + static void PrintUint32(std::ostream& os, uint32_t n); +};