From f1116a8bb7216dea85d04648c2540014936fd7b1 Mon Sep 17 00:00:00 2001 From: Joshua Moerman Date: Tue, 4 Mar 2014 14:38:13 +0100 Subject: [PATCH] splits data from algorithms --- include/analyzed_grid.hpp | 16 +--------- include/data.hpp | 67 +++++++++++++++++++++++++++++++++++++++ include/dynamic_grid.hpp | 24 ++------------ include/rules.hpp | 19 +++++------ include/solver.hpp | 27 ++++++++-------- lib/dynamic_grid.cpp | 2 +- src/generate.cpp | 10 +++--- src/replay.cpp | 6 ++-- 8 files changed, 102 insertions(+), 69 deletions(-) create mode 100644 include/data.hpp diff --git a/include/analyzed_grid.hpp b/include/analyzed_grid.hpp index 6e02b3b..d08a637 100644 --- a/include/analyzed_grid.hpp +++ b/include/analyzed_grid.hpp @@ -1,29 +1,15 @@ #pragma once +#include "data.hpp" #include "dynamic_grid.hpp" #include "solver.hpp" #include "rules.hpp" #include #include -#include #include -template -struct AnalyzedGrid { - Grid grid; - Solution analysis; - BasicRules rules; - -private: - friend class boost::serialization::access; - template - void serialize(Archive & ar, const unsigned int /*version*/){ - ar & grid & analysis.solution_traces; - } -}; - inline auto grid_from_file(std::string file_path){ std::ifstream file(file_path); boost::archive::text_iarchive ar(file); diff --git a/include/data.hpp b/include/data.hpp new file mode 100644 index 0000000..891fb79 --- /dev/null +++ b/include/data.hpp @@ -0,0 +1,67 @@ +#pragma once + +#include +#include +#include +#include + +struct BasicRulesBase { + unsigned int min_size; + +private: + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int /*version*/){ + ar & min_size; + } +}; + +template +struct Solutions { + using Trace = std::vector; + std::vector traces; + +private: + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int /*version*/){ + ar & traces; + } +}; + +template +struct AnalyzedGrid { + Grid grid; + Solutions solutions; + BasicRulesBase rules; + +private: + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int /*version*/){ + ar & grid & solutions & rules; + } +}; + +struct DynamicGridBase { + using Position = std::pair; + + int W; + int H; + std::vector grid; + std::vector positions; + + DynamicGridBase() = default; + DynamicGridBase(int width, int height, std::vector && data) + : W(width), H(height), grid(std::move(data)) + {} + +private: + friend class boost::serialization::access; + template + void serialize(Archive & ar, const unsigned int /*version*/){ + ar & W & H & grid & positions; + // archiving positions is redundant (I'm being lazy here) + // consider make_nvp for readable json + } +}; diff --git a/include/dynamic_grid.hpp b/include/dynamic_grid.hpp index ef9c71c..c76348e 100644 --- a/include/dynamic_grid.hpp +++ b/include/dynamic_grid.hpp @@ -1,10 +1,7 @@ #pragma once #include "utilities.hpp" - -#include -#include -#include +#include "data.hpp" #include #include @@ -16,8 +13,8 @@ // Position {0,0} is bottom left. // Position {W-1, H-1} is top right. // template -struct DynamicGrid{ - using Position = std::pair; +struct DynamicGrid : public DynamicGridBase { + using Position = DynamicGridBase::Position; DynamicGrid(int width, int height, std::vector && data); @@ -74,11 +71,6 @@ struct DynamicGrid{ size_t hash() const; private: - int W; - int H; - std::vector grid; - std::vector positions; - //! \brief Single vertical collapsing step auto vcollapse(); @@ -87,16 +79,6 @@ private: //! \brief Returns true if the whole column at x is empty auto empty_column(int x); - - friend class boost::serialization::access; - - //! \brief Serializes the grid - template - void serialize(Archive & ar, const unsigned int /*version*/){ - ar & W & H & grid & positions; - // archiving positions is redundant (I'm being lazy here) - // consider make_nvp for readable json - } }; template diff --git a/include/rules.hpp b/include/rules.hpp index b9f9d9f..7d76195 100644 --- a/include/rules.hpp +++ b/include/rules.hpp @@ -1,9 +1,15 @@ #pragma once -struct BasicRules { +#include "data.hpp" + +struct BasicRules : public BasicRulesBase { BasicRules() = default; BasicRules(unsigned int minimal_cluster_size) - : min_size(minimal_cluster_size) + : BasicRulesBase{minimal_cluster_size} + {} + + BasicRules(BasicRulesBase base) + : BasicRulesBase(base) {} auto min_cluster_size() const { @@ -13,13 +19,4 @@ struct BasicRules { auto same_cluster(int x, int y) const { return x == y; } - -private: - unsigned int min_size; - - friend class boost::serialization::access; - template - void serialize(Archive & ar, const unsigned int /*version*/){ - ar & min_size; - } }; diff --git a/include/solver.hpp b/include/solver.hpp index 5456deb..95a15ca 100644 --- a/include/solver.hpp +++ b/include/solver.hpp @@ -1,13 +1,13 @@ #pragma once +#include "data.hpp" #include "clusters.hpp" #include template -struct Solution { - using Trace = std::vector; - Trace current_trace; - std::vector solution_traces; +struct State { + using Trace = typename Solutions::Trace; + Trace trace; // current trace being considered }; template @@ -16,10 +16,10 @@ auto pop(std::vector & v){ } template -auto solve_impl(Grid const & grid, Rules const & rules, Solution & s){ +auto solve_impl(Grid const & grid, Rules const & rules, State & state, Solutions & solutions){ if(grid.empty()){ // solved path - s.solution_traces.push_back(s.current_trace); + solutions.traces.push_back(state.trace); return; } @@ -31,22 +31,23 @@ auto solve_impl(Grid const & grid, Rules const & rules, Solution & s){ for(auto&& c : clusters){ // remove the cluster - s.current_trace.push_back(*c.begin()); + state.trace.push_back(*c.begin()); auto new_grid = make_empty(grid, c); // recurse - solve_impl(new_grid, rules, s); + solve_impl(new_grid, rules, state, solutions); // go on with next cluster - pop(s.current_trace); + pop(state.trace); } return; } template auto solve(Grid const & grid, Rules const & rules){ - Solution s; - s.current_trace.reserve(10); - solve_impl(grid, rules, s); - return s; + Solutions solutions; + State state; + state.trace.reserve(10); + solve_impl(grid, rules, state, solutions); + return solutions; } diff --git a/lib/dynamic_grid.cpp b/lib/dynamic_grid.cpp index 55b4283..e74b80c 100644 --- a/lib/dynamic_grid.cpp +++ b/lib/dynamic_grid.cpp @@ -14,7 +14,7 @@ static auto all_positions_impl(int W, int H) { } DynamicGrid::DynamicGrid(int width, int height, std::vector && data) -: W(width), H(height), grid(std::move(data)) { +: DynamicGridBase(width, height, std::move(data)) { assert(grid.size() == W*H); positions = all_positions_impl(W, H); } diff --git a/src/generate.cpp b/src/generate.cpp index 2095357..02831d0 100644 --- a/src/generate.cpp +++ b/src/generate.cpp @@ -51,25 +51,25 @@ int main(int argc, char** argv){ unsigned int unsolvable = 0; while(n--){ auto field = random_dynamic_grid(w, h, c, gen); - auto solution = solve(field, rules); + auto solutions = solve(field, rules); - if(!solution.solution_traces.empty()){ + if(!solutions.traces.empty()){ ++solvable; } else { ++unsolvable; } - std::string s = solution.solution_traces.empty() ? "u" : "s"; + std::string s = solutions.traces.empty() ? "u" : "s"; std::string filename = "levels/" + std::to_string(w) + "_" + std::to_string(h) + "_" + std::to_string(c) + "_" + s + "_" + std::to_string(field.hash()) + ".lvl"; if(verbose){ std::cout << "= Puzzle " << n << " =\n"; field.print(std::cout); - std::cout << solution.solution_traces.size() << " solutions\n"; + std::cout << solutions.traces.size() << " solutions\n"; std::cout << filename << "\n\n"; } - grid_to_file({std::move(field), std::move(solution), rules}, filename); + grid_to_file({std::move(field), std::move(solutions), rules}, filename); } std::cout << solvable << " solvable (= " << 100 * solvable / double(solvable + unsolvable) << "%)\n"; diff --git a/src/replay.cpp b/src/replay.cpp index 811157d..6962025 100644 --- a/src/replay.cpp +++ b/src/replay.cpp @@ -32,10 +32,10 @@ int main(int argc, char** argv){ std::cout << "= The puzzle =\n"; auto level = grid_from_file(vm["file"].as()); level.grid.print(std::cout); - std::cout << "has " << level.analysis.solution_traces.size() << " solutions\n\n"; + std::cout << "has " << level.solutions.traces.size() << " solutions\n\n"; int count = 1; - for(auto && solution : level.analysis.solution_traces){ + for(auto && solution : level.solutions.traces){ std::cout << "= Solution " << count++ << " =\n"; auto grid = level.grid; @@ -43,7 +43,7 @@ int main(int argc, char** argv){ for(auto && tap : solution){ std::cout << "Tapping on " << tap.first << ", " << tap.second << " => \n"; - grid = make_empty(grid, cluster_at(grid, level.rules, tap)); + grid = make_empty(grid, cluster_at(grid, BasicRules{level.rules}, tap)); grid.print(std::cout); } }