#include #include #include #include #include #include #include "VoxelSpace.h" auto backtrack_solve_iter(std::vector *polycube_input, std::vector *offsets)-> void { auto num_inputs = offsets->size() - 1; auto solns = std::vector(); auto iter_stack = std::vector(); auto curr_soln_stack = std::vector(); auto soln_spaces_stack = std::vector(); 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 *polycube_input, std::vector *offsets, uint64_t working_solution = 0ull, int set = 0) -> int { auto solns = 0; auto start = offsets->at(set); auto end = offsets->at(set + 1); 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 filter_unique(std::vector> *solutions, int dims[3]) -> std::vector> { if (solutions->size() == 0) { return std::vector>(); } auto unique_solns = std::vector>(); for (auto &solution : unique_solns) { auto foundMatch = false; auto soln_rotations = std::vector>(); for (auto &piece : solution) { auto space = Voxel::Space{ .space=solution.at(0), .dims={ dims[0], dims[1], dims[2] } }; auto unique_rots = Voxel::getUniqueRotations(&space); soln_rotations.insert(soln_rotations.end(), unique_rots.begin(), unique_rots.end()); } for (auto &rotation : soln_rotations) { auto end = unique_solns.size(); for (int i = 0; i < end; i++) { if (rotation == unique_solns[i]) { foundMatch = true; } } } if (!foundMatch) { unique_solns.push_back(solution); } } return unique_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 { 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(); 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{ 23ull, 30ull, 15ull, 43ull, 172ull, 92ull, 11ull, }; std::cout << "Great. Calculating solutions...\n"; auto offsets = std::vector(); auto polycubes = std::vector(); 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::getAllPositionsInPrism(space.space, space.dims, 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 solns = backtrack_solve(&polycubes, &offsets); std::cout << solns << std::endl; return 0; }