fixing stuff

This commit is contained in:
Daniel Ledda
2025-01-03 19:21:18 +01:00
parent 3430b4e69a
commit 256292c20d
47 changed files with 3401 additions and 6901 deletions

View File

@@ -1,15 +1,11 @@
#include <bitset>
#include <span>
#include <cstdint>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include "VoxelSpace.h"
auto get_dims_input(int dims[3]) -> void {
void get_dims_input(int dims[3]) {
std::cout << "Enter dimensions separated by newlines. (x*y*z must not exceed 64)\n";
auto success = false;
bool success = false;
while (!success) {
std::cout << "x: ";
std::cin >> dims[0];
@@ -18,7 +14,7 @@ auto get_dims_input(int dims[3]) -> void {
std::cout << "z: ";
std::cin >> dims[2];
auto size = dims[0]*dims[1]*dims[2];
int size = dims[0]*dims[1]*dims[2];
if (size <= 64) {
success = true;
} else {
@@ -28,12 +24,12 @@ auto get_dims_input(int dims[3]) -> void {
}
}
auto get_reprs_input(int units_required) -> std::vector<uint64_t> {
std::vector<uint64> get_reprs_input(int units_required) {
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;
std::vector<uint64> reprs = std::vector<uint64>();
int total_units = 0;
while (true) {
auto input = std::string();
std::string input = std::string();
std::getline(std::cin, input);
if (input.size() == 0) {
if (total_units == units_required) {
@@ -44,12 +40,12 @@ auto get_reprs_input(int units_required) -> std::vector<uint64_t> {
continue;
}
}
auto bit_repr = 0ul;
auto i = 0;
auto good_repr = true;
uint64 bit_repr = 0;
int i = 0;
bool good_repr = true;
for (auto it = input.rbegin(); it < input.rend(); it++, i++) {
if (*it == '1') {
bit_repr |= 1ul << i;
bit_repr |= 1 << i;
total_units++;
} else if (*it != '0' || i >= 64) {
std::cout << "Input invalid. Enter a binary string only with max 64 bits." << '\n';
@@ -64,191 +60,189 @@ auto get_reprs_input(int units_required) -> std::vector<uint64_t> {
return reprs;
}
namespace SomaSolve {
using SomaSolution = std::vector<uint64_t>;
typedef std::vector<uint64> SomaSolution;
struct Solver {
std::vector<uint64_t>* input;
std::vector<int>* offsets;
std::vector<SomaSolution>* solutions;
};
struct Solver {
std::vector<uint64>* input;
std::vector<int>* offsets;
std::vector<SomaSolution>* solutions;
};
auto STD_SOMA = std::vector<uint64_t>{ 23ul, 30ul, 15ul, 1043ul, 24594ul, 12306ul, 11ul };
std::vector<uint64> STD_SOMA = { 23ul, 30ul, 15ul, 1043ul, 24594ul, 12306ul, 11ul };
auto backtrack_solve_iter(std::vector<uint64_t> *polycube_input, std::vector<int> *offsets)-> void {
auto num_inputs = offsets->size() - 1;
void backtrack_solve_iter(std::vector<uint64> *polycube_input, std::vector<int> *offsets) {
int num_inputs = offsets->size() - 1;
auto solns = std::vector<int>();
std::vector<int> 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(0ul);
std::vector<int> iter_stack = std::vector<int>();
std::vector<int> curr_soln_stack = std::vector<int>();
std::vector<uint64> soln_spaces_stack = std::vector<uint64>();
soln_spaces_stack.push_back(0ul);
auto depth = 0;
int 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--;
}
while (depth >= 0) {
if (depth >= iter_stack.size()) {
iter_stack.push_back(offsets->at(depth));
}
std::cout << "Done. Found " << solns.size() << " solutions." << std::endl;
}
auto backtrack_solve(Solver *solver, uint64_t working_solution = 0ul, int curr_piece = 0) -> void {
auto input = solver->input;
auto offsets = solver->offsets;
auto solutions = solver->solutions;
auto start = offsets->at(curr_piece);
auto end = offsets->at(curr_piece + 1);
auto num_pieces = offsets->size() - 1;
for (int i = start; i < end; i++) {
auto successful_fuse = !Voxel::collides(working_solution, input->at(i));
int end = offsets->at(depth + 1);
bool broke = false;
for (; iter_stack[depth] < end; iter_stack[depth]++) {
uint64 next_space = polycube_input->at(iter_stack[depth]);
uint64 soln_space = soln_spaces_stack[depth];
std::cout << next_space << " " << soln_space << std::endl;
bool successful_fuse = (soln_space | next_space) == (soln_space ^ next_space);
if (successful_fuse) {
auto new_working_solution = working_solution | input->at(i);
solutions->back().at(curr_piece) = input->at(i);
if (curr_piece == num_pieces - 1) {
auto last_soln = solutions->back();
solutions->push_back(SomaSolution(last_soln.begin(), last_soln.end()));
return;
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 {
backtrack_solve(solver, new_working_solution, curr_piece + 1);
}
}
}
if (curr_piece == 0) {
solutions->pop_back();
}
}
auto get_solution_rotations(SomaSolution *solution, int dims[3]) -> std::vector<SomaSolution> {
auto result = std::vector<SomaSolution>(Voxel::NUM_ROTS_3D);
for (int piece_i = 0; piece_i < solution->size(); piece_i++) {
auto space = Voxel::Space{
.space=solution->at(piece_i),
.dim_x=dims[0],
.dim_y=dims[1],
.dim_z=dims[2],
};
auto piece_rotations = Voxel::getAllRotations(&space);
for (int rot_i = 0; rot_i < piece_rotations.size(); rot_i++) {
result[rot_i].push_back(piece_rotations[rot_i].space);
}
}
return result;
}
auto filter_unique(std::vector<SomaSolution> *solutions, int dims[3]) -> std::vector<SomaSolution> {
if (solutions->size() == 0) {
return std::vector<SomaSolution>();
}
auto unique_solns = std::vector<SomaSolution>{};
for (auto &solution : *solutions) {
auto found_match = false;
for (auto &rotation : get_solution_rotations(&solution, dims)) {
for (auto &unique_soln : unique_solns) {
auto is_match = true;
for (int piece_i = 0; piece_i < unique_soln.size(); piece_i++) {
if (rotation[piece_i] != unique_soln[piece_i]) {
is_match = false;
break;
}
}
if (is_match) {
found_match = true;
break;
}
}
if (found_match) {
depth++;
broke = true;
break;
}
}
if (!found_match) {
unique_solns.push_back(SomaSolution(solution));
}
if (!broke) {
curr_soln_stack.pop_back();
soln_spaces_stack.pop_back();
depth--;
}
}
std::cout << "Done. Found " << solns.size() << " solutions." << std::endl;
}
void backtrack_solve(Solver *solver, uint64 working_solution = 0, int curr_piece = 0) {
std::vector<uint64> *input = solver->input;
std::vector<int> *offsets = solver->offsets;
std::vector<SomaSolution> *solutions = solver->solutions;
int start = offsets->at(curr_piece);
int end = offsets->at(curr_piece + 1);
size_t num_pieces = offsets->size() - 1;
for (int i = start; i < end; i++) {
bool successful_fuse = !collides(working_solution, input->at(i));
if (successful_fuse) {
uint64 new_working_solution = working_solution | input->at(i);
solutions->back().at(curr_piece) = input->at(i);
if (curr_piece == num_pieces - 1) {
std::vector<uint64> last_soln = solutions->back();
solutions->push_back(SomaSolution(last_soln.begin(), last_soln.end()));
return;
} else {
backtrack_solve(solver, new_working_solution, curr_piece + 1);
}
}
return unique_solns;
}
auto solve(std::vector<uint64_t> *reprs_in, int dims[3]) -> std::vector<SomaSolution> {
auto reprs = *reprs_in;
auto offsets = std::vector<int>();
auto polycubes = std::vector<uint64_t>();
polycubes.reserve(reprs.size() * 10);
auto model_space = Voxel::Space{
.space={},
.dim_x=dims[0],
.dim_y=dims[1],
.dim_z=dims[2],
};
offsets.push_back(0);
auto space = model_space;
space.space = reprs[0];
Voxel::cullEmptySpace(&space);
auto positions = Voxel::getAllPositionsInPrism(&space, dims);
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::getAllPermutationsInPrism(&space, dims);
polycubes.insert(polycubes.end(), perms.begin(), perms.end());
}
offsets.push_back(polycubes.size());
auto solutions = std::vector<SomaSolution>{std::vector<uint64_t>(reprs.size())};
auto solver = Solver{
.input=&polycubes,
.offsets=&offsets,
.solutions=&solutions,
};
backtrack_solve(&solver);
return filter_unique(solver.solutions, dims);
}
auto interactive_cmd_line_solve_soma() -> void {
int dims[3] = { 3, 3, 3 };
//get_dims_input(dims);
//std::cout << '\n';
//auto reprs = get_reprs_input(dims[0]*dims[1]*dims[2]);
std::cout << "Great. Calculating solutions...\n";
auto solutions = SomaSolve::solve(&SomaSolve::STD_SOMA, std::array<int, 3>{ 3, 3, 3 }.data());
std::cout << solutions.size() << " solutions found." << std::endl;
}
if (curr_piece == 0) {
solutions->pop_back();
}
}
std::vector<SomaSolution> get_solution_rotations(SomaSolution *solution, int dims[3]) {
std::vector<SomaSolution> result = std::vector<SomaSolution>(NUM_ROTS_3D);
for (int piece_i = 0; piece_i < solution->size(); piece_i++) {
Space space = {
solution->at(piece_i),
dims[0],
dims[1],
dims[2],
};
std::vector<Space> piece_rotations = getAllRotations(&space);
for (int rot_i = 0; rot_i < piece_rotations.size(); rot_i++) {
result[rot_i].push_back(piece_rotations[rot_i].space);
}
}
return result;
}
std::vector<SomaSolution> filter_unique(std::vector<SomaSolution> *solutions, int dims[3]) {
if (solutions->size() == 0) {
return std::vector<SomaSolution>();
}
std::vector<SomaSolution> unique_solns = std::vector<SomaSolution>{};
for (std::vector<uint64> &solution : *solutions) {
bool found_match = false;
for (SomaSolution &rotation : get_solution_rotations(&solution, dims)) {
for (auto &unique_soln : unique_solns) {
bool is_match = true;
for (int piece_i = 0; piece_i < unique_soln.size(); piece_i++) {
if (rotation[piece_i] != unique_soln[piece_i]) {
is_match = false;
break;
}
}
if (is_match) {
found_match = true;
break;
}
}
if (found_match) {
break;
}
}
if (!found_match) {
unique_solns.push_back(SomaSolution(solution));
}
}
return unique_solns;
}
std::vector<SomaSolution> solve(std::vector<uint64> *reprs_in, int dims[3]) {
std::vector<uint64> reprs = *reprs_in;
std::vector<int> offsets = std::vector<int>();
std::vector<uint64> polycubes = std::vector<uint64>();
polycubes.reserve(reprs.size() * 10);
Space model_space = {
{},
dims[0],
dims[1],
dims[2],
};
offsets.push_back(0);
Space space = model_space;
space.space = reprs[0];
cullEmptySpace(&space);
std::vector<uint64> positions = getAllPositionsInPrism(&space, dims);
polycubes.insert(polycubes.end(), positions.begin(), positions.end());
for (int i = 1; i < reprs.size(); i++) {
offsets.push_back(polycubes.size());
Space space = model_space;
space.space = reprs[i];
cullEmptySpace(&space);
std::vector<uint64> perms = getAllPermutationsInPrism(&space, dims);
polycubes.insert(polycubes.end(), perms.begin(), perms.end());
}
offsets.push_back(polycubes.size());
std::vector<SomaSolution> solutions = {std::vector<uint64>(reprs.size())};
Solver solver = {
&polycubes,
&offsets,
&solutions,
};
backtrack_solve(&solver);
return filter_unique(solver.solutions, dims);
}
void interactive_cmd_line_solve_soma() {
int dims[3] = { 3, 3, 3 };
//get_dims_input(dims);
//std::cout << '\n';
//auto reprs = get_reprs_input(dims[0]*dims[1]*dims[2]);
std::cout << "Great. Calculating solutions...\n";
std::vector<SomaSolution> solutions = solve(&STD_SOMA, dims);
std::cout << solutions.size() << " solutions found." << std::endl;
}