我看到了一个我决定尝试的编程任务,它基本上是用户输入类似“123456789 = 120”的东西,并且程序必须在不同位置插入“+”或“ - ”来制作语句真正。例如,在这种情况下,它可以做123 + 4-5 + 6-7 + 8-9 = 120.只有3 ^ 8种可能的组合,所以我认为可以蛮力它,但我不喜欢我不知道我可以进入的顺序/如何实际实现它。更具体地说,我不知道在插入'+'和' - '时我会采用什么顺序。这就是我所拥有的:
#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;
}
答案 0 :(得分:1)
基本想法:生成+
,-
运算符的所有可能变体(包括缺少运算符的情况),然后解析字符串并获取总和。
方法:组合地,很容易证明我们可以通过将运算符(或不存在运算符)与基数为3的数字相关联来实现。因此,我们可以迭代每个8位三进制数,但不是打印0,1和2,而是在字符串中的下一个数字之前附加“+”,“ - ”或任何内容。
请注意,我们 实际上需要一个字符串;也可以直接使用数字和运算符等,即时计算结果。我只采用基于字符串的方法,因为它解释起来很简单,实现起来很简单,另外,它给了我们一些视觉反馈,这有助于理解解决方案。
现在我们已经构造了我们的字符串,我们可以解析它;最简单的解决方案是使用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$
答案 1 :(得分:0)
以下bool advance(string& s)
函数会为您提供除{1}之外的任意长度的'+'
,'-'
和' '
字符串的所有组合,如果不再有,则返回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交叉,跳过空格,以生成表达式。
答案 2 :(得分:0)
另一个非常类似的方法, in plain C OK,在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
的懒惰,虽然它们的速度非常慢。