Add 2017 day 14 puzzles.
This commit is contained in:
93
2017/puzzle-14-01.cc
Normal file
93
2017/puzzle-14-01.cc
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
#include <bit>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <numeric>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using Byte = std::uint8_t;
|
||||||
|
using KnotString = std::vector<Byte>;
|
||||||
|
|
||||||
|
auto knot_round(KnotString const& in, Byte current_position, Byte length) -> KnotString
|
||||||
|
{
|
||||||
|
KnotString rot_left;
|
||||||
|
rot_left.reserve(in.size());
|
||||||
|
std::copy(in.begin() + current_position, in.end(), std::back_inserter(rot_left));
|
||||||
|
std::copy(in.begin(), in.begin() + current_position, std::back_inserter(rot_left));
|
||||||
|
|
||||||
|
std::reverse(rot_left.begin(), rot_left.begin() + length);
|
||||||
|
|
||||||
|
KnotString rot_right;
|
||||||
|
std::copy(rot_left.end() - current_position, rot_left.end(), std::back_inserter(rot_right));
|
||||||
|
std::copy(rot_left.begin(), rot_left.end() - current_position, std::back_inserter(rot_right));
|
||||||
|
return rot_right;
|
||||||
|
}
|
||||||
|
|
||||||
|
using Knot = std::pair<std::uint64_t, std::uint64_t>;
|
||||||
|
|
||||||
|
auto knot(std::string const& rounds) -> Knot
|
||||||
|
{
|
||||||
|
/* Put the lengths into a vector. */
|
||||||
|
std::vector<Byte> lengths;
|
||||||
|
lengths.reserve(rounds.size() + 5);
|
||||||
|
for (auto c : rounds) {
|
||||||
|
lengths.emplace_back(static_cast<Byte>(c));
|
||||||
|
}
|
||||||
|
lengths.emplace_back(17);
|
||||||
|
lengths.emplace_back(31);
|
||||||
|
lengths.emplace_back(73);
|
||||||
|
lengths.emplace_back(47);
|
||||||
|
lengths.emplace_back(23);
|
||||||
|
|
||||||
|
/* Run the hash */
|
||||||
|
Byte current_pos{0};
|
||||||
|
Byte skip{0};
|
||||||
|
std::vector<Byte> string;
|
||||||
|
string.resize(256);
|
||||||
|
std::iota(string.begin(), string.end(), 0);
|
||||||
|
|
||||||
|
for (unsigned i{0}; i < 64; ++i) {
|
||||||
|
for (auto length : lengths) {
|
||||||
|
string = knot_round(string, current_pos, length);
|
||||||
|
current_pos += length + skip;
|
||||||
|
++skip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print the dense hash. */
|
||||||
|
std::uint64_t result0{0};
|
||||||
|
std::uint64_t result1{0};
|
||||||
|
std::uint64_t* hash{&result0};
|
||||||
|
for (unsigned i{0}; i < string.size(); ++i) {
|
||||||
|
if (i % 16 == 0) {
|
||||||
|
if (i == string.size() / 2) {
|
||||||
|
hash = &result1;
|
||||||
|
}
|
||||||
|
*hash <<= 8;
|
||||||
|
}
|
||||||
|
*hash ^= string[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return {result0, result1};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto main() -> int
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
if (!std::getline(std::cin, line)) {
|
||||||
|
std::cerr << "Unable to read Line\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned bit_count{0};
|
||||||
|
for (unsigned i = 0; i < 128; ++i) {
|
||||||
|
std::string key{line};
|
||||||
|
key += '-';
|
||||||
|
key += std::to_string(i);
|
||||||
|
auto [knot1, knot2] = knot(key);
|
||||||
|
bit_count += std::popcount(knot1) + std::popcount(knot2);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Population count " << bit_count << '\n';
|
||||||
|
return 0;
|
||||||
|
}
|
133
2017/puzzle-14-02.cc
Normal file
133
2017/puzzle-14-02.cc
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
#include <bit>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
|
#include <numeric>
|
||||||
|
#include <set>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
using UInt = unsigned;
|
||||||
|
using Byte = std::uint8_t;
|
||||||
|
using KnotString = std::vector<Byte>;
|
||||||
|
|
||||||
|
auto knot_round(KnotString const& in, Byte current_position, Byte length) -> KnotString
|
||||||
|
{
|
||||||
|
KnotString rot_left;
|
||||||
|
rot_left.reserve(in.size());
|
||||||
|
std::copy(in.begin() + current_position, in.end(), std::back_inserter(rot_left));
|
||||||
|
std::copy(in.begin(), in.begin() + current_position, std::back_inserter(rot_left));
|
||||||
|
|
||||||
|
std::reverse(rot_left.begin(), rot_left.begin() + length);
|
||||||
|
|
||||||
|
KnotString rot_right;
|
||||||
|
std::copy(rot_left.end() - current_position, rot_left.end(), std::back_inserter(rot_right));
|
||||||
|
std::copy(rot_left.begin(), rot_left.end() - current_position, std::back_inserter(rot_right));
|
||||||
|
return rot_right;
|
||||||
|
}
|
||||||
|
|
||||||
|
using Knot = std::pair<std::uint64_t, std::uint64_t>;
|
||||||
|
|
||||||
|
auto knot(std::string const& rounds) -> Knot
|
||||||
|
{
|
||||||
|
/* Put the lengths into a vector. */
|
||||||
|
std::vector<Byte> lengths;
|
||||||
|
lengths.reserve(rounds.size() + 5);
|
||||||
|
for (auto c : rounds) {
|
||||||
|
lengths.emplace_back(static_cast<Byte>(c));
|
||||||
|
}
|
||||||
|
lengths.emplace_back(17);
|
||||||
|
lengths.emplace_back(31);
|
||||||
|
lengths.emplace_back(73);
|
||||||
|
lengths.emplace_back(47);
|
||||||
|
lengths.emplace_back(23);
|
||||||
|
|
||||||
|
/* Run the hash */
|
||||||
|
Byte current_pos{0};
|
||||||
|
Byte skip{0};
|
||||||
|
std::vector<Byte> string;
|
||||||
|
string.resize(256);
|
||||||
|
std::iota(string.begin(), string.end(), 0);
|
||||||
|
|
||||||
|
for (unsigned i{0}; i < 64; ++i) {
|
||||||
|
for (auto length : lengths) {
|
||||||
|
string = knot_round(string, current_pos, length);
|
||||||
|
current_pos += length + skip;
|
||||||
|
++skip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Print the dense hash. */
|
||||||
|
std::uint64_t result0{0};
|
||||||
|
std::uint64_t result1{0};
|
||||||
|
std::uint64_t* hash{&result0};
|
||||||
|
for (unsigned i{0}; i < string.size(); ++i) {
|
||||||
|
if (i % 16 == 0) {
|
||||||
|
if (i == string.size() / 2) {
|
||||||
|
hash = &result1;
|
||||||
|
}
|
||||||
|
*hash <<= 8;
|
||||||
|
}
|
||||||
|
*hash ^= string[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return {result0, result1};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto main() -> int
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
if (!std::getline(std::cin, line)) {
|
||||||
|
std::cerr << "Unable to read Line\n";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::set<std::pair<UInt, UInt>> clusters;
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < 128; ++i) {
|
||||||
|
constexpr std::uint64_t top_bit{1ULL << 63};
|
||||||
|
std::string key{line};
|
||||||
|
key += '-';
|
||||||
|
key += std::to_string(i);
|
||||||
|
auto [knot1, knot2] = knot(key);
|
||||||
|
for (auto j = 0; j < 64; ++j) {
|
||||||
|
if (0 != (knot1 & top_bit)) {
|
||||||
|
clusters.insert({j, i});
|
||||||
|
}
|
||||||
|
if (0 != (knot2 & top_bit)) {
|
||||||
|
clusters.insert({j + 64, i});
|
||||||
|
}
|
||||||
|
knot1 <<= 1;
|
||||||
|
knot2 <<= 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Population count " << clusters.size() << '\n';
|
||||||
|
|
||||||
|
UInt cluster_count{0};
|
||||||
|
while (!clusters.empty()) {
|
||||||
|
++cluster_count;
|
||||||
|
std::set<std::pair<UInt, UInt>> to_check;
|
||||||
|
to_check.insert(*clusters.begin());
|
||||||
|
while (!to_check.empty()) {
|
||||||
|
auto it{to_check.begin()};
|
||||||
|
auto [x, y] = *it;
|
||||||
|
clusters.erase(*it);
|
||||||
|
to_check.erase(it);
|
||||||
|
if (clusters.contains({x + 1, y})) {
|
||||||
|
to_check.insert({x + 1, y});
|
||||||
|
}
|
||||||
|
if (clusters.contains({x, y + 1})) {
|
||||||
|
to_check.insert({x, y + 1});
|
||||||
|
}
|
||||||
|
if (x != 0 && clusters.contains({x - 1, y})) {
|
||||||
|
to_check.insert({x - 1, y});
|
||||||
|
}
|
||||||
|
if (y != 0 && clusters.contains({x, y - 1})) {
|
||||||
|
to_check.insert({x, y - 1});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Number of cluster groups " << cluster_count << '\n';
|
||||||
|
return 0;
|
||||||
|
}
|
Reference in New Issue
Block a user