183 lines
5.9 KiB
C++
183 lines
5.9 KiB
C++
#include <bitset>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include "VoxelSpace.h"
|
|
|
|
auto backtrack_solve_iter(std::vector<uint64_t> *polycube_input, std::vector<int> *offsets)-> void {
|
|
auto num_inputs = offsets->size() - 1;
|
|
|
|
auto solns = std::vector<int>();
|
|
|
|
auto iter_stack = std::vector<int>();
|
|
auto curr_soln_stack = std::vector<int>();
|
|
auto soln_spaces_stack = std::vector<uint64_t>();
|
|
soln_spaces_stack.push_back(0ull);
|
|
|
|
auto depth = 0;
|
|
|
|
while (depth >= 0) {
|
|
if (depth >= iter_stack.size()) {
|
|
iter_stack.push_back(offsets->at(depth));
|
|
}
|
|
auto end = offsets->at(depth + 1);
|
|
auto broke = false;
|
|
for (; iter_stack[depth] < end; iter_stack[depth]++) {
|
|
auto next_space = polycube_input->at(iter_stack[depth]);
|
|
auto soln_space = soln_spaces_stack[depth];
|
|
std::cout << next_space << " " << soln_space << std::endl;
|
|
auto successful_fuse = (soln_space | next_space) == (soln_space ^ next_space);
|
|
if (successful_fuse) {
|
|
soln_spaces_stack.push_back(soln_space |= next_space);
|
|
curr_soln_stack.push_back(iter_stack[depth]);
|
|
depth++;
|
|
if (curr_soln_stack.size() == num_inputs) {
|
|
solns.push_back(1);
|
|
curr_soln_stack.pop_back();
|
|
soln_spaces_stack.pop_back();
|
|
depth--;
|
|
} else {
|
|
depth++;
|
|
auto broke = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!broke) {
|
|
curr_soln_stack.pop_back();
|
|
soln_spaces_stack.pop_back();
|
|
depth--;
|
|
}
|
|
}
|
|
std::cout << "Done. Found " << solns.size() << " solutions." << std::endl;
|
|
}
|
|
|
|
auto backtrack_solve(std::vector<uint64_t> *polycube_input, std::vector<int> *offsets, uint64_t working_solution = 0ull, int set = 0) -> int {
|
|
auto solns = 0;
|
|
auto start = offsets->at(set);
|
|
auto end = offsets->at(set + 1);
|
|
std::cout << start << " " << end << "\n";
|
|
for (int i = start; i < end; i++) {
|
|
auto successful_fuse = !Voxel::collides(working_solution, polycube_input->at(i));
|
|
if (successful_fuse) {
|
|
working_solution = working_solution | polycube_input->at(i);
|
|
if (set == offsets->size() - 2) {
|
|
return solns + 1;
|
|
} else {
|
|
solns += backtrack_solve(polycube_input, offsets, working_solution, set + 1);
|
|
}
|
|
}
|
|
}
|
|
return solns;
|
|
}
|
|
|
|
auto get_dims_input(int dims[3]) -> void {
|
|
std::cout << "Enter dimensions separated by newlines. (x*y*z must not exceed 64)\n";
|
|
auto success = false;
|
|
while (!success) {
|
|
std::cout << "x: ";
|
|
std::cin >> dims[0];
|
|
std::cout << "y: ";
|
|
std::cin >> dims[1];
|
|
std::cout << "z: ";
|
|
std::cin >> dims[2];
|
|
|
|
auto size = dims[0]*dims[1]*dims[2];
|
|
if (size <= 64) {
|
|
success = true;
|
|
} else {
|
|
std::cout << "That resulted in " << size << " units. Try again.\n";
|
|
}
|
|
std::cin.ignore();
|
|
}
|
|
}
|
|
|
|
auto get_reprs_input(int units_required) -> std::vector<uint64_t> {
|
|
std::cout << "Enter bit-representations (big endian, max 64 bits, total 1s must add up to " << units_required << "). press ENTER twice to finish input.\n";
|
|
auto reprs = std::vector<uint64_t>();
|
|
auto total_units = 0;
|
|
while (true) {
|
|
auto input = std::string();
|
|
std::getline(std::cin, input);
|
|
if (input.size() == 0) {
|
|
if (total_units == units_required) {
|
|
break;
|
|
} else {
|
|
std::cout << "Bad number of units. You entered: " << total_units << ", but exactly " << units_required << " were required.\n";
|
|
total_units = 0;
|
|
continue;
|
|
}
|
|
}
|
|
auto bit_repr = 0ull;
|
|
auto i = 0;
|
|
auto good_repr = true;
|
|
for (auto it = input.rbegin(); it < input.rend(); it++, i++) {
|
|
if (*it == '1') {
|
|
bit_repr |= 1ull << i;
|
|
total_units++;
|
|
} else if (*it != '0' || i >= 64) {
|
|
std::cout << "Input invalid. Enter a binary string only with max 64 bits." << '\n';
|
|
good_repr = false;
|
|
break;
|
|
}
|
|
}
|
|
if (good_repr) {
|
|
reprs.push_back(bit_repr);
|
|
}
|
|
}
|
|
return reprs;
|
|
}
|
|
|
|
auto main() -> int {
|
|
int dims[3] = { 3, 3, 3 };
|
|
//get_dims_input(dims);
|
|
std::cout << '\n';
|
|
//auto reprs = get_reprs_input(dims[0]*dims[1]*dims[2]);
|
|
auto reprs = std::vector<uint64_t>{
|
|
23ull,
|
|
30ull,
|
|
15ull,
|
|
43ull,
|
|
172ull,
|
|
92ull,
|
|
11ull,
|
|
};
|
|
std::cout << "Great. Calculating solutions...\n";
|
|
|
|
auto offsets = std::vector<int>();
|
|
auto polycubes = std::vector<Voxel::Space>();
|
|
polycubes.reserve(reprs.size() * 10);
|
|
|
|
auto model_space = Voxel::Space{
|
|
.space={},
|
|
.dims={dims[0], dims[1], dims[2]},
|
|
};
|
|
|
|
offsets.push_back(polycubes.size());
|
|
auto space = model_space;
|
|
space.space = reprs[0];
|
|
Voxel::cullEmptySpace(&space);
|
|
auto positions = Voxel::getUniqueRotations(&space);
|
|
polycubes.insert(polycubes.end(), positions.begin(), positions.end());
|
|
|
|
for (int i = 1; i < reprs.size(); i++) {
|
|
offsets.push_back(polycubes.size());
|
|
auto space = model_space;
|
|
space.space = reprs[i];
|
|
Voxel::cullEmptySpace(&space);
|
|
auto perms = Voxel::getUniqueRotations(&space);
|
|
polycubes.insert(polycubes.end(), perms.begin(), perms.end());
|
|
}
|
|
|
|
offsets.push_back(polycubes.size());
|
|
|
|
auto spaces = std::vector<uint64_t>(polycubes.size());
|
|
std::transform(polycubes.begin(), polycubes.end(), spaces.begin(), [](auto i) { return i.space; });
|
|
|
|
auto solns = backtrack_solve(&spaces, &offsets);
|
|
|
|
std::cout << solns << std::endl;
|
|
return 0;
|
|
}
|