替换向量中的元素

时间:2014-06-11 03:53:54

标签: c++ vector

我最近完成了一个解决模拟魔方的程序,但是,我的解决方案总是很长,因为程序通常会循环多个单层旋转以找到某种颜色。

如果您不知道Rubik的立方体符号是什么,基本上单个字母表示层(U)顺时针旋转90度,带撇号的字母是90度逆时针旋转(U'),并且后跟2的字母是180转(U2)。

我想要做的是在我的解决方案中使用任何[U,U] s并将它们转换为[U2],然后取任何[U,U,U]并使它们成为[U'] s 。基本上将解决方案压缩到更小的尺寸

我将旋转字母作为字符串存储在字符串向量中,所以我正在考虑制作一个这样的循环

for (int i = 0; i < vector.size(); i++)
{
    //and then check if there are similarities
    if (vector[i] == "U" && vector[i+1] == "U" && vector[i+2] == "U")
    {
        //Replace the first string with U' and delete the other 2 from the vector
    }
    else if (vector[i] == "U" && vector[i+1] == "U" && vector[i+2] != "U")
    {
        //Replace with U2
    }
    //Etc.
}

我只是想知道是否有人有更优雅的解决方案,或者你是否能看到我的缺陷(我还没有实施)

谢谢!

4 个答案:

答案 0 :(得分:1)

这可以通过坚持algorithms library来执行搜索来完成,从而避免担心边界条件。

我编写了一个帮助函数,使用std::search_n搜索你,找到连续的U

template<typename RanIter>
std::pair<RanIter, RanIter> do_search(RanIter first, RanIter last)
{
    // first look for 2 consecutive Us
    auto it = std::search_n(first, last, 2, "U");

    if(it == last) {
        // nothing to replace, bail
        return std::make_pair(last, last);
    }

    // check if we have 3 consecutive Us
    if(std::distance(it, last) >= 3) {
        // there are at least 3 elements in the range, it's ok to check
        if(*std::next(it, 2) == "U") {
            return std::make_pair(it, std::next(it, 3));
        }
    }

    return std::make_pair(it, std::next(it, 2));
}

辅助函数返回一对迭代器,指示要替换的元素范围。如果该对的第一个元素等于向量的end(),则不再有要替换的元素。否则,根据对元素之间的距离是2还是3,我们分别用"U2""U'"替换范围。

while(first != vec.end()) {
    auto result = do_search(first, vec.end());
    first = result.first;
    if(first == vec.end()) {
        break;
    }

    auto dist = std::distance(first, result.second);
    if(dist == 3) {
        first = vec.insert(first, "U'");
    } else {
        first = vec.insert(first, "U2");
    }

    // advance first to the first element to be removed and erase them
    std::advance(first, 1);
    first = vec.erase(first, std::next(first, dist));
}

Live demo

答案 1 :(得分:0)

//as pointed out by chris if i = vector.size() - 2 you're in deep trouble
for (int i = 0; i < (vector.size()-2); i++)
{
    //and then check if there are similarities
    if (vector[i] == "U" && vector[i+1] == "U" && vector[i+2] == "U")
    {
        //Replace the first string with U' and delete the other 2 from the vector
    }
    else if (vector[i] == "U" && vector[i+1] == "U" && vector[i+2] != "U")
    {
        //Replace with U2
    }
    //Etc.
}

修复了它。

答案 2 :(得分:0)

for (int i = 0; i < vector.size(); i++)
{
    //and then check if there are similarities
    if (vector[i] == "U" )
    {
       if ( (i < vector.size() - 1) && (vector[i+1] == "U") )
       {
          if ( (i < vector.size() - 2) && (vector[i+2] == "U") )
          {
             // Replace the first string with U'
             // and delete the other 2 from the vector
          }
          else
          {
             //Replace with U2
          }
       }
       else
       {
          // Just a plain U
       }
    }

    else if {...}
    //Etc.
}

答案 3 :(得分:0)

感谢您的建议pipja,chris和Sahu。我实际上最终做到这一点的方式是这样的:

    for (int i = 0; i < solution.size(); i++)
    {
        if (solution[i] == solution[i+1] && solution[i+1] == solution[i+2]) //Check if there are 3 in a row
        {
            string temp = solution[i]; 
            //Check if it's legal to compress this (ie it isn't a triplet of [U']s
            bool isLegal = true;
            for (int i = 0; i < temp.length(); i++)
            {
                if (temp[i] == '\'' || temp[i] == '2')
                {
                    isLegal = false;
                }
            }
            if (isLegal == false)
            {
                continue;
            }
            temp+="'"; //Add an apostrophe
            //Replace and delete the others
            solution[i] = temp;
            solution.erase(solution.begin()+i+1);
            solution.erase(solution.begin()+i+2);

        }
        else if (solution[i] == solution[i+1] && solution[i+1] != solution[i+2]) //Repeat for if it's 2 in a row
        {
            string temp = solution[i];
            bool isLegal = true;
            for (int i = 0; i < temp.length(); i++)
            {
                if (temp[i] == '\'' || temp[i] == '2')
                {
                    isLegal = false;
                }
            }
            if (isLegal == false)
            {
                continue;
            }
            temp+="2";
            solution[i] = temp;
            solution.erase(solution.begin()+i+1);
        }
        else //This else solves the problem mentioned by Sahu
        {
            continue;
        }
    }

我对它很满意,它不是最优雅的解决方案,但我认为它很有效