65 int add_block(
int pos_x,
int pos_y,
int pos_z,
int size_x,
int size_y,
int size_z,
int blockidx)
68 snprintf(buffer, 1024,
"block(%d,%d,%d,%d,%d,%d,%d);", size_x, size_y, size_z, pos_x, pos_y, pos_z, blockidx);
73 for (
int ix = pos_x; ix < pos_x+size_x; ix++)
74 for (
int iy = pos_y; iy < pos_y+size_y; iy++)
75 for (
int iz = pos_z; iz < pos_z+size_z; iz++)
76 grid[ix][iy][iz].push_back(var);
95 block_positions_124.clear();
96 for (
int size_x = 1; size_x <= 4; size_x *= 2)
97 for (
int size_y = 1; size_y <= 4; size_y *= 2)
98 for (
int size_z = 1; size_z <= 4; size_z *= 2) {
99 if (size_x == size_y || size_y == size_z || size_z == size_x)
101 for (
int ix = 0; ix <=
DIM_X-size_x; ix++)
102 for (
int iy = 0; iy <=
DIM_Y-size_y; iy++)
103 for (
int iz = 0; iz <=
DIM_Z-size_z; iz++)
104 block_positions_124.push_back(
add_block(ix, iy, iz, size_x, size_y, size_z,
blockidx++));
110 block_positions_223.clear();
111 for (
int orientation = 0; orientation < 3; orientation++) {
112 int size_x = orientation == 0 ? 3 : 2;
113 int size_y = orientation == 1 ? 3 : 2;
114 int size_z = orientation == 2 ? 3 : 2;
115 for (
int ix = 0; ix <=
DIM_X-size_x; ix++)
116 for (
int iy = 0; iy <=
DIM_Y-size_y; iy++)
117 for (
int iz = 0; iz <=
DIM_Z-size_z; iz++)
118 block_positions_223.push_back(
add_block(ix, iy, iz, size_x, size_y, size_z,
blockidx++));
125 static uint32_t x = 314159265;
134 std::map<int, std::set<int>> exclusive;
136 for (
int ix = 0; ix <
DIM_X; ix++)
137 for (
int iy = 0; iy <
DIM_Y; iy++)
138 for (
int iz = 0; iz <
DIM_Z; iz++) {
139 for (
int a :
grid[ix][iy][iz])
140 for (
int b :
grid[ix][iy][iz])
142 exclusive[a].insert(b);
145 std::vector<std::vector<int>> pools;
149 std::vector<int> candidate_pools;
150 for (
size_t i = 0; i < pools.size(); i++)
152 for (
int b : pools[i])
153 if (exclusive[a].count(b) == 0)
154 goto no_candidate_pool;
155 candidate_pools.push_back(i);
159 if (candidate_pools.size() > 0) {
160 int p = candidate_pools[
xorshift32() % candidate_pools.size()];
161 pools[p].push_back(a);
163 pools.push_back(std::vector<int>());
164 pools.back().push_back(a);
168 std::vector<int> new_vars;
169 for (
auto &pool : pools)
171 std::vector<int> formula;
175 formula.push_back(ez.
OR(ez.
NOT(a),
var));
180 new_vars.push_back(var);
183 printf(
"Condensed %d variables into %d one-hot pools.\n",
int(vars.size()),
int(new_vars.size()));
189 printf(
"\nCreating SAT encoding..\n");
192 std::vector<int> block_positions_124;
198 std::vector<int> block_positions_223;
204 for (
int ix = 0; ix <
DIM_X; ix++)
205 for (
int iy = 0; iy <
DIM_Y; iy++)
206 for (
int iz = 0; iz <
DIM_Z; iz++) {
207 assert(
grid[ix][iy][iz].size() > 0);
211 printf(
"Found %d possible block positions.\n",
int(
blockgeom.size()));
214 std::set<std::set<blockgeom_t>> symmetries;
216 bool keep_running =
true;
217 while (keep_running) {
218 keep_running =
false;
219 std::set<std::set<blockgeom_t>> old_sym;
220 old_sym.swap(symmetries);
221 for (
auto &old_sym_set : old_sym)
223 std::set<blockgeom_t> mx, my, mz;
224 std::set<blockgeom_t> rx, ry, rz;
225 for (
auto &bg : old_sym_set) {
228 bg_mx.
mirror_x(), bg_my.mirror_y(), bg_mz.mirror_z();
229 bg_rx.
rotate_x(), bg_ry.rotate_y(), bg_rz.rotate_z();
230 mx.insert(bg_mx), my.insert(bg_my), mz.insert(bg_mz);
231 rx.insert(bg_rx), ry.insert(bg_ry), rz.insert(bg_rz);
233 if (!old_sym.count(mx) || !old_sym.count(my) || !old_sym.count(mz) ||
234 !old_sym.count(rx) || !old_sym.count(ry) || !old_sym.count(rz))
236 symmetries.insert(old_sym_set);
237 symmetries.insert(mx);
238 symmetries.insert(my);
239 symmetries.insert(mz);
240 symmetries.insert(rx);
241 symmetries.insert(ry);
242 symmetries.insert(rz);
247 std::vector<std::vector<int>> vecvec;
248 for (
auto &sym : symmetries) {
249 std::vector<int> vec;
251 vec.push_back(bg.var);
252 vecvec.push_back(vec);
254 for (
size_t i = 1; i < vecvec.size(); i++)
257 printf(
"Found and eliminated %d spatial symmetries.\n",
int(symmetries.size()));
260 std::vector<int> modelExpressions;
261 std::vector<bool> modelValues;
265 modelExpressions.push_back(it.first);
268 int solution_counter = 0;
271 printf(
"\nSolving puzzle..\n");
272 bool ok = ez.
solve(modelExpressions, modelValues);
275 printf(
"No more solutions found!\n");
279 printf(
"Puzzle solution:\n");
280 std::vector<int> constraint;
281 for (
size_t i = 0; i < modelExpressions.size(); i++)
282 if (modelValues[i]) {
283 constraint.push_back(ez.
NOT(modelExpressions[i]));
284 printf(
"%s\n", blockinfo.at(modelExpressions[i]).c_str());
290 printf(
"\nFound %d distinct solutions.\n", solution_counter);
291 printf(
"Have a nice day.\n\n");
void condense_exclusives(std::vector< int > &vars)
int numCnfClauses() const
int onehot(const std::vector< int > &vec, bool max_only=false)
int numCnfVariables() const
bool solve(const std::vector< int > &modelExpressions, std::vector< bool > &modelValues, const std::vector< int > &assumptions)
std::set< blockgeom_t > blockgeom
int ordered(const std::vector< int > &vec1, const std::vector< int > &vec2, bool allow_equal=true)
std::vector< int > grid[DIM_X][DIM_Y][DIM_Z]
void add_block_positions_223(std::vector< int > &block_positions_223)
int manyhot(const std::vector< int > &vec, int min_hot, int max_hot=-1)
std::map< int, std::string > blockinfo
int expression(OpId op, int a=0, int b=0, int c=0, int d=0, int e=0, int f=0)
int OR(_V a=0, _V b=0, _V c=0, _V d=0, _V e=0, _V f=0)
bool operator<(const blockgeom_t &other) const
virtual void freeze(int id)
int add_block(int pos_x, int pos_y, int pos_z, int size_x, int size_y, int size_z, int blockidx)
void add_block_positions_124(std::vector< int > &block_positions_124)