I was challenged with a CS problem.
The problem consists of recursively finding which expressions of the form ((10+10)/(10+10)) produces a number. For example, ((10+10)/(10+10)) produces 1. Find all the other expressions using the operators +, -, *, /, with 4 numbers of 10, and all the combinations of parentheses to enforce orders of operations.
I was referred to the Reverse Polish Notation, but that relies on postfix notation, which isn’t required to solve this problem.
Some pseudocode I have is this. I know using recursion is the easiest way to solve this problem. But don't know how to make sure I get all combinations.
build([10,10,10,10], Expression) :-
Operator
/ \
[10] [10,10,10]
Operator
/ \
[10] [10,10]
Operator
/ \
[10] [10]
This is a problem I am trying to solve in Prolog but C++ is good as well.
I have a partial solution which I will outline here and hopefully it will get you moving and you can find the complete solution.
The first tool you need is the ability to make some expressions:
This defines
build_expr/3
, which takes two variables or expressions and produces a new expression. This is how we are going to permute the operators. Now we need a way to handle the lists, so let's definebuild_expr/2
that operates on a list at once:Let's get a few solutions so we get the flavor of what it's doing:
This looks pretty good to me. But like I said, I'm only generating the right-leaning tree. You will have to modify or replace
build_expr/2
to produce the other shapes, if they actually matter (which I'm not convinced they do).Now let's make the next step simpler by bundling in evaluation:
Now we should be able to find all the unique solutions using
setof/3
:Oops. Division by zero error. No problem, let's catch that and fail in those cases instead:
I fiddled with the formatting there a little, but I think that's a pretty good solution, but I can already see one missing solution: (10+10)*(10+10)=400. So you will have to get more creative with
build_expr/2
to make it produce other shapes of tree.Edit: Adding the rest of the solutions
I found an answer by @gusbro that gives a way to enumerate the trees. I wasn't able to get it to work with the recursive trickery I was doing there (maybe someone else will show me a very easy trick) but I was able to adapt his answer to your problem, to wit:
Why am I using
[L0|LR]
and[R0|RR]
instead ofLeftList
andRightList
or some such? This is how I'm turning @gusbro's numeric constraints into list length constraints and ensuring that I always have at least one element in both the left and right lists, so my recursive calls tobuild_tree/2
will succeed.Simplifying
build_expr/3
from above down to a single operator you can see this generates all the various flavors you'd expect:Switch it back, because we're still using the
build_expr/3
function from the earlier example. I have simplified the evaluation somewhat using thisbuild_eval/2
predicate:Here's what the final solution looks like:
Wow, quite a few alternatives, 68 to be exact!