mostly migrated for c compatibility

This commit is contained in:
Daniel Ledda
2025-11-11 04:31:20 +01:00
parent 6958228da7
commit 344056744d
14 changed files with 3050 additions and 355 deletions

View File

@@ -1,11 +1,9 @@
#include <cstring>
#include <iostream>
#include <string>
#include <vector>
#include "VoxelSpace.h"
/*
void get_dims_input(int dims[3]) {
std::cout << "Enter dimensions separated by newlines. (x*y*z must not exceed 64)\n";
print("Enter dimensions separated by newlines. (x*y*z must not exceed 64)\n");
bool success = false;
while (!success) {
std::cout << "x: ";
@@ -19,14 +17,16 @@ void get_dims_input(int dims[3]) {
if (size <= 64) {
success = true;
} else {
std::cout << "That resulted in " << size << " units. Try again.\n";
print("That resulted in %zu units. Try again", size);
}
std::cin.ignore();
}
}
*/
/*
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";
print("Enter bit-representations (big endian, max 64 bits, total 1s must add up to %zu). press ENTER twice to finish input.\n", units_required );
std::vector<uint64> reprs = std::vector<uint64>();
int total_units = 0;
while (true) {
@@ -60,17 +60,19 @@ std::vector<uint64> get_reprs_input(int units_required) {
}
return reprs;
}
*/
typedef std::vector<uint64> SomaSolution;
typedef list<uint64> SomaSolution;
struct Solver {
typedef struct Solver {
list<uint64>* input;
list<size_t>* offsets;
std::vector<SomaSolution>* solutions;
};
list<SomaSolution>* solutions;
} Solver;
uint64 STD_SOMA[] = { 23ul, 30ul, 15ul, 1043ul, 24594ul, 12306ul, 11ul };
/*
void backtrack_solve_iter(std::vector<uint64> *polycube_input, std::vector<int> *offsets) {
size_t num_inputs = offsets->size() - 1;
@@ -118,94 +120,117 @@ 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, size_t curr_piece = 0) {
void backtrackSolve(Arena *arena, 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;
list<SomaSolution> *solutions = solver->solutions;
size_t start = offsets->data[curr_piece];
size_t end = offsets->data[curr_piece + 1];
size_t num_pieces = offsets->length - 1;
size_t num_pieces = offsets->head - 1;
for (size_t i = start; i < end; i++) {
bool successful_fuse = !collides(working_solution, input->data[i]);
if (successful_fuse) {
uint64 new_working_solution = working_solution | input->data[i];
solutions->back().at(curr_piece) = input->data[i];
solutions->data[solutions->head - 1].data[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()));
list<uint64> last_soln = solutions->data[solutions->head - 1];
list<uint64> last_soln_copy = PushList(arena, uint64, last_soln.head);
last_soln_copy.length = last_soln.head;
last_soln_copy.head = last_soln.head;
memcpy(last_soln_copy.data, last_soln.data, last_soln.head * sizeof(uint64));
appendList(solutions, last_soln_copy);
return;
} else {
backtrack_solve(solver, new_working_solution, curr_piece + 1);
backtrackSolve(arena, solver, new_working_solution, curr_piece + 1);
}
}
}
if (curr_piece == 0) {
solutions->pop_back();
}
solutions->head -= 1;
}
}
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 = {
solution->at(piece_i),
list<SomaSolution> getSolutionRotations(Arena *arena, SomaSolution *solution, int dims[3]) {
list<SomaSolution> result = PushFullList(arena, SomaSolution, NUM_ROTS_3D);
for (EachIn(result, i)) {
result.data[i] = PushList(arena, uint64, solution->head);
}
for (int piece_i = 0; piece_i < solution->head; piece_i++) {
Space space = {
solution->data[piece_i],
dims[0],
dims[1],
dims[2],
};
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);
list<Space> pieceRotations = getAllRotations(arena, &space);
for (int rot_i = 0; rot_i < pieceRotations.head; rot_i++) {
appendList(&result.data[rot_i], pieceRotations.data[rot_i].space);
}
}
return result;
}
std::vector<SomaSolution> filter_unique(Arena *arena, std::vector<SomaSolution> *solutions, int dims[3]) {
if (solutions->size() == 0) {
return std::vector<SomaSolution>();
list<SomaSolution> filterUnique(Arena *arena, list<SomaSolution> *solutions, int dims[3]) {
if (solutions->head == 0) {
return list<SomaSolution>{NULL,0,0};
}
std::vector<SomaSolution> unique_solns = std::vector<SomaSolution>{};
for (std::vector<uint64> &solution : *solutions) {
bool found_match = false;
list<SomaSolution> uniqueSolns = PushList(arena, SomaSolution, solutions->head);
for (EachIn(*solutions, i)) {
SomaSolution solution = solutions->data[i];
bool foundMatch = false;
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]) {
is_match = false;
list<SomaSolution> rots = getSolutionRotations(temp.arena, &solution, dims);
for (EachIn(rots, j)) {
SomaSolution rotation = rots.data[j];
for (EachIn(uniqueSolns, k)) {
SomaSolution unique_soln = uniqueSolns.data[k];
bool isMatch = true;
for (EachIn(unique_soln, piece_i)) {
if (rotation.data[piece_i] != unique_soln.data[piece_i]) {
isMatch = false;
break;
}
}
if (is_match) {
found_match = true;
if (isMatch) {
foundMatch = true;
break;
}
}
if (found_match) {
if (foundMatch) {
break;
}
}
scratchEnd(temp);
if (!found_match) {
unique_solns.push_back(SomaSolution(solution));
if (!foundMatch) {
SomaSolution solutionCopy = PushList(arena, uint64, solution.head);
solutionCopy.length = solution.head;
solutionCopy.head = solution.head;
memcpy(solutionCopy.data, solution.data, solution.head * sizeof(uint64));
appendList(&uniqueSolns, solutionCopy);
}
}
return unique_solns;
return uniqueSolns;
}
std::vector<SomaSolution> solve(uint64 *reprs_in, uint32 reprs_in_count, int dims[3]) {
uint64 factorial(int n) {
uint64 result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
list<SomaSolution> solve(uint64 *reprs_in, uint32 reprs_in_count, int dims[3]) {
Arena *arena = arenaAlloc(Megabytes(64));
Arena *permsArena = arenaAlloc(Megabytes(64));
Arena *permsArena = arenaAlloc(Megabytes(128));
list<size_t> offsets = PushList(arena, size_t, reprs_in_count + 1);
list<uint64> polycubes = PushList(arena, uint64, 0);
Space empty_voxel_space = {
Space empty_voxel_space = {
{},
dims[0],
dims[1],
@@ -214,12 +239,15 @@ std::vector<SomaSolution> solve(uint64 *reprs_in, uint32 reprs_in_count, int dim
appendList(&offsets, (size_t)0);
list<uint64> positions = {};
uint64 possibleCombos = 0;
{
list<uint64> positions = {};
Space space = empty_voxel_space;
space.space = reprs_in[0];
cullEmptySpace(&space);
positions = getAllPositionsInPrism(permsArena, &space, dims);
possibleCombos += positions.head;
uint64 *insertion = PushArray(arena, uint64, positions.length);
polycubes.length += positions.length;
polycubes.head += positions.head;
@@ -232,24 +260,28 @@ std::vector<SomaSolution> solve(uint64 *reprs_in, uint32 reprs_in_count, int dim
space.space = reprs_in[i];
cullEmptySpace(&space);
list<uint64> perms = getAllPermutationsInPrism(permsArena, &space, dims);
possibleCombos *= perms.head;
uint64 *insertion = PushArray(arena, uint64, perms.length);
polycubes.length += perms.length;
polycubes.head += perms.head;
memcpy(insertion, perms.data, perms.length * sizeof(uint64));
}
appendList(&offsets, polycubes.length);
appendList(&offsets, polycubes.head);
list<SomaSolution> solutions = PushList(permsArena, SomaSolution, (size_t)floor(sqrt(possibleCombos)));
SomaSolution initialSoln = PushFullList(permsArena, uint64, reprs_in_count);
appendList(&solutions, initialSoln);
std::vector<SomaSolution> solutions = {std::vector<uint64>(reprs_in_count)};
Solver solver = {
&polycubes,
&offsets,
&solutions,
};
backtrack_solve(&solver);
backtrackSolve(permsArena, &solver);
return filter_unique(arena, solver.solutions, dims);
return filterUnique(permsArena, solver.solutions, dims);
}
@@ -258,7 +290,7 @@ void interactive_cmd_line_solve_soma() {
//get_dims_input(dims);
//std::cout << '\n';
//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, ArrayCount(STD_SOMA), dims);
std::cout << solutions.size() << " solutions found." << std::endl;
print("Great. Calculating solutions...\n");
list<SomaSolution> solutions = solve(STD_SOMA, ArrayCount(STD_SOMA), dims);
print("%zu solutions found.\n", solutions.head);
}