打印房间但只能访问一次

时间:2016-06-21 19:44:53

标签: c++ string linear extended-ascii memory-access

我正在修补打印房间from this problem的方法。我正在使用extended ASCII中的方框图来测试这个,所以我认识到这限制了我的代码编译的范围。

如果您不想在那里阅读,请快速解释问题:

将房间定义为4位整数,以便

  • 最重要的一位代表房间是否有西墙
  • 房间是否有北墙的次要位置
  • 房间是否有东墙
  • 是次要的
  • 最不重要的位代表房间是否有南墙

作为一个例子,由 0b1101 代表的房间将有一个西,北和南墙:

┌─
│
└─

还有其他限制因素:

  1. 房间的外墙总是有一面墙
  2. 内墙将始终在两个房间中表达(示例 0b1101 在南方有一面墙,因此它下方的房间必须具有下一个最重要的位设置,表示一个北方壁)
  3. 永远不会超过numeric_limits<int>::max()个房间
  4. 我的问题是选择交叉点字符。我的强力算法必须访问每个房间两次(第一行/列中的房间除外。)有没有办法找到每个房间只有一个内存访问的交叉点?

    如果您想查看我的代码以供参考;它需要:

    1. vector<char>房间信息
    2. size_t给出行宽
    3. 带有每个房间标签的vector<int>(可以将其设置为vector(size(testValues), -17),只打印没有标签的房间结构
    4. string printArray(const vector<char>& testValues, const size_t width, const vector<int>& indexes) {
          if (empty(testValues)) {
              return string();
          } else {
              string result;
              auto prevLine = "\xC9\xCD"s;
      
              prevLine.reserve(2U * (1U + width));
      
              for (auto i = 0U; i + 1 < width; ++i) {
                  if ((testValues[i] & 0b10) != 0) {
                      prevLine += "\xD1\xCD"s;
                  } else {
                      prevLine += "\xCD\xCD"s;
                  }
              }
              prevLine += "\xBB\n"s;
      
              result.reserve(size(prevLine) * (1U + 2U * size(testValues) / width));
      
              for (auto i = 0U; i < size(testValues) - width; ++i) {
                  const auto x = i % width;
      
                  const auto isBottomSet = (testValues[i] & 0b1) != 0;
      
                  if (x == 0) {
                      result += (prevLine + '\xBA') + static_cast<char>('0' + indexes[i]);
                      prevLine = isBottomSet ? "\xC7\xC4"s : "\xBA "s;
                  }
      
                  if (x + 1U == width) {
                      result += "\xBA\n"s;
                      prevLine += isBottomSet ? "\xB6\n"s : "\xBA\n"s;
                  } else {
                      const auto isRightSet = (testValues[i] & 0b10) != 0;
                      const size_t index = static_cast<int>(isRightSet) << 3 | testValues[i + width + 1] & 0b100 | (testValues[i + width + 1] & 0b1000) >> 2 | static_cast<int>(isBottomSet);
                      // MSB: isAboveIntersectionSet
                      //      isRightOfIntersectionSet
                      //      isBelowIntersectionSet
                      // LSB: isLeftOfIntersectionSet
                      constexpr const char* getIntersection[] = { "  ", // 0b0
                                                                  "  ", // 0b1
                                                                  "  ", // 0b10
                                                                  "\xBF ", // 0b11
                                                                  " \xC4", // 0b100
                                                                  "\xC4\xC4", // 0b101
                                                                  "\xDA\xC4", // 0b110
                                                                  "\xC2\xC4", // 0b111
                                                                  "  ", // 0b1000:
                                                                  "\xD9 ", // 0b1001
                                                                  "\xB3 ", // 0b1010
                                                                  "\xB4 ", // 0b1011
                                                                  "\xC0\xC4", // 0b1100
                                                                  "\xC1\xC4", // 0b1101
                                                                  "\xC3\xC4", // 0b1110
                                                                  "\xC5\xC4" }; // 0b1111
      
                      result += { isRightSet ? '\xB3' : ' ', static_cast<char>('0' + indexes[i + 1]) };
                      prevLine += getIntersection[index];
                  }
              }
      
              result += (prevLine + '\xBA') + static_cast<char>('0' + indexes[size(testValues) - width]);
              prevLine = "\xC8\xCD"s;
      
              for (auto i = size(testValues) - width; i + 1 < size(testValues); ++i) {
                  if ((testValues[i] & 0b10) != 0) {
                      result += { '\xB3', static_cast<char>('0' + indexes[i + 1]) };
                      prevLine += "\xCF\xCD"s;
                  } else {
                      result += { ' ', static_cast<char>('0' + indexes[i + 1]) };
                      prevLine += "\xCD\xCD"s;
                  }
              }
              return result + "\xBA\n"s + prevLine + '\xBC';
          }
      }
      

      如果您对此进行简单测试感兴趣,可以这样做:

      const vector<char> rooms = { 0b1101,    0b110,  0b1101, 0b110,  0b1100, 0b101,  0b110,
                                   0b1110,    0b1001, 0b110,  0b1011, 0b1010, 0b1111, 0b1010,
                                   0b1000,    0b101,  0b11,   0b1110, 0b1011, 0b1110, 0b1010,
                                   0b1011,    0b1101, 0b101,  0b1,    0b101,  0b11,   0b1011 };
      const vector<int> indexes = { 1,    1,  2,  2,  3,  3,  3,
                                    1,    1,  1,  2,  3,  5,  3,
                                    1,    1,  1,  6,  3,  6,  3,
                                    1,    6,  6,  6,  6,  6,  3 };
      
      cout << printArray(rooms, width, indexes) << endl;
      

      要运行此功能,您需要转到http://webcompiler.cloudapp.net/并粘贴所有内容。

0 个答案:

没有答案