With function Groupings, function allPossibleExp can be expressed more elegantly and directly. The recursive function f can be omitted.
In[]:=
operations={func1,func2,func3,func4};
In[]:=
allPossibleExp[operands_List,operations_List]:=Apply[Union,Groupings[#,#->2&/@operations,HoldForm]&/@Permutations[operands]];
The result of this function is same as before. And operations is added as an argument. Use HoldForm to give a clear expression structure.
In[]:=
allPossibleExp[{a,b,c},operations]//Short
Out[]//Short=
{func1[a,func1[b,c]],func1[a,func1[c,b]],func1[a,func2[b,c]],186,func4[func4[b,c],a],func4[func4[c,a],b],func4[func4[c,b],a]}
In[]:=
allPossibleExp[{a,b,c},operations]//Length
Out[]=
192
As for solve function, it selects all expressions that are equal to target directly.
In[]:=
Off[General::infy];Off[General::indet];solve[operands_List,operations_List,target_]:=Select[allPossibleExp[operands,operations],ReleaseHold[#]==target&];
In[]:=
operations={Plus,Subtract,Times,Divide};
In[]:=
solve[{5,5,5,12},operations,24]
Out[]=
12,(5+5),(5+5),,,12,,
5+5
5
12
5
12
5
12
5
5+5
(5+5)12
5
5+5
5
5+5
5
12
12(5+5)
5
We can get same results as before but with some duplicate results.
In[]:=
combinations=Flatten[Table[{i,j,k,l},{i,1,13},{j,i,13},{k,j,13},{l,k,13}],3];
And we can test if this solution is faster than before.
In[]:=
Timing[Length[Select[combinations,solve[#,operations,24]=!={}&]]]
Out[]=
{371.016,1362}
The good news is the code is more short and elegant and the bad news is the computation time seems longer. Ha ha!
I think that may because Groupings do not delete duplicate elements, so we need to do that manually.
I think that may because Groupings do not delete duplicate elements, so we need to do that manually.
In[]:=
allPossibleExp[operands_List,operations_List]:=DeleteDuplicates[Apply[Union,Groupings[#,#->2&/@operations,HoldForm]&/@Permutations[operands]],ReleaseHold[#1]==ReleaseHold[#2]&];Timing[solve[{5,5,5,12},operations,24]]
Out[]=
0.421875,12
5+5
5
Compare the computation time with the function before.
allPossibleExp[operands_List,operations_List]:=Apply[Union,Groupings[#,#->2&/@operations,HoldForm]&/@Permutations[operands]];Timing[solve[{5,5,5,12},operations,24]]
Out[]=
0.0625,12,(5+5),(5+5),,,12,,
5+5
5
12
5
12
5
12
5
5+5
(5+5)12
5
5+5
5
5+5
5
12
12(5+5)
5
Unfortunately, deleting duplicate elements spent more time than before. So the former one is better. And it took about 371s to check all solvable outcomes.
The conclusion is, if more efficient algorithm but more code is preferred, use function f based on Recursion and function Outer, but if you prefer short and elegant code and do not care spending a little more time on computation, Groupings is a better choice.
Anyway, if just for one question, time gap between the two methods are narrow. I’d like to use Groupings for one or two questions and use function f for large data volume.