This commit is contained in:
Daniel Ledda
2025-01-04 22:51:33 +01:00
parent 50f4501c86
commit 2daee71548
11 changed files with 277 additions and 245 deletions

View File

@@ -1,7 +1,9 @@
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include "VoxelSpace.h"
#include "lib/djstdlib/core.h"
void get_dims_input(int dims[3]) {
std::cout << "Enter dimensions separated by newlines. (x*y*z must not exceed 64)\n";
@@ -43,7 +45,7 @@ std::vector<uint64> get_reprs_input(int units_required) {
uint64 bit_repr = 0;
int i = 0;
bool good_repr = true;
for (auto it = input.rbegin(); it < input.rend(); it++, i++) {
for (std::reverse_iterator it = input.rbegin(); it < input.rend(); it++, i++) {
if (*it == '1') {
bit_repr |= 1 << i;
total_units++;
@@ -63,12 +65,12 @@ std::vector<uint64> get_reprs_input(int units_required) {
typedef std::vector<uint64> SomaSolution;
struct Solver {
std::vector<uint64>* input;
std::vector<int>* offsets;
list<uint64>* input;
list<size_t>* offsets;
std::vector<SomaSolution>* solutions;
};
std::vector<uint64> STD_SOMA = { 23ul, 30ul, 15ul, 1043ul, 24594ul, 12306ul, 11ul };
uint64 STD_SOMA[] = { 23ul, 30ul, 15ul, 1043ul, 24594ul, 12306ul, 11ul };
void backtrack_solve_iter(std::vector<uint64> *polycube_input, std::vector<int> *offsets) {
int num_inputs = offsets->size() - 1;
@@ -118,18 +120,18 @@ void backtrack_solve_iter(std::vector<uint64> *polycube_input, std::vector<int>
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;
void backtrack_solve(Solver *solver, uint64 working_solution = 0, size_t curr_piece = 0) {
list<uint64> *input = solver->input;
list<size_t> *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;
int start = offsets->data[curr_piece];
int end = offsets->data[curr_piece + 1];
size_t num_pieces = offsets->length - 1;
for (int i = start; i < end; i++) {
bool successful_fuse = !collides(working_solution, input->at(i));
bool successful_fuse = !collides(working_solution, input->data[i]);
if (successful_fuse) {
uint64 new_working_solution = working_solution | input->at(i);
solutions->back().at(curr_piece) = input->at(i);
uint64 new_working_solution = working_solution | input->data[i];
solutions->back().at(curr_piece) = input->data[i];
if (curr_piece == num_pieces - 1) {
std::vector<uint64> last_soln = solutions->back();
solutions->push_back(SomaSolution(last_soln.begin(), last_soln.end()));
@@ -144,7 +146,7 @@ void backtrack_solve(Solver *solver, uint64 working_solution = 0, int curr_piece
}
}
std::vector<SomaSolution> get_solution_rotations(SomaSolution *solution, int dims[3]) {
std::vector<SomaSolution> get_solution_rotations(Arena *arena, 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 = {
@@ -153,23 +155,25 @@ std::vector<SomaSolution> get_solution_rotations(SomaSolution *solution, int dim
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);
list<Space> piece_rotations = getAllRotations(arena, &space);
for (int rot_i = 0; rot_i < piece_rotations.length; rot_i++) {
result[rot_i].push_back(piece_rotations.data[rot_i].space);
}
}
return result;
}
std::vector<SomaSolution> filter_unique(std::vector<SomaSolution> *solutions, int dims[3]) {
std::vector<SomaSolution> filter_unique(Arena *arena, 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) {
Scratch temp = scratchStart(&arena, 1);
std::vector<SomaSolution> rots = get_solution_rotations(temp.arena, &solution, dims);
for (SomaSolution &rotation : rots) {
for (std::vector<uint64> &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]) {
@@ -186,6 +190,7 @@ std::vector<SomaSolution> filter_unique(std::vector<SomaSolution> *solutions, in
break;
}
}
scratchEnd(temp);
if (!found_match) {
unique_solns.push_back(SomaSolution(solution));
}
@@ -193,11 +198,13 @@ std::vector<SomaSolution> filter_unique(std::vector<SomaSolution> *solutions, in
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);
std::vector<SomaSolution> solve(uint64 *reprs_in, uint32 reprs_in_count, int dims[3]) {
Arena *arena = arenaAlloc(Megabytes(64));
Arena *permsArena = arenaAlloc(Megabytes(64));
list<size_t> offsets = PushList(arena, size_t, reprs_in_count + 1);
list<uint64> polycubes = PushList(arena, uint64, 0);
Space model_space = {
{},
@@ -206,25 +213,29 @@ std::vector<SomaSolution> solve(std::vector<uint64> *reprs_in, int dims[3]) {
dims[2],
};
offsets.push_back(0);
appendList(&offsets, 0ul);
Space space = model_space;
space.space = reprs[0];
space.space = reprs_in[0];
cullEmptySpace(&space);
std::vector<uint64> positions = getAllPositionsInPrism(&space, dims);
polycubes.insert(polycubes.end(), positions.begin(), positions.end());
list<uint64> positions = getAllPositionsInPrism(arena, &space, dims);
polycubes.length += positions.length;
polycubes.head += positions.head;
memcpy(polycubes.data, positions.data, positions.length / sizeof(uint64));
for (int i = 1; i < reprs.size(); i++) {
offsets.push_back(polycubes.size());
for (int i = 1; i < reprs_in_count; i++) {
appendList(&offsets, polycubes.length);
Space space = model_space;
space.space = reprs[i];
space.space = reprs_in[i];
cullEmptySpace(&space);
std::vector<uint64> perms = getAllPermutationsInPrism(&space, dims);
polycubes.insert(polycubes.end(), perms.begin(), perms.end());
list<uint64> perms = getAllPermutationsInPrism(permsArena, &space, dims);
polycubes.length += positions.length;
polycubes.head += positions.head;
memcpy(polycubes.data + polycubes.length, perms.data, perms.length / sizeof(uint64));
}
offsets.push_back(polycubes.size());
appendList(&offsets, polycubes.length);
std::vector<SomaSolution> solutions = {std::vector<uint64>(reprs.size())};
std::vector<SomaSolution> solutions = {std::vector<uint64>(reprs_in_count)};
Solver solver = {
&polycubes,
&offsets,
@@ -233,7 +244,7 @@ std::vector<SomaSolution> solve(std::vector<uint64> *reprs_in, int dims[3]) {
backtrack_solve(&solver);
return filter_unique(solver.solutions, dims);
return filter_unique(arena, solver.solutions, dims);
}
@@ -241,8 +252,8 @@ 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::vector<uint64> 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::vector<SomaSolution> solutions = solve(STD_SOMA, ArrayCount(STD_SOMA), dims);
std::cout << solutions.size() << " solutions found." << std::endl;
}