I am at a loss with how to solve my problem. I have a homework in which I need to simplify expressions using the rules the professor set out. I need to take strings of expressions:
"(and(x x))"
"(or (and x z) y)"
"(and (or z (not x))(or e a))"
and simplify them using rules:
(or x nil) => x;
(or nil x) => x;
(or 1 x) => 1;
(or x 1) => 1;
(and x nil) => nil;
(and nil x) => nil;
(and x 1) => x;
(and 1 x) => x;
(not nil) => 1;
(not 1) => nil;
(not (and x y)) => (or (not x) (not y));
(not (or x y)) => (and (not x) (not y));
I decided to take the expressions in the exact form that it is above (can’t be any other way), and parse it into an array, so in each index for example, it would look like this:
and or x y z //ArrayBuffer[String]
I then use a recursive function which checks the left and right expressions, until it gets the simplified expression. My problem is not with the rules, as I have figured that out. I essentially have 3 cases done, which are:
"(and z (or x y)" // the case when the left symbol is simple but the right side must be recursed
"(and (or x y) z)" // case when the right symbol is simple but the right side must be recursed
"(and x y)" // simple case where no recursion is necessary
I am missing the case when both the left and right symbols must be recursed in order to obtain those simplified symbols. I don’t have a way to know when they end or begin, and there could be many cases in which it must be recursed even within those inner expressions:
"(and (or (and x y) z)(or x a))"
"(and (or (and x y) z)(or (and y z) a))"
I have thought about how this can be done in an efficient manner with the current implementation I have, but haven’t gotten anything yet. I am asking for some advice on how to go about it. I am providing no code as I would like to get it done on my own, just need a nudge in the right direction. If clarification is needed, please ask and I will do so. Thanks again advance!
I would avoid representing an expression like this. While is is possible to unambiguously get the structure of the expression in prefix notion, it’s not quite as easy as when you have a recursive structure.
You should instead represent the expression with a recursively-defined class hierarchy. Without giving too many details, you will probably have an interface (a
Traitor abstractClass), and implementers of that interface that depend on the number of arguments: one for expressions with three parts (like ((or, x, y), or(and, (or x y), z))), one for expressions with two parts (like(not, x)), and one for expressions with one part (likex,y,z,nil, etc).Then your simplification procedure becomes one big pattern-matching method that can call itself recursively to traverse the expression’s parse tree:
EDIT: Converting the
ArrayBuffer[String]into your classes could be done with a simple recursive parsing function since you know how many arguments should be associated with each operator. You could traverse the buffer, and every time you see anandoror, you start creating a 3-part expression, every time you see anot, you start creating a 2-part expression, and you create a 1-part expression for anything else.