具有过度约束类的噩梦表达式树
我无意中让我的学生过度约束用于解决以下问题的共享类。我意识到这可能是该网站的用户可能喜欢的一个问题。
第一个团队/函数 getNodes 采用一个表示使用有符号整数和四个操作 +、-、* 和 / 的前缀表达式的字符串,并使用 Node 类生成相应的以空结尾的标记链表,其中标记通过“右”指针。
第二个团队/函数 getTree 采用类似的字符串,将其传递给 getNodes,并将结果节点重新链接为表达式树。
第三个团队/函数,evaluate,采用类似的字符串,将其传递给 getTree,并评估结果表达式树以形成答案。
过度约束的 exptree.h 如下。这个问题必须通过只编写上面定义的三个函数来解决,不需要额外的函数。
#ifndef EXPTREE_H_
#define EXPTREE_H_
using namespace std;
enum Ops{ADD, SUB, MUL, DIV, NUM};
class Node {
private:
int num;
Ops op;
Node *left, *right;
public:
friend Node *getNodes(string d);
friend Node *getTree(string d);
friend int evaluate (string);
};
int evaluate(string d);
Node *getNodes(string d);
Node *getTree(string d);
#endif
唯一可以使用的库是这些。
#include <iostream>
#include <vector>
#include <string>
#include "exptree.h"
对于那些担心我的学生的人,我今天将指出,只需几个更合适的函数就可以轻松解决这个问题。我知道表达式树可以编码有理数而不仅仅是整数。今天我也会指出这一点。
这是我根据他们的规格给他们的驱动程序。
#include <iostream>
#include <string>
#include "exptree.h"
using namespace std;
void test(string s, int target) {
int result = evaluate(s);
if (result == target)
cout << s << " correctly evaluates to " << target << endl;
else
cout << s << "(" << result
<< ") incorrectly evaluates to " << target << endl;
}
int main() {
test("42", 42);
test("* - / 4 2 1 42", 42);
test("* - / -4 +2 -1 2", -2);
test("* - / -4 +2 -1 2 ", -2);
test("* 9 6", 54);
return 0;
}
你能以尽可能优雅的方式编写这三个函数来解决这个噩梦般的问题吗?
I inadvertently let my students overconstrain a shared class used to solve the following problem. I realized it might be a problem denizens of this site might enjoy.
The first team/function, getNodes, takes a string representing a prefix expression using signed integers and the four operations +, -, *, and / and produces the corresponding null terminated linked list of tokens, using the class Node, with tokens linked through the "right" pointer.
The second team/function, getTree, takes a similar string, passes it to getNodes, and relinks the resultant nodes to be an expression tree.
The third team/function, evaluate, takes a similar string, passes it to getTree, and evaluates the resultant expression tree to form an answer.
The over-constrained exptree.h follows. The problem has to be solved by writing just the three functions defined above, no additional functions.
#ifndef EXPTREE_H_
#define EXPTREE_H_
using namespace std;
enum Ops{ADD, SUB, MUL, DIV, NUM};
class Node {
private:
int num;
Ops op;
Node *left, *right;
public:
friend Node *getNodes(string d);
friend Node *getTree(string d);
friend int evaluate (string);
};
int evaluate(string d);
Node *getNodes(string d);
Node *getTree(string d);
#endif
The only libraries that can be used are these
#include <iostream>
#include <vector>
#include <string>
#include "exptree.h"
For those of you worried about my students, I will be pointing out today how just a couple of more well placed functions would allow this problem to be easily solved. I know the expression tree can code rational numbers and not just integers. I'll be pointing that out today as well.
Here is the driver program I gave them based on their specs.
#include <iostream>
#include <string>
#include "exptree.h"
using namespace std;
void test(string s, int target) {
int result = evaluate(s);
if (result == target)
cout << s << " correctly evaluates to " << target << endl;
else
cout << s << "(" << result
<< ") incorrectly evaluates to " << target << endl;
}
int main() {
test("42", 42);
test("* - / 4 2 1 42", 42);
test("* - / -4 +2 -1 2", -2);
test("* - / -4 +2 -1 2 ", -2);
test("* 9 6", 54);
return 0;
}
Can you write the three functions in as elegant a fashion as possible to solve this nightmarish problem?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在这些约束下编写
getNodes
和getTree
函数将非常简单,因此我直接跳到有趣的部分。您自然会递归地计算表达式树,但这不是这里的一个选项,因为 eval 函数只接受一个字符串。当然,您可以将剩余的树重新字符串化为前缀表达式,并对其递归调用 eval,但这只是愚蠢的。首先,我将表达式树转换为后缀表达式,使用显式堆栈作为穷人的递归。然后我使用标准操作数堆栈对其进行评估。
The
getNodes
andgetTree
functions would be pretty trivial to write under these constraints, so I just skipped ahead to the interesting part. You would naturally evaluate an expression tree recursively, but that is not an option here because the eval function only takes a string. Sure, you could restringify the remaining tree into a prefix expression and call eval recursively on that, but that would just be stupid.First, I convert the expression tree into a postfix expression, using an explicit stack as the poor man's recursion. Then I evaluate that with the standard operand stack.
我认为“没有附加功能”这个要求太苛刻了。实现 getTree 的最简单方法可能是递归,并且需要定义一个附加函数。
我可以通过使用显式堆栈(由 std::vector 实现)来实现递归,但这很丑陋且晦涩(除非您希望学生完全练习这一点)。
I think that "no additional functions" is a too tough requirement. The easiest way to implement e.g.
getTree
is probably recursive, and it requires defining an additional function.I could implement recursion by using an explicit stack (implemented by
std::vector
) but that is ugly and obscure (unless you want you students to practice exactly that).就其价值而言,这是我在发布问题之前编写的解决方案
For what its worth, here is the solution I coded up just before I posted the question