Loading ci_cd/problem3a.yml +3 −3 Original line number Diff line number Diff line Loading @@ -3,8 +3,8 @@ prebuild_problem_3a: script: - | # Check if source files exist if [ ! -f "Rubk.cpp" ]; then echo "Rubk.cpp does not exist"; if [ ! -f "impl/Rubk.cpp" ]; then echo "Rubk.cpp does not exist under impl directory"; exit 1; fi - git clone https://agile.bu.edu/gitlab/configs/ec330/homeworks/homeworktwo.git hw2 Loading @@ -21,7 +21,7 @@ compile_problem_3a: - job: prebuild_problem_3a artifacts: true script: - cp Rubk.cpp hw2/tests/ - cp impl/Rubk.cpp hw2/tests/ - cd hw2/tests - make problem3a artifacts: Loading ci_cd/problem3c.yml +3 −3 Original line number Diff line number Diff line Loading @@ -7,8 +7,8 @@ prebuild_problem_3c: echo "main.cpp does not exist"; exit 1; fi if [ ! -f "Rubk.cpp" ]; then echo "Rubk.cpp does not exist"; if [ ! -f "impl/Rubk.cpp" ]; then echo "Rubk.cpp does not exist under impl directory"; exit 1; fi - git clone https://agile.bu.edu/gitlab/configs/ec330/homeworks/homeworktwo.git hw2 Loading @@ -25,7 +25,7 @@ compile_problem_3c: - job: prebuild_problem_3c artifacts: true script: - cp Rubk.cpp main.cpp hw2/tests/ - cp impl/Rubk.cpp main.cpp hw2/tests/ - cd hw2/tests - make problem3c artifacts: Loading impl/Rubk.cppdeleted 100644 → 0 +0 −274 Original line number Diff line number Diff line // // Created by Ari on 2/4/17. // #include "../include/Rubk.h" #include "../include/Enums.h" #include <algorithm> #include <cctype> #include <iostream> #include <stdexcept> // HELPER FUNCTIONS /** * @param line The line to examine * @return true iff line consists only of space-like characters */ bool isBlank(string line) { return all_of(line.begin(), line.end(), // keep going until a blank line or eof [](unsigned char ch) { return std::isspace(ch); }); } void faceHelper(Rubk &result, istringstream &fps, FaceName theFace, string line) { int col = 0, row = 0; bool lineOk; do { // look for a non-blank line while (isBlank(line)) getline(fps, line); for (auto ch : line) { if (!std::isspace(ch)) { result.setCellColor(theFace, Face::Row(row), Face::Column(col), CharToColor(ch)); col++; } } row++; col = 0; // reset for next line lineOk = static_cast<bool>(getline(fps, line)); } while (lineOk && row < result.getLen()); } /** * Cycles through four positions for a single index (based on ChatGPT * optimization). */ void cycle4(const Rubk &src, Rubk &dst, FaceName f1, Face::Row r1, Face::Column c1, FaceName f2, Face::Row r2, Face::Column c2, FaceName f3, Face::Row r3, Face::Column c3, FaceName f4, Face::Row r4, Face::Column c4) { Color tmp = src.getCellColor(f1, r1, c1); dst.setCellColor(f1, r1, c1, src.getCellColor(f2, r2, c2)); dst.setCellColor(f2, r2, c2, src.getCellColor(f3, r3, c3)); dst.setCellColor(f3, r3, c3, src.getCellColor(f4, r4, c4)); dst.setCellColor(f4, r4, c4, tmp); } /** * Concatenates 4 faces to the output stream. * Output is undefined if the faces do not have the same dimensions. * @param os The stream onto which the faces are output. */ void concatFaces(std::ostream &os, const Face &face1, const Face &face2, const Face &face3, const Face &face4) { for (int xx = 0; xx < face1.faceLen(); xx++) { Face::Row xxRow(xx); os << face1.printRow(xxRow) << " " << face2.printRow(xxRow) << " " << face3.printRow(xxRow) << " " << face4.printRow(xxRow) << " " << endl; } } std::ostream &operator<<(std::ostream &os, const Rubk &cube) { return os << cube.printFlattened(); } // RUBK IMPLEMENTATIONS Rubk::Rubk(int len) : cubeLen(len) { _faces.emplace(FaceName::TOP, Face(Color::RED, cubeLen)); _faces.emplace(FaceName::LEFT, Face(Color::BLUE, cubeLen)); _faces.emplace(FaceName::FRONT, Face(Color::WHITE, cubeLen)); _faces.emplace(FaceName::RIGHT, Face(Color::RED, cubeLen)); _faces.emplace(FaceName::AFT, Face(Color::BLUE, cubeLen)); _faces.emplace(FaceName::BOTTOM, Face(Color::WHITE, cubeLen)); } Rubk::Rubk(Rubk const &other) { cubeLen = other.cubeLen; _faces = other._faces; } Rubk::Rubk(const string &flatProfile) { std::istringstream fps(flatProfile); // a stream version of the flatProfile // get cube dimensions and setup faces string line; // dimension length is the number of non-space characters in the non-blank // first line while (isBlank(line)) { getline(fps, line); } cubeLen = static_cast<int>(count_if(line.begin(), line.end(), [](unsigned char ch) { return !std::isspace(ch); })); _faces.emplace(FaceName::TOP, Face(Color::RED, cubeLen)); _faces.emplace(FaceName::LEFT, Face(Color::BLUE, cubeLen)); _faces.emplace(FaceName::FRONT, Face(Color::WHITE, cubeLen)); _faces.emplace(FaceName::RIGHT, Face(Color::RED, cubeLen)); _faces.emplace(FaceName::AFT, Face(Color::BLUE, cubeLen)); _faces.emplace(FaceName::BOTTOM, Face(Color::WHITE, cubeLen)); // read the top tranche faceHelper(*this, fps, FaceName::TOP, line); // read the middle tranche getline(fps, line); int col = 0, row = 0; bool lineOk; do { // look for a non-blank line while (isBlank(line)) getline(fps, line); // read the characters of the line auto theFace = FaceName::LEFT; for (auto ch : line) { if (!std::isspace(ch)) { setCellColor(theFace, Face::Row(row), Face::Column(col), CharToColor(ch)); if (++col == cubeLen) { col = 0; switch (theFace) { case FaceName::LEFT: theFace = FaceName::FRONT; break; case FaceName::FRONT: theFace = FaceName::RIGHT; break; case FaceName::RIGHT: theFace = FaceName::AFT; break; default: break; } } } } row++; col = 0; // reset for next line lineOk = static_cast<bool>(getline(fps, line)); } while (lineOk && row < cubeLen); // read the bottom tranche getline(fps, line); faceHelper(*this, fps, FaceName::BOTTOM, line); } bool Rubk::isUnscrambled() const { throw logic_error("Rubk::isUnscrambled() has not yet been implemented"); } Rubk Rubk::rotate(bool direction, FaceName theFaceName) const { Rubk result(*this); for (int xx = 0; xx < cubeLen; xx++) for (int yy = 0; yy < cubeLen; yy++) result.setCellColor( theFaceName, Face::Row(direction ? xx : cubeLen - 1 - xx), Face::Column(direction ? cubeLen - 1 - yy : yy), getCellColor(theFaceName, Face::Row(yy), Face::Column(xx))); return result; } Rubk Rubk::makeMove(CubeMoves theMove) const { constexpr Face::Column leftCol(0); constexpr Face::Row topRow(0); const Face::Column rightCol(cubeLen - 1); const Face::Row bottomRow(cubeLen - 1); Rubk result(*this); switch (theMove) { case LeftDown: { // front left column goes down for (int yy = 0; yy < cubeLen; ++yy) { Face::Row r(yy); Face::Row rr(cubeLen - 1 - yy); cycle4(*this, result, FaceName::FRONT, r, leftCol, FaceName::TOP, r, leftCol, FaceName::AFT, rr, rightCol, // reversed FaceName::BOTTOM, r, leftCol); } result = result.rotate(true, FaceName::LEFT); break; } case RightDown: { // front right column goes down for (int yy = 0; yy < cubeLen; ++yy) { const Face::Row r(yy); const Face::Row rr(cubeLen - 1 - yy); cycle4(*this, result, FaceName::FRONT, r, rightCol, FaceName::TOP, r, rightCol, FaceName::AFT, rr, leftCol, // back reversed FaceName::BOTTOM, r, rightCol); } result = result.rotate(false, FaceName::RIGHT); break; } case TopLeft: { // top row goes left for (int yy = 0; yy < cubeLen; ++yy) { Face::Column c(yy); cycle4(*this, result, FaceName::FRONT, topRow, c, FaceName::RIGHT, topRow, c, FaceName::AFT, topRow, c, FaceName::LEFT, topRow, c); } result = result.rotate(true, FaceName::TOP); break; } case BottomLeft: { // bottom row goes left for (int yy = 0; yy < cubeLen; ++yy) { const Face::Column c(yy); cycle4(*this, result, FaceName::FRONT, bottomRow, c, FaceName::RIGHT, bottomRow, c, FaceName::AFT, bottomRow, c, FaceName::LEFT, bottomRow, c); } result = result.rotate(false, FaceName::BOTTOM); break; } default: throw out_of_range("ERR: I don't know how to do that yet ... sorry!"); } return result; } Color Rubk::getCellColor(FaceName theFaceName, Face::Row theRow, Face::Column theColumn) const { return getFace(theFaceName).get(theRow, theColumn); } void Rubk::setCellColor(FaceName theFaceName, Face::Row theRow, Face::Column theColumn, Color newColor) { getFace(theFaceName).set(theRow, theColumn, newColor); } string Rubk::printFlattened() const { stringstream os; // the output stream Face BLANK_FACE(Color::BLANK_, cubeLen); // a blank face // output the cube // ... row 0 concatFaces(os, BLANK_FACE, getFace(FaceName::TOP), BLANK_FACE, BLANK_FACE); os << endl; // ... row 1 concatFaces(os, getFace(FaceName::LEFT), getFace(FaceName::FRONT), getFace(FaceName::RIGHT), getFace(FaceName::AFT)); os << endl; // ... row 2 concatFaces(os, BLANK_FACE, getFace(FaceName::BOTTOM), BLANK_FACE, BLANK_FACE); os << endl; return os.str(); } No newline at end of file tests/testMoves.cpp +1 −32 Original line number Diff line number Diff line Loading @@ -123,39 +123,8 @@ bool test_2() { return true; } // -------------------- New moves equivalence: inverse = 3 repeats of forward -------------------- bool test_3() { const char* T = "Inverse move should equal 3 repeats of forward move"; Rubk start(3); // For the 4 new inverse moves, check: // start.makeMove(LeftUp) == start.makeMove(LeftDown)^3, etc. struct Pair { CubeMoves inv; CubeMoves fwd; }; const std::array<Pair, 4> pairs = {{ {LeftUp, LeftDown}, {RightUp, RightDown}, {TopRight, TopLeft}, {BottomRight, BottomLeft} }}; for (auto p : pairs) { Rubk gotInv = start.makeMove(p.inv); Rubk got3 = applyK(start, p.fwd, 3); if (!sameCube(gotInv, got3)) { return failExample( T, "inverse should match 3 repeats of forward", "same flattened cube", "different flattened cube" ); } } return true; } int main() { bool results[] = { test_0(), test_1(), test_2(), test_3() }; bool results[] = { test_0(), test_1(), test_2()}; bool allPassed = true; for (size_t ii = 0; ii < std::size(results); ii++) { Loading tests/testUnscramble.cpp +41 −16 Original line number Diff line number Diff line Loading @@ -62,12 +62,7 @@ static std::string runSolverCaptureStdout(const std::string& flatProfile) { } std::string cmd = std::string(SOLVER_CMD) + " < " + tmpIn; #if defined(_WIN32) FILE* pipe = _popen(cmd.c_str(), "r"); #else FILE* pipe = popen(cmd.c_str(), "r"); #endif if (!pipe) { std::remove(tmpIn); throw std::runtime_error("Failed to run solver via popen/_popen."); Loading @@ -79,12 +74,7 @@ static std::string runSolverCaptureStdout(const std::string& flatProfile) { out += buffer; } #if defined(_WIN32) _pclose(pipe); #else pclose(pipe); #endif std::remove(tmpIn); return out; } Loading Loading @@ -183,8 +173,7 @@ static std::vector<fs::path> collectTestcases() { const auto fname = p.filename().string(); // match test_*.txt if (fname.size() >= 9 && fname.rfind("test_", 0) == 0 && if (fname.rfind("test_", 0) == 0 && p.extension() == ".txt") { files.push_back(p); } Loading @@ -194,7 +183,41 @@ static std::vector<fs::path> collectTestcases() { return files; } // -------------------- test IsUnscrambled -------------------- static bool testIsUnscrambled() { const char* T = "isUnscrambled() sanity check"; Rubk solved(3); if (!solved.isUnscrambled()) { return failExample(T, "solved cube should report unscrambled", "true", "false"); } Rubk scrambled = solved.makeMove(LeftDown); if (scrambled.isUnscrambled()) { return failExample(T, "scrambled cube should report scrambled", "false", "true"); } return true; } int main() { bool allPassed = true; size_t idx = 0; // ---------- isUnscrambled test ---------- bool sanity = testIsUnscrambled(); cout << "isUnscrambled functionality test: " << (sanity ? "passed" : "failed") << endl; allPassed &= sanity; // ---------- collect testcases ---------- std::vector<fs::path> tests; try { tests = collectTestcases(); Loading @@ -208,15 +231,17 @@ int main() { return -1; } bool allPassed = true; size_t idx = 0; // ---------- run solver tests ---------- for (const auto& tc : tests) { bool ok = runOneTestcase(tc); cout << "Testcase " << idx++ << " (" << tc.filename().string() << "): " cout << "Testcase " << idx++ << " (" << tc.filename().string() << "): " << (ok ? "passed" : "failed") << "\n"; allPassed &= ok; } return allPassed ? 0 : -1; } Loading
ci_cd/problem3a.yml +3 −3 Original line number Diff line number Diff line Loading @@ -3,8 +3,8 @@ prebuild_problem_3a: script: - | # Check if source files exist if [ ! -f "Rubk.cpp" ]; then echo "Rubk.cpp does not exist"; if [ ! -f "impl/Rubk.cpp" ]; then echo "Rubk.cpp does not exist under impl directory"; exit 1; fi - git clone https://agile.bu.edu/gitlab/configs/ec330/homeworks/homeworktwo.git hw2 Loading @@ -21,7 +21,7 @@ compile_problem_3a: - job: prebuild_problem_3a artifacts: true script: - cp Rubk.cpp hw2/tests/ - cp impl/Rubk.cpp hw2/tests/ - cd hw2/tests - make problem3a artifacts: Loading
ci_cd/problem3c.yml +3 −3 Original line number Diff line number Diff line Loading @@ -7,8 +7,8 @@ prebuild_problem_3c: echo "main.cpp does not exist"; exit 1; fi if [ ! -f "Rubk.cpp" ]; then echo "Rubk.cpp does not exist"; if [ ! -f "impl/Rubk.cpp" ]; then echo "Rubk.cpp does not exist under impl directory"; exit 1; fi - git clone https://agile.bu.edu/gitlab/configs/ec330/homeworks/homeworktwo.git hw2 Loading @@ -25,7 +25,7 @@ compile_problem_3c: - job: prebuild_problem_3c artifacts: true script: - cp Rubk.cpp main.cpp hw2/tests/ - cp impl/Rubk.cpp main.cpp hw2/tests/ - cd hw2/tests - make problem3c artifacts: Loading
impl/Rubk.cppdeleted 100644 → 0 +0 −274 Original line number Diff line number Diff line // // Created by Ari on 2/4/17. // #include "../include/Rubk.h" #include "../include/Enums.h" #include <algorithm> #include <cctype> #include <iostream> #include <stdexcept> // HELPER FUNCTIONS /** * @param line The line to examine * @return true iff line consists only of space-like characters */ bool isBlank(string line) { return all_of(line.begin(), line.end(), // keep going until a blank line or eof [](unsigned char ch) { return std::isspace(ch); }); } void faceHelper(Rubk &result, istringstream &fps, FaceName theFace, string line) { int col = 0, row = 0; bool lineOk; do { // look for a non-blank line while (isBlank(line)) getline(fps, line); for (auto ch : line) { if (!std::isspace(ch)) { result.setCellColor(theFace, Face::Row(row), Face::Column(col), CharToColor(ch)); col++; } } row++; col = 0; // reset for next line lineOk = static_cast<bool>(getline(fps, line)); } while (lineOk && row < result.getLen()); } /** * Cycles through four positions for a single index (based on ChatGPT * optimization). */ void cycle4(const Rubk &src, Rubk &dst, FaceName f1, Face::Row r1, Face::Column c1, FaceName f2, Face::Row r2, Face::Column c2, FaceName f3, Face::Row r3, Face::Column c3, FaceName f4, Face::Row r4, Face::Column c4) { Color tmp = src.getCellColor(f1, r1, c1); dst.setCellColor(f1, r1, c1, src.getCellColor(f2, r2, c2)); dst.setCellColor(f2, r2, c2, src.getCellColor(f3, r3, c3)); dst.setCellColor(f3, r3, c3, src.getCellColor(f4, r4, c4)); dst.setCellColor(f4, r4, c4, tmp); } /** * Concatenates 4 faces to the output stream. * Output is undefined if the faces do not have the same dimensions. * @param os The stream onto which the faces are output. */ void concatFaces(std::ostream &os, const Face &face1, const Face &face2, const Face &face3, const Face &face4) { for (int xx = 0; xx < face1.faceLen(); xx++) { Face::Row xxRow(xx); os << face1.printRow(xxRow) << " " << face2.printRow(xxRow) << " " << face3.printRow(xxRow) << " " << face4.printRow(xxRow) << " " << endl; } } std::ostream &operator<<(std::ostream &os, const Rubk &cube) { return os << cube.printFlattened(); } // RUBK IMPLEMENTATIONS Rubk::Rubk(int len) : cubeLen(len) { _faces.emplace(FaceName::TOP, Face(Color::RED, cubeLen)); _faces.emplace(FaceName::LEFT, Face(Color::BLUE, cubeLen)); _faces.emplace(FaceName::FRONT, Face(Color::WHITE, cubeLen)); _faces.emplace(FaceName::RIGHT, Face(Color::RED, cubeLen)); _faces.emplace(FaceName::AFT, Face(Color::BLUE, cubeLen)); _faces.emplace(FaceName::BOTTOM, Face(Color::WHITE, cubeLen)); } Rubk::Rubk(Rubk const &other) { cubeLen = other.cubeLen; _faces = other._faces; } Rubk::Rubk(const string &flatProfile) { std::istringstream fps(flatProfile); // a stream version of the flatProfile // get cube dimensions and setup faces string line; // dimension length is the number of non-space characters in the non-blank // first line while (isBlank(line)) { getline(fps, line); } cubeLen = static_cast<int>(count_if(line.begin(), line.end(), [](unsigned char ch) { return !std::isspace(ch); })); _faces.emplace(FaceName::TOP, Face(Color::RED, cubeLen)); _faces.emplace(FaceName::LEFT, Face(Color::BLUE, cubeLen)); _faces.emplace(FaceName::FRONT, Face(Color::WHITE, cubeLen)); _faces.emplace(FaceName::RIGHT, Face(Color::RED, cubeLen)); _faces.emplace(FaceName::AFT, Face(Color::BLUE, cubeLen)); _faces.emplace(FaceName::BOTTOM, Face(Color::WHITE, cubeLen)); // read the top tranche faceHelper(*this, fps, FaceName::TOP, line); // read the middle tranche getline(fps, line); int col = 0, row = 0; bool lineOk; do { // look for a non-blank line while (isBlank(line)) getline(fps, line); // read the characters of the line auto theFace = FaceName::LEFT; for (auto ch : line) { if (!std::isspace(ch)) { setCellColor(theFace, Face::Row(row), Face::Column(col), CharToColor(ch)); if (++col == cubeLen) { col = 0; switch (theFace) { case FaceName::LEFT: theFace = FaceName::FRONT; break; case FaceName::FRONT: theFace = FaceName::RIGHT; break; case FaceName::RIGHT: theFace = FaceName::AFT; break; default: break; } } } } row++; col = 0; // reset for next line lineOk = static_cast<bool>(getline(fps, line)); } while (lineOk && row < cubeLen); // read the bottom tranche getline(fps, line); faceHelper(*this, fps, FaceName::BOTTOM, line); } bool Rubk::isUnscrambled() const { throw logic_error("Rubk::isUnscrambled() has not yet been implemented"); } Rubk Rubk::rotate(bool direction, FaceName theFaceName) const { Rubk result(*this); for (int xx = 0; xx < cubeLen; xx++) for (int yy = 0; yy < cubeLen; yy++) result.setCellColor( theFaceName, Face::Row(direction ? xx : cubeLen - 1 - xx), Face::Column(direction ? cubeLen - 1 - yy : yy), getCellColor(theFaceName, Face::Row(yy), Face::Column(xx))); return result; } Rubk Rubk::makeMove(CubeMoves theMove) const { constexpr Face::Column leftCol(0); constexpr Face::Row topRow(0); const Face::Column rightCol(cubeLen - 1); const Face::Row bottomRow(cubeLen - 1); Rubk result(*this); switch (theMove) { case LeftDown: { // front left column goes down for (int yy = 0; yy < cubeLen; ++yy) { Face::Row r(yy); Face::Row rr(cubeLen - 1 - yy); cycle4(*this, result, FaceName::FRONT, r, leftCol, FaceName::TOP, r, leftCol, FaceName::AFT, rr, rightCol, // reversed FaceName::BOTTOM, r, leftCol); } result = result.rotate(true, FaceName::LEFT); break; } case RightDown: { // front right column goes down for (int yy = 0; yy < cubeLen; ++yy) { const Face::Row r(yy); const Face::Row rr(cubeLen - 1 - yy); cycle4(*this, result, FaceName::FRONT, r, rightCol, FaceName::TOP, r, rightCol, FaceName::AFT, rr, leftCol, // back reversed FaceName::BOTTOM, r, rightCol); } result = result.rotate(false, FaceName::RIGHT); break; } case TopLeft: { // top row goes left for (int yy = 0; yy < cubeLen; ++yy) { Face::Column c(yy); cycle4(*this, result, FaceName::FRONT, topRow, c, FaceName::RIGHT, topRow, c, FaceName::AFT, topRow, c, FaceName::LEFT, topRow, c); } result = result.rotate(true, FaceName::TOP); break; } case BottomLeft: { // bottom row goes left for (int yy = 0; yy < cubeLen; ++yy) { const Face::Column c(yy); cycle4(*this, result, FaceName::FRONT, bottomRow, c, FaceName::RIGHT, bottomRow, c, FaceName::AFT, bottomRow, c, FaceName::LEFT, bottomRow, c); } result = result.rotate(false, FaceName::BOTTOM); break; } default: throw out_of_range("ERR: I don't know how to do that yet ... sorry!"); } return result; } Color Rubk::getCellColor(FaceName theFaceName, Face::Row theRow, Face::Column theColumn) const { return getFace(theFaceName).get(theRow, theColumn); } void Rubk::setCellColor(FaceName theFaceName, Face::Row theRow, Face::Column theColumn, Color newColor) { getFace(theFaceName).set(theRow, theColumn, newColor); } string Rubk::printFlattened() const { stringstream os; // the output stream Face BLANK_FACE(Color::BLANK_, cubeLen); // a blank face // output the cube // ... row 0 concatFaces(os, BLANK_FACE, getFace(FaceName::TOP), BLANK_FACE, BLANK_FACE); os << endl; // ... row 1 concatFaces(os, getFace(FaceName::LEFT), getFace(FaceName::FRONT), getFace(FaceName::RIGHT), getFace(FaceName::AFT)); os << endl; // ... row 2 concatFaces(os, BLANK_FACE, getFace(FaceName::BOTTOM), BLANK_FACE, BLANK_FACE); os << endl; return os.str(); } No newline at end of file
tests/testMoves.cpp +1 −32 Original line number Diff line number Diff line Loading @@ -123,39 +123,8 @@ bool test_2() { return true; } // -------------------- New moves equivalence: inverse = 3 repeats of forward -------------------- bool test_3() { const char* T = "Inverse move should equal 3 repeats of forward move"; Rubk start(3); // For the 4 new inverse moves, check: // start.makeMove(LeftUp) == start.makeMove(LeftDown)^3, etc. struct Pair { CubeMoves inv; CubeMoves fwd; }; const std::array<Pair, 4> pairs = {{ {LeftUp, LeftDown}, {RightUp, RightDown}, {TopRight, TopLeft}, {BottomRight, BottomLeft} }}; for (auto p : pairs) { Rubk gotInv = start.makeMove(p.inv); Rubk got3 = applyK(start, p.fwd, 3); if (!sameCube(gotInv, got3)) { return failExample( T, "inverse should match 3 repeats of forward", "same flattened cube", "different flattened cube" ); } } return true; } int main() { bool results[] = { test_0(), test_1(), test_2(), test_3() }; bool results[] = { test_0(), test_1(), test_2()}; bool allPassed = true; for (size_t ii = 0; ii < std::size(results); ii++) { Loading
tests/testUnscramble.cpp +41 −16 Original line number Diff line number Diff line Loading @@ -62,12 +62,7 @@ static std::string runSolverCaptureStdout(const std::string& flatProfile) { } std::string cmd = std::string(SOLVER_CMD) + " < " + tmpIn; #if defined(_WIN32) FILE* pipe = _popen(cmd.c_str(), "r"); #else FILE* pipe = popen(cmd.c_str(), "r"); #endif if (!pipe) { std::remove(tmpIn); throw std::runtime_error("Failed to run solver via popen/_popen."); Loading @@ -79,12 +74,7 @@ static std::string runSolverCaptureStdout(const std::string& flatProfile) { out += buffer; } #if defined(_WIN32) _pclose(pipe); #else pclose(pipe); #endif std::remove(tmpIn); return out; } Loading Loading @@ -183,8 +173,7 @@ static std::vector<fs::path> collectTestcases() { const auto fname = p.filename().string(); // match test_*.txt if (fname.size() >= 9 && fname.rfind("test_", 0) == 0 && if (fname.rfind("test_", 0) == 0 && p.extension() == ".txt") { files.push_back(p); } Loading @@ -194,7 +183,41 @@ static std::vector<fs::path> collectTestcases() { return files; } // -------------------- test IsUnscrambled -------------------- static bool testIsUnscrambled() { const char* T = "isUnscrambled() sanity check"; Rubk solved(3); if (!solved.isUnscrambled()) { return failExample(T, "solved cube should report unscrambled", "true", "false"); } Rubk scrambled = solved.makeMove(LeftDown); if (scrambled.isUnscrambled()) { return failExample(T, "scrambled cube should report scrambled", "false", "true"); } return true; } int main() { bool allPassed = true; size_t idx = 0; // ---------- isUnscrambled test ---------- bool sanity = testIsUnscrambled(); cout << "isUnscrambled functionality test: " << (sanity ? "passed" : "failed") << endl; allPassed &= sanity; // ---------- collect testcases ---------- std::vector<fs::path> tests; try { tests = collectTestcases(); Loading @@ -208,15 +231,17 @@ int main() { return -1; } bool allPassed = true; size_t idx = 0; // ---------- run solver tests ---------- for (const auto& tc : tests) { bool ok = runOneTestcase(tc); cout << "Testcase " << idx++ << " (" << tc.filename().string() << "): " cout << "Testcase " << idx++ << " (" << tc.filename().string() << "): " << (ok ? "passed" : "failed") << "\n"; allPassed &= ok; } return allPassed ? 0 : -1; }