Commit b25af341 authored by XingyuChen's avatar XingyuChen
Browse files

fix comments

parent 7b1e0efb
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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
@@ -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:
+3 −3
Original line number Diff line number Diff line
@@ -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
@@ -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:

impl/Rubk.cpp

deleted100644 → 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
+1 −32
Original line number Diff line number Diff line
@@ -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++) {
+41 −16
Original line number Diff line number Diff line
@@ -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.");
@@ -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;
}
@@ -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);
    }
@@ -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();
@@ -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;
}