diff --git a/2017/11.cpp b/2017/11.cpp index 0ffec6e..d879964 100644 --- a/2017/11.cpp +++ b/2017/11.cpp @@ -10,43 +10,12 @@ #include #include +#include + +using namespace aocpp; namespace { -/* - \ n / -nw +--+ ne - / \ --+ +- - \ / -sw +--+ se - / s \ -*/ - -struct Hex { - std::int64_t q, r, s; -}; - -constexpr Hex HEX_N { 0, -1, 1 }; -constexpr Hex HEX_NE { 1, -1, 0 }; -constexpr Hex HEX_SE { 1, 0, -1 }; -constexpr Hex HEX_S { 0, 1, -1 }; -constexpr Hex HEX_SW { -1, 1, 0 }; -constexpr Hex HEX_NW { -1, 0, 1 }; - -auto operator+(Hex a, Hex b) -> Hex { - return {a.q + b.q, a.r + b.r, a.s + b.s }; -} - -auto operator+=(Hex & a, Hex b) -> Hex & { - a.q += b.q; a.r += b.r; a.s += b.s; - return a; -} - -auto hex_distance(Hex hex) -> std::int64_t { - return (std::abs(hex.q) + std::abs(hex.r) + std::abs(hex.s)) / 2; -} - auto Walk(std::string const& commands) -> std::pair { @@ -93,7 +62,7 @@ TEST_SUITE("2017-11 examples") { auto main(int argc, char** argv) -> int { std::string line; - std::getline(*aocpp::Startup(argc, argv), line); + std::getline(*Startup(argc, argv), line); auto [part1, part2] = Walk(line); std::cout << "Part 1: " << part1 << std::endl; std::cout << "Part 2: " << part2 << std::endl; diff --git a/2017/12.cpp b/2017/12.cpp new file mode 100644 index 0000000..54c83ef --- /dev/null +++ b/2017/12.cpp @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace aocpp; + +namespace { + +auto Parse(std::istream & in) +-> std::vector> +{ + std::string line; + std::vector> result; + while (std::getline(in, line)) { + line.erase(std::remove_if(line.begin(), line.end(), [](auto c) { + return c=='<' || c=='-' || c=='>' || c == ','; + }), line.end()); + std::istringstream lin { line }; + std::uint16_t x; + lin >> x; + std::vector links; + while (lin >> x) { + links.push_back(x); + } + result.emplace_back(std::move(links)); + } + return result; +} + +auto Find(std::vector & leaders, std::uint16_t const who) -> std::uint16_t +{ + std::uint16_t cursor; + std::uint16_t leader = who; + + do { + cursor = leader; + leader = leaders[cursor]; + } while (leader != cursor); + + cursor = who; + while (cursor != leader) { + auto tmp = leaders[cursor]; + leaders[cursor] = leader; + cursor = tmp; + } + + return leader; +} + +auto LinkNodes(std::vector> const& input) +-> std::pair +{ + // Allocate leaders array and assign each node as its own leader + std::vector leaders(input.size()); + for (std::size_t i = 0; i < leaders.size(); i++) { + leaders[i] = i; + } + + // Link up all the nodes as specified in the input file + for (std::size_t i = 0; i < input.size(); i++) { + auto x_ = Find(leaders, i); + for (auto const y : input[i]) { + leaders[Find(leaders,y)] = x_; + } + } + + std::size_t part1 = 0; + std::size_t part2 = 0; + + auto target1 = Find(leaders, 0); + for (std::size_t i = 0; i < leaders.size(); i++) { + if (Find(leaders, i) == target1) part1++; + if (leaders[i] == i) part2++; + } + + return {part1, part2}; +} + +} // namespace + +TEST_SUITE("2017-12 examples") { + TEST_CASE("example") { + std::istringstream in { + "0 <-> 2\n" + "1 <-> 1\n" + "2 <-> 0, 3, 4\n" + "3 <-> 2, 4\n" + "4 <-> 2, 3, 6\n" + "5 <-> 6\n" + "6 <-> 4, 5\n"}; + auto [p1,p2] = LinkNodes(Parse(in)); + CHECK(p1 == 6); + CHECK(p2 == 2); + } +} + +auto main(int argc, char** argv) -> int { + auto input = Parse(*Startup(argc, argv)); + auto [part1, part2] = LinkNodes(input); + std::cout << "Part 1: " << part1 << std::endl; + std::cout << "Part 2: " << part2 << std::endl; +} \ No newline at end of file diff --git a/2017/CMakeLists.txt b/2017/CMakeLists.txt index 7ee3bc3..cbd2fb4 100644 --- a/2017/CMakeLists.txt +++ b/2017/CMakeLists.txt @@ -10,6 +10,9 @@ target_link_libraries(2017_10 aocpp knothash) add_executable(2017_11 11.cpp) target_link_libraries(2017_11 aocpp) +add_executable(2017_12 12.cpp) +target_link_libraries(2017_12 aocpp) + add_executable(2017_14 14.cpp) target_link_libraries(2017_14 aocpp knothash) diff --git a/lib/include/aocpp/Hex.hpp b/lib/include/aocpp/Hex.hpp new file mode 100644 index 0000000..0127c11 --- /dev/null +++ b/lib/include/aocpp/Hex.hpp @@ -0,0 +1,57 @@ +#ifndef AOCPP_HEX_HPP_ +#define AOCPP_HEX_HPP_ + +#include +#include + +namespace aocpp { +/* + \ n / +nw +--+ ne + / \ +-+ +- + \ / +sw +--+ se + / s \ +*/ + +struct Hex { + std::int64_t q, r, s; +}; + +constexpr Hex HEX_N { 0, -1, 1 }; +constexpr Hex HEX_NE { 1, -1, 0 }; +constexpr Hex HEX_SE { 1, 0, -1 }; +constexpr Hex HEX_S { 0, 1, -1 }; +constexpr Hex HEX_SW { -1, 1, 0 }; +constexpr Hex HEX_NW { -1, 0, 1 }; + +auto operator+(Hex const& a, Hex const& b) -> Hex { + return {a.q + b.q, a.r + b.r, a.s + b.s }; +} + +auto operator+=(Hex & a, Hex const& b) -> Hex & { + a.q += b.q; a.r += b.r; a.s += b.s; + return a; +} + +auto operator-(Hex const& a, Hex const& b) -> Hex { + return {a.q - b.q, a.r - b.r, a.s - b.s }; +} + +auto operator-=(Hex & a, Hex const& b) -> Hex & { + a.q -= b.q; a.r -= b.r; a.s -= b.s; + return a; +} + +auto operator-(Hex const& a) -> Hex { + return {-a.q, -a.r, -a.s }; +} + +auto hex_distance(Hex hex) -> std::int64_t { + return (std::abs(hex.q) + std::abs(hex.r) + std::abs(hex.s)) / 2; +} + +} // namespace + +#endif \ No newline at end of file