我想将A中给出的一系列扑克牌转换为B格式,以便我可以生成结果C.
A: "(AK,AQ,(A2:*h*h)):*s*s!AsQs,(JJ:*s*h)"
B: (((AsKs union AsQs union (A2 intersect hand with two hearts)) intersect hand with two spades) less AsQs) union (JJ intersect hand with one spade one heart)
C: AsKs,JsJh
操作的优先级是
我有在B中执行操作的功能,例如Intersect(“AA”,“* s * s”)==“AsAs”,但我需要一种方法从表单A到表单B输入和相关操作,我可以按顺序执行以达到C.
我已经查看了Irony和其他一些词法分析器/解析器解决方案,但它们对于这个问题似乎有些过分。有更简单的解决方案吗?
答案 0 :(得分:2)
你可以解析A
来构造一个指令树,然后从叶子开始执行它们(因为我假设你想先执行最里面括号的内容)。对于此解析任务,您可以使用Regexes或其他任何您想要的。在我的脑海中,我认为您可以首先查找括号和运算符符号以找出树结构,然后使用实际的基本指令和每个与运算符的结点填充每个叶子。
存储A
的数据结构可以由实现接口Expression
的对象(称为IOperand
)组成;每个Expression
应该有三个字段:
Operator
,它是enum Operations {Union, Intersection, SetDiff}
的一个实例,或者只是一个字符串,具体取决于您的喜好。Operand1
和Operand2
,可以是“Ah”(定义一组卡片)或另一个Expression
。因此,它们应声明为IOperand
。你持有一套卡片的班级,比如“啊”,也应该实现这个IOperand
。接口IOperand
本身不需要做任何事情。
为了将每个给定指令与操作匹配,您可以使用简单的开关,或者Dictionary
string
(或enum
)到delegate IOperand SetOp(IOperand, IOperand);
,然后使用(匿名)函数填充Dictionary
(包含B
的说明。)
在Dictionary
的情况下,您可以简单地执行instructionList[thisExpression.Operation](thisExpression);
(这可能会更优雅地完成以避免引用thisExpression
两次)以及相应的C#转换字符串输入将被执行。
概念证明
我已经制作了一个基本实现和一个控制台应用来演示这里的用法:https://bitbucket.org/Superbest/lexer
如果你成功完成了整个练习并保持完整性(计算机会将你用作代理解析和操作库,那么祝你好运)那么最后一步应该要求你评估一个等于{的表达式{1}}然后打印刚刚输入的内容。 (当第一次运行时,您可能希望遵守程序的指令。我怀疑打破代码并获得大量异常非常容易,如果您试图考虑无效的事情,那么就会非常困惑。输入。)
如果您按原样运行代码,请尝试以下答案序列(,= Enter):
C
您的输出将是:
n, y, 2, n, n, n, y, 2, n, n, y, n, y, 2, n, n, n, n, alpha, beta, gamma
您应该能够简单地更新标记为过时且具有工作程序的方法的主体。
如果您想添加更多二进制操作,请参阅gamma
正文中的TODO。从我已经做过的三个操作中可以看出适当的语法;实际上,代码仅支持二进制操作。如果您的方法使用字符串,则可以使用Simplification.Simplification()
字段。
答案 1 :(得分:1)
我想出了这个解决方案(使用Superbest的答案中的树形思想)。任何关于你会改变的事情的评论都将不胜感激!
public class Node
{
private string mStr;
private string mOperation;
private List mChildren = new List();
//private Collection mCollection = new Collection();
public Node(string input)
{
mStr = Regex.Replace(input, @"^\(([^\(\)]*)\)$", "$1");
Init();
}
private void Init()
{
Split(mStr);
return;
}
public Collection GenerateHands()
{
Collection collection = new Collection();
if (Children == 0) { collection.Add(mStr); }
if (Children > 0)
{
if (mOperation == "union") { collection = mChildren.ElementAt(0).GenerateHands().Union(mChildren.ElementAt(1).GenerateHands()); }
if (mOperation == "intersect") { collection = mChildren.ElementAt(0).GenerateHands().Intersect(mChildren.ElementAt(1).GenerateHands()); }
if (mOperation == "less") { collection = mChildren.ElementAt(0).GenerateHands().Less(mChildren.ElementAt(1).GenerateHands()); }
}
return collection;
}
public string PrettyPrint()
{
string print = "";
if (Children == 0) { print += mStr; }
if (Children > 0)
{
if (mChildren.ElementAt(0).Children > 0) { print += "("; }
print += mChildren.ElementAt(0).PrettyPrint();
if (mChildren.ElementAt(0).Children > 0) { print += ")"; }
if (Children > 0) { print += " " + mOperation + " "; }
if (mChildren.ElementAt(1).Children > 0) { print += "("; }
print += mChildren.ElementAt(1).PrettyPrint();
if (mChildren.ElementAt(1).Children > 0) { print += ")"; }
}
return print;
}
private void Split(string s)
{
// WARNING: Either could pass a,aa or a:aa
// WARNING: This can hand down a 0 length string if ',' is at beginning or end of s.
if (CommaOutsideBrackets(s) >= 0)
{
mChildren.Add(new Node(s.Substring(0, CommaOutsideBrackets(s))));
mChildren.Add(new Node(s.Substring(CommaOutsideBrackets(s) + 1, s.Count() - CommaOutsideBrackets(s) - 1)));
mOperation = "union";
}
// WARNING: This could throw negative if for example (aaaa)bb
else if (OperatorOutsideBrackets(s) >= 0)
{
mChildren.Add(new Node(s.Substring(0, OperatorOutsideBrackets(s))));
mChildren.Add(new Node(s.Substring(OperatorOutsideBrackets(s) + 1, s.Count() - OperatorOutsideBrackets(s) - 1)));
if (s[OperatorOutsideBrackets(s)] == '!') { mOperation = "less"; }
if (s[OperatorOutsideBrackets(s)] == ':') { mOperation = "intersection"; }
}
// We must be done?
else
{
}
}
private int CommaOutsideBrackets(string s)
{
int countRound = 0, countSquare = 0;
for (int i = 0; i = 0; i--)
{
if (s[i] == '!' || s[i] == ':') { return i; }
}
return -1;
}
public string Str
{
get { return mStr; }
}
public int Children
{
get { return mChildren.Count; }
}
}