creating office shelf
This commit is contained in:
parent
3461ab5570
commit
06d1d3474a
34 changed files with 551 additions and 0 deletions
74
OfficeShelf/zuschnitt_cpp/zuscnitt/.gitignore
vendored
Normal file
74
OfficeShelf/zuschnitt_cpp/zuscnitt/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
# This file is used to ignore files which are generated
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
*.a
|
||||
*.core
|
||||
*.moc
|
||||
*.o
|
||||
*.obj
|
||||
*.orig
|
||||
*.rej
|
||||
*.so
|
||||
*.so.*
|
||||
*_pch.h.cpp
|
||||
*_resource.rc
|
||||
*.qm
|
||||
.#*
|
||||
*.*#
|
||||
core
|
||||
!core/
|
||||
tags
|
||||
.DS_Store
|
||||
.directory
|
||||
*.debug
|
||||
Makefile*
|
||||
*.prl
|
||||
*.app
|
||||
moc_*.cpp
|
||||
ui_*.h
|
||||
qrc_*.cpp
|
||||
Thumbs.db
|
||||
*.res
|
||||
*.rc
|
||||
/.qmake.cache
|
||||
/.qmake.stash
|
||||
|
||||
# qtcreator generated files
|
||||
*.pro.user*
|
||||
CMakeLists.txt.user*
|
||||
|
||||
# xemacs temporary files
|
||||
*.flc
|
||||
|
||||
# Vim temporary files
|
||||
.*.swp
|
||||
|
||||
# Visual Studio generated files
|
||||
*.ib_pdb_index
|
||||
*.idb
|
||||
*.ilk
|
||||
*.pdb
|
||||
*.sln
|
||||
*.suo
|
||||
*.vcproj
|
||||
*vcproj.*.*.user
|
||||
*.ncb
|
||||
*.sdf
|
||||
*.opensdf
|
||||
*.vcxproj
|
||||
*vcxproj.*
|
||||
|
||||
# MinGW generated files
|
||||
*.Debug
|
||||
*.Release
|
||||
|
||||
# Python byte code
|
||||
*.pyc
|
||||
|
||||
# Binaries
|
||||
# --------
|
||||
*.dll
|
||||
*.exe
|
||||
|
||||
14
OfficeShelf/zuschnitt_cpp/zuscnitt/CMakeLists.txt
Normal file
14
OfficeShelf/zuschnitt_cpp/zuscnitt/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
project(zuscnitt LANGUAGES CXX)
|
||||
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "-O3")
|
||||
SET(CMAKE_C_FLAGS_DEBUG "-O3")
|
||||
|
||||
add_executable(zuscnitt main.cpp)
|
||||
|
||||
install(TARGETS zuscnitt
|
||||
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
|
||||
287
OfficeShelf/zuschnitt_cpp/zuscnitt/main.cpp
Normal file
287
OfficeShelf/zuschnitt_cpp/zuscnitt/main.cpp
Normal file
|
|
@ -0,0 +1,287 @@
|
|||
#include <cassert>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
bool intvectcontains(const std::vector<int> &heystack, int needle) {
|
||||
for (auto i: heystack) {
|
||||
if (i == needle) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
class Cut {
|
||||
|
||||
public:
|
||||
Cut(int l) {
|
||||
this->Length = l;
|
||||
}
|
||||
|
||||
int length() const {
|
||||
return this->Length;
|
||||
}
|
||||
|
||||
private:
|
||||
Cut(Cut &); // deny copying
|
||||
int Length = 0;
|
||||
};
|
||||
|
||||
|
||||
class CutableRod {
|
||||
public:
|
||||
CutableRod() {
|
||||
this->Length = 6000;
|
||||
this->CutThickness = 9;
|
||||
this->Remainder = this->Length;
|
||||
}
|
||||
|
||||
CutableRod(CutableRod &other) {
|
||||
this->Length = other.Length;
|
||||
this->CutThickness = other.CutThickness;
|
||||
this->Remainder = other.Remainder;
|
||||
for (auto c : other.Cuts) {
|
||||
this->Cuts.push_back(c);
|
||||
}
|
||||
}
|
||||
|
||||
void addCut(std::shared_ptr<const Cut> cut) {
|
||||
assert(this->canAddCut(cut));
|
||||
this->Cuts.push_back(cut);
|
||||
this->Remainder -= cut->length();
|
||||
this->Remainder -= this->CutThickness;
|
||||
}
|
||||
|
||||
bool canAddCut(std::shared_ptr<const Cut> cut) {
|
||||
return this->Remainder >= cut->length();
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<const Cut>> cuts() {
|
||||
return this->Cuts;
|
||||
}
|
||||
|
||||
int remainder() {
|
||||
return this->Remainder;
|
||||
}
|
||||
|
||||
int variety(void) {
|
||||
std::vector<int> lengths;
|
||||
for (auto cut : this->Cuts) {
|
||||
if (!intvectcontains(lengths, cut->length()))
|
||||
lengths.push_back(cut->length());
|
||||
}
|
||||
return lengths.size();
|
||||
}
|
||||
|
||||
private:
|
||||
int Length = 0;
|
||||
int CutThickness = 0;
|
||||
int Remainder = 0;
|
||||
std::vector<std::shared_ptr<const Cut>> Cuts;
|
||||
};
|
||||
|
||||
|
||||
class CutSolution {
|
||||
public:
|
||||
CutSolution() {
|
||||
}
|
||||
|
||||
CutSolution(CutSolution &other) {
|
||||
for (auto r_other: other.Rods) {
|
||||
auto r_copy = std::make_shared<CutableRod>(*r_other);
|
||||
this->Rods.push_back(r_copy);
|
||||
}
|
||||
}
|
||||
|
||||
void addCut(std::shared_ptr<const Cut> cut) {
|
||||
|
||||
// add rod if empty
|
||||
if (this->Rods.empty()) {
|
||||
auto new_rod = std::make_shared<CutableRod>();
|
||||
this->Rods.push_back(new_rod);
|
||||
}
|
||||
|
||||
// add rod if cannot add cut
|
||||
if (!this->Rods.back()->canAddCut(cut)) {
|
||||
auto new_rod = std::make_shared<CutableRod>();
|
||||
this->Rods.push_back(new_rod);
|
||||
}
|
||||
|
||||
// add cut to last rod
|
||||
this->Rods.back()->addCut(cut);
|
||||
}
|
||||
|
||||
bool isBetterThan(const CutSolution &other) {
|
||||
|
||||
// compare rod amount
|
||||
int my_r = this->rods();
|
||||
int other_r = other.rods();
|
||||
if (my_r != other_r) {
|
||||
return my_r < other_r;
|
||||
|
||||
// compare remainder amount
|
||||
} else {
|
||||
int my_r = this->remainder();
|
||||
int other_r = other.remainder();
|
||||
if (my_r != other_r) {
|
||||
return my_r < other_r;
|
||||
|
||||
// compare variety amount
|
||||
} else {
|
||||
int my_v = this->variety();
|
||||
int other_v = other.variety();
|
||||
if (my_v != other_v) {
|
||||
return my_v < other_v;
|
||||
|
||||
// both solutions are equal
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void print(bool shortform=false) {
|
||||
if (!shortform) {
|
||||
std::cout << std::endl << "Solution" << std::endl;
|
||||
for (auto it = this->Rods.begin(); it != this->Rods.end(); ++it) {
|
||||
int pos = std::distance(this->Rods.begin(), it);
|
||||
std::cout << "Rod " << pos << ": ";
|
||||
for (auto c: (*it)->cuts()) {
|
||||
std::cout << c->length() << " ";
|
||||
}
|
||||
std::cout << "(-" << (*it)->remainder() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "Rods=" << this->rods();
|
||||
std::cout << ", Remainder=" << this->remainder();
|
||||
std::cout << ", Variety=" << this->variety();
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
int remainder() const {
|
||||
int ret = 0;
|
||||
for (auto r: this->Rods) {
|
||||
ret += r->remainder();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int rods() const {
|
||||
return (int) this->Rods.size();
|
||||
}
|
||||
|
||||
int variety() const {
|
||||
int ret = 0;
|
||||
for (auto r: this->Rods) {
|
||||
int v = r->variety();
|
||||
if (v > 1) ret += v;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<CutableRod>> Rods;
|
||||
};
|
||||
|
||||
|
||||
class CutRequest {
|
||||
public:
|
||||
CutRequest() {}
|
||||
|
||||
void add(int amount, int length) {
|
||||
for (int i=0; i < amount; ++i) {
|
||||
auto c = std::make_shared<Cut>(length);
|
||||
this->Cuts.push_back(c);
|
||||
}
|
||||
}
|
||||
|
||||
void arrangeCuts() {
|
||||
auto time_start = std::time(nullptr);
|
||||
auto solution = CutSolution();
|
||||
solution = this->arrangeCutIteration(solution, this->Cuts);
|
||||
solution.print();
|
||||
auto time_end = std::time(nullptr);
|
||||
std::cout << "Duration: " << (time_end - time_start) << std::endl;
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<const Cut>> cuts() {
|
||||
return this->Cuts;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<const Cut>> Cuts;
|
||||
|
||||
CutSolution arrangeCutIteration(CutSolution ¤t_solution,
|
||||
std::vector<std::shared_ptr<const Cut>> remaining_cuts) {
|
||||
|
||||
if (remaining_cuts.empty()) return current_solution;
|
||||
CutSolution best_solution;
|
||||
bool ret_is_defined = false;
|
||||
|
||||
std::vector<int> tested_lengths;
|
||||
for (int idx_try=0; idx_try < remaining_cuts.size(); ++idx_try) {
|
||||
auto cut = remaining_cuts.at(idx_try);
|
||||
|
||||
// avaoid testing same length again
|
||||
// if (std::find(tested_lengths.begin(), tested_lengths.end(), cut->length()) != tested_lengths.end()) continue;
|
||||
if (intvectcontains(tested_lengths, cut->length())) continue;
|
||||
tested_lengths.push_back(cut->length());
|
||||
|
||||
// create temporary solution for trial
|
||||
CutSolution trysol(current_solution);
|
||||
|
||||
// add cut to temporary solution
|
||||
trysol.addCut(cut);
|
||||
|
||||
// create list of remaining other cuts
|
||||
std::vector<std::shared_ptr<const Cut>> remaining_cuts_without_try;
|
||||
remaining_cuts_without_try.clear();
|
||||
for (int idx_other=0; idx_other < remaining_cuts.size(); ++idx_other) {
|
||||
if (idx_other == idx_try) continue;
|
||||
|
||||
auto cut_other = remaining_cuts.at(idx_other);
|
||||
remaining_cuts_without_try.push_back(cut_other);
|
||||
}
|
||||
|
||||
// solve for tried remaining cuts
|
||||
trysol = this->arrangeCutIteration(trysol, remaining_cuts_without_try);
|
||||
|
||||
// keep best solution
|
||||
if (!ret_is_defined || trysol.isBetterThan(best_solution)) {
|
||||
best_solution = trysol;
|
||||
if (current_solution.rods() == 0) {
|
||||
std::cout << "Better Solution: ";
|
||||
best_solution.print(true);
|
||||
}
|
||||
ret_is_defined = true;
|
||||
}
|
||||
}
|
||||
|
||||
return best_solution;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
int main(void) {
|
||||
CutRequest cr;
|
||||
cr.add(8, 660);
|
||||
cr.add(16, 620);
|
||||
cr.add(1, 905);
|
||||
cr.add(2, 442);
|
||||
cr.add(2, 848);
|
||||
cr.add(4, 414);
|
||||
cr.arrangeCuts();
|
||||
|
||||
// // manual solve
|
||||
// CutSolution cs;
|
||||
// for (auto c: cr.cuts()) {
|
||||
// cs.addCut(c);
|
||||
// }
|
||||
// cs.print();
|
||||
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue