1
Fork 0

splits data from algorithms

This commit is contained in:
Joshua Moerman 2014-03-04 14:38:13 +01:00
parent 570bc18976
commit f1116a8bb7
8 changed files with 102 additions and 69 deletions

View file

@ -1,29 +1,15 @@
#pragma once
#include "data.hpp"
#include "dynamic_grid.hpp"
#include "solver.hpp"
#include "rules.hpp"
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/serialization.hpp>
#include <fstream>
template <typename Grid>
struct AnalyzedGrid {
Grid grid;
Solution<Grid> analysis;
BasicRules rules;
private:
friend class boost::serialization::access;
template<class Archive>
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);

67
include/data.hpp Normal file
View file

@ -0,0 +1,67 @@
#pragma once
#include <boost/serialization/vector.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/serialization.hpp>
#include <vector>
struct BasicRulesBase {
unsigned int min_size;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int /*version*/){
ar & min_size;
}
};
template <typename Grid>
struct Solutions {
using Trace = std::vector<typename Grid::Position>;
std::vector<Trace> traces;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int /*version*/){
ar & traces;
}
};
template <typename Grid>
struct AnalyzedGrid {
Grid grid;
Solutions<Grid> solutions;
BasicRulesBase rules;
private:
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int /*version*/){
ar & grid & solutions & rules;
}
};
struct DynamicGridBase {
using Position = std::pair<int, int>;
int W;
int H;
std::vector<int> grid;
std::vector<Position> positions;
DynamicGridBase() = default;
DynamicGridBase(int width, int height, std::vector<int> && data)
: W(width), H(height), grid(std::move(data))
{}
private:
friend class boost::serialization::access;
template<class Archive>
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
}
};

View file

@ -1,10 +1,7 @@
#pragma once
#include "utilities.hpp"
#include <boost/serialization/vector.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/serialization.hpp>
#include "data.hpp"
#include <cassert>
#include <utility>
@ -16,8 +13,8 @@
// Position {0,0} is bottom left.
// Position {W-1, H-1} is top right.
// template <typename T>
struct DynamicGrid{
using Position = std::pair<int, int>;
struct DynamicGrid : public DynamicGridBase {
using Position = DynamicGridBase::Position;
DynamicGrid(int width, int height, std::vector<int> && data);
@ -74,11 +71,6 @@ struct DynamicGrid{
size_t hash() const;
private:
int W;
int H;
std::vector<int> grid;
std::vector<Position> 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<class Archive>
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 <typename URNG>

View file

@ -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<class Archive>
void serialize(Archive & ar, const unsigned int /*version*/){
ar & min_size;
}
};

View file

@ -1,13 +1,13 @@
#pragma once
#include "data.hpp"
#include "clusters.hpp"
#include <vector>
template <typename Grid>
struct Solution {
using Trace = std::vector<typename Grid::Position>;
Trace current_trace;
std::vector<Trace> solution_traces;
struct State {
using Trace = typename Solutions<Grid>::Trace;
Trace trace; // current trace being considered
};
template <typename T>
@ -16,10 +16,10 @@ auto pop(std::vector<T> & v){
}
template <typename Grid, typename Rules>
auto solve_impl(Grid const & grid, Rules const & rules, Solution<Grid> & s){
auto solve_impl(Grid const & grid, Rules const & rules, State<Grid> & state, Solutions<Grid> & 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<Grid> & 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 <typename Grid, typename Rules>
auto solve(Grid const & grid, Rules const & rules){
Solution<Grid> s;
s.current_trace.reserve(10);
solve_impl(grid, rules, s);
return s;
Solutions<Grid> solutions;
State<Grid> state;
state.trace.reserve(10);
solve_impl(grid, rules, state, solutions);
return solutions;
}

View file

@ -14,7 +14,7 @@ static auto all_positions_impl(int W, int H) {
}
DynamicGrid::DynamicGrid(int width, int height, std::vector<int> && 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);
}

View file

@ -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";

View file

@ -32,10 +32,10 @@ int main(int argc, char** argv){
std::cout << "= The puzzle =\n";
auto level = grid_from_file(vm["file"].as<std::string>());
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);
}
}