我看到了我决定尝试尝试的编程作业,这基本上是用户输入" 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。