From 551df7ffb279aed590c6371d4ec6a397e3705e2f Mon Sep 17 00:00:00 2001 From: Thraix Date: Fri, 4 Sep 2026 19:41:32 +0200 Subject: [PATCH] Add solution for 2016 Day 24 --- res/2016/day24/test_input.txt | 5 +++ src/2016/Day24.cpp | 69 +++++++++++++++++++++++++++++------ src/common/lib/Graph.h | 5 +++ src/common/lib/Helper.h | 48 +++++++++++++----------- 4 files changed, 94 insertions(+), 33 deletions(-) diff --git a/res/2016/day24/test_input.txt b/res/2016/day24/test_input.txt index e69de29..628e51b 100644 --- a/res/2016/day24/test_input.txt +++ b/res/2016/day24/test_input.txt @@ -0,0 +1,5 @@ +########### +#0.1.....2# +#.#######.# +#4.......3# +########### diff --git a/src/2016/Day24.cpp b/src/2016/Day24.cpp index 1b4fbfb..f7ac7f4 100644 --- a/src/2016/Day24.cpp +++ b/src/2016/Day24.cpp @@ -2,30 +2,77 @@ namespace y2016::day24 { - REGISTER_DAY(2016, Day24, std::vector, int); + REGISTER_DAY(2016, Day24, Array2D, int); - REGISTER_TEST_EXAMPLE(2016, Day24, ExampleInput, 1, 0); - REGISTER_TEST(2016, Day24, Input, 1, 0); - REGISTER_TEST_EXAMPLE(2016, Day24, ExampleInput, 2, 0); - REGISTER_TEST(2016, Day24, Input, 2, 0); + REGISTER_TEST_EXAMPLE(2016, Day24, ExampleInput, 1, 14); + REGISTER_TEST(2016, Day24, Input, 1, 448); + REGISTER_TEST_EXAMPLE(2016, Day24, ExampleInput, 2, 20); + REGISTER_TEST(2016, Day24, Input, 2, 672); READ_INPUT(input) { - std::vector vec; - std::string str; - while (getline(input, str)) + return Input::ReadArray2D(input); + } + + struct State + { + Index2D pos; + char goalChar; + + bool operator<(const State& other) const { + return pos < other.pos; } - return vec; + }; + + std::vector> Branch(const Array2D& map, const State& state) + { + std::vector> branches; + for (const auto& pos : map.GetNeighbors(state.pos, false)) + { + if (map[pos] != '#') + branches.emplace_back(1, State{pos, state.goalChar}); + } + return branches; + } + + bool Goal(const Array2D& map, const State& state) + { + return map[state.pos] == state.goalChar; + } + + Graph GetGraph(const Array2D& map) + { + std::vector positions(10); + for (auto it = map.begin(); it != map.end(); it++) + { + if (*it >= '0' && *it <= '9') + { + positions[*it - '0'] = it.index; + } + } + while (!positions.back().IsValid()) + positions.pop_back(); + + Graph graph; + for (size_t i = 0; i < positions.size(); i++) + { + for (size_t j = i + 1; j < positions.size(); j++) + { + int distance = Helper::Dijkstras(map, State{positions[i], (char)(j + '0')}, Branch, Goal); + graph.AddTwoWayEdge(i + '0', j + '0', distance); + } + } + return graph; } OUTPUT1(input) { - return 0; + return Helper::TSP(GetGraph(input), '0', false); } OUTPUT2(input) { - return 0; + return Helper::TSP(GetGraph(input), '0', true); } } diff --git a/src/common/lib/Graph.h b/src/common/lib/Graph.h index 92d1e17..88fb2d5 100644 --- a/src/common/lib/Graph.h +++ b/src/common/lib/Graph.h @@ -106,6 +106,11 @@ public: return graph.find(from)->second.find(to)->second; } + const std::map>& GetGraph() const + { + return graph; + } + const std::map& GetPaths(const Key& from) const { return graph.find(from)->second; diff --git a/src/common/lib/Helper.h b/src/common/lib/Helper.h index df2d321..195b996 100644 --- a/src/common/lib/Helper.h +++ b/src/common/lib/Helper.h @@ -506,17 +506,29 @@ struct Helper static void ResetTraceErrors(); private: - template + template + static Value TSPCalculatePath(const Graph& graph, const std::vector& path, bool returnToStart) + { + int cost = 0; + for (int i = 0; i < path.size() - 1; i++) + { + cost += graph.GetEdge(path[i], path[i + 1]); + } + + if (returnToStart) + cost += graph.GetEdge(path.back(), path.front()); + + return cost; + } + + template static int TSP(const Graph& graph, const std::set& nodesLeft, const std::vector& order, - Compare compare, - Eval eval) + bool returnToStart) { if (nodesLeft.empty()) - { - return eval(graph, order); - } + return TSPCalculatePath(graph, order, returnToStart); bool hasSet = false; Value tsp; @@ -528,9 +540,9 @@ private: std::vector newOrder = order; newOrder.emplace_back(node); if (hasSet) - tsp = compare(tsp, TSP(graph, newNodesLeft, newOrder, compare, eval)); + tsp = std::min(tsp, TSP(graph, newNodesLeft, newOrder, returnToStart)); else - tsp = TSP(graph, newNodesLeft, newOrder, compare, eval); + tsp = TSP(graph, newNodesLeft, newOrder, returnToStart); hasSet = true; } return tsp; @@ -539,28 +551,20 @@ private: public: // Key - Node type of the graph // Value - Edge type of the graph - // Compare - Value(Value, Value) - // Given two solutions, which one is better - // Eval - int(const Graph&, const std::vector&) - // Given the graph and order of the TSP, what is the total cost - template - static int TSP(const Graph& graph, const Key& start, Compare compare, Eval eval) + template + static int TSP(const Graph& graph, const Key& start, bool returnToStart) { std::set nodes = graph.GetNodes(); nodes.erase(nodes.find(start)); - return TSP(graph, nodes, std::vector{start}, compare, eval); + return TSP(graph, nodes, std::vector{start}, returnToStart); } // Key - Node type of the graph // Value - Edge type of the graph - // Compare - Value(Value, Value) - // Given two solutions, which one is better - // Eval - int(const Graph&, const std::vector&) - // Given the graph and order of the TSP, what is the total cost - template - static int TSP(const Graph& graph, Compare compare, Eval eval) + template + static int TSP(const Graph& graph, bool returnToStart) { - return TSP(graph, graph.GetNodes(), std::vector{}, compare, eval); + return TSP(graph, graph.GetNodes(), std::vector{}, returnToStart); } static bool traceErrors;