在这种情况下,我将如何循环浏览所有各种可能性



我看到了我决定尝试尝试的编程作业,这基本上是用户输入" 123456789 = 120"之类的东西,并且该程序必须插入' '或' - - '或' - '在不同的位置以使陈述成为现实。例如,在这种情况下,它可以做123 4-5 6-7 8-9 =120。只有3^8个可能的组合,所以我认为可以施加强大的力量,但是我不喜欢t确切地知道我可以进入什么顺序/如何实际实施它。更具体地说,我不知道在插入" "one_answers" - "时会采取什么顺序。这是我拥有的:

#include <iostream>
#include <cmath>
using namespace std;
int string_to_integer(string);
int main()
{
    string input, result_string;
    int result, possibilities;
    getline(cin, input);
    //remove spaces
    for(int i = 0; i < input.size(); i++)
    {
        if(input[i] == ' ')
        {
            input.erase(i, 1);
        }
    }
    result_string = input.substr(input.find('=') + 1, input.length() - input.find('='));
    result = string_to_integer(result_string);
    input.erase(input.find('='), input.length() - input.find('='));
    possibilities = pow(3, input.length() - 1);
    cout << possibilities;
}
int string_to_integer(string substring)
{
    int total = 0;
    int power = 1;
    for(int i = substring.length() - 1; i >= 0; i--)
    {
        total += (power * (substring[i] - 48));
        power *= 10;
    }
    return total;
}

基本思想:生成+-运算符的所有可能变化(包括丢失操作员的情况),然后分析字符串并获得字符串总和。

方法:综合,很容易证明我们可以通过将操作员(或其不存在)与base-3数字相关联来做到这一点。因此,我们只能在每个8位三元数字上迭代,但是我们将不再打印0、1和2,而是将" ",a"附加到字符串中的下一个数字之前。

请注意,我们实际上不需要一个字符串;也可以直接使用数字和操作员等,可以即时计算结果。我只采用了基于字符串的方法,因为它很容易解释,实施琐碎,而且它为我们提供了一些视觉反馈,这有助于理解解决方案。

现在我们已经构建了弦,我们可以将其解析;最简单的解决方案是将C标准库函数strtol()用于此目的,该功能将考虑符号,并将返回签名的整数。因此,我们可以将所有签名的整数总结在一个简单的循环中,然后完成。

代码:

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
int main()
{
    const char *ops = " +-";
    // 3 ^ 8 = 6561
    for (int i = 0; i < 6561; i++) {
        // first, generate the line
        int k = i;
        std::string line = "1";
        for (int j = 0; j < 8; j++) {
            if (k % 3)
                line += ops[k % 3];
            k /= 3;
            line += (char)('2' + j);
        }
        // now parse it
        int result = 0;
        const char *s = line.c_str();
        char *p;
        while (*s) {
            int num = strtol(s, &p, 10);
            result += num;
            s = p;
        }
        // output
        std::cout << line << " = " << result << (result == 120 ? " MATCH" : "") << std::endl;
    }
    return 0;
}

结果:

h2co3-macbook:~ h2co3$ ./quirk | grep MATCH
12-3-45+67+89 = 120 MATCH
1+2-34-5+67+89 = 120 MATCH
12-3+4+5+6+7+89 = 120 MATCH
1-23+4+56-7+89 = 120 MATCH
1+2+34-5+6-7+89 = 120 MATCH
123+4+5-6-7-8+9 = 120 MATCH
1+2-3+45+6+78-9 = 120 MATCH
12-3+45+67+8-9 = 120 MATCH
123+4-5+6-7+8-9 = 120 MATCH
123-4+5+6+7-8-9 = 120 MATCH
h2co3-macbook:~ h2co3$ 

以下bool advance(string& s)函数将为您提供所有'+''-'' '的组合,除一个任意长度外,如果没有更多,则返回false

char advance(char c)
{
    switch (c)
    {
        case ' ': return '+';
        case '+': return '-';
        default: case '-': return ' ';
    }
}
bool advance(string& s)
{
    for (int i = 0; i < s.size(); ++i)
        if ((s[i] = advance(s[i])) != ' ')
            return true;
    return false;
}

您必须首先用一个仅包含带有所需长度的空间的字符串将其馈入,然后重复"前进"它。用法:

string s = "    ";
while (advance(s))
    cout << '"' << s << '"' << endl;

以上代码将打印

"+   "
"-   "
" +  "
"++  "
"-+  "
" -  "
.
.
.
" ---"
"+---"
"----"

请注意,仅打印了仅印刷4个空间的"第一个"组合。

您可以将这些组合与您的LHS,跳过空间,产生表达式。

另一种非常相似的方法,在平原c 中,在C 中,如果您真的想要它;),有点可配置

相同的基本3数字用于列举void, 和 - 运算符的组合。

字符串被处理为添加在一起的正值或负值的列表。

另一个贡献非常紧凑且优雅,但使用一些C技巧来缩短代码。
希望这是一个更加确定的,尽管不那么美丽。

#include <iostream>
#include <string>
using namespace std;
#include <string.h>
#include <math.h>
void solver (const char * str, int result)
{
    int op_max = pow(3, strlen(str)); // number of operator permutations
    // loop through all possible operator combinations
    for (int o = 0 ; o != op_max ; o++)
    {
        int res  = 0; // computed operation result
        int sign = 1; // sign of the current value
        int val = str[0]-'0'; // read 1st digit
        string litteral;      // litteral display of the current operation
        // parse remaining digits
        int op;
        for (unsigned i=1, op=o ; i != strlen (str) ; i++, op/=3)
        {
            // get current digit
            int c = str[i]-'0';
            // get current operator
            int oper = op % 3;
            // apply operator
            if (oper == 0) val = 10*val + c;
            else
            {
                // add previous value
                litteral += sign*val;
                res += sign*val;
                // store next sign
                sign = oper == 1 ? 1 : -1;
                // start a new value
                val = c;
            }
        }   
        // add last value
        litteral += sign*val;
        res += sign*val;
        // check result
        if (res == result)
        {
            cout << litteral << " = " << result << endl;
        }
    }
}
int main(void)
{
    solver ("123456789", 120);
}

注意:尽管臭名昭著的是慢慢来,但我使用了std::string s。

最新更新