Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h1>Using RPN (reverse Polish Notation) </h1> <p></p> <p>For RPN intro see <a href="http://en.wikipedia.org/wiki/Reverse_Polish_notation" rel="noreferrer">here</a>.</p> <p></p> <h2>The Problem size</h2> <p>We have to build a list of four numbers, which implies 3 operators.<br> Those numbers and operators will be pushed or executed against a stack. </p> <p>Lets call the list of execution {a1 a2 a3 a4 a5 a6 a7}.</p> <p>{a1 a2} should be numbers, as there are no unary operations on the stack.</p> <p>{a7} should be an operator, to complete the operation.</p> <p>For {a3, a4, a5, a6} we have several options, but always at least two numbers must be in the stack to be able to operate. So the possible combinations are: (N= number, O=Operator) </p> <p>{N N O O}, {N O N O}, {O N O N}, {O N N O} and {N O O N}. </p> <p>The combination {O O N N} is forbidden because the stack is empty for the second O.</p> <p>So we have: </p> <blockquote> <pre><code> | {N N O O} | | {N O N O} | {N N} | {O N O N} | {O} | {O N N O} | | {N O O N} | </code></pre> </blockquote> <p>Now we will count the possible arrangements. Of course we are over counting because the commutative operator (Plus and Times) may cut the permutation tree in half, but the problem is small enough not to be bother by that. (We are also overcounting in those cases where the sequence is {O O}. but we simply go on ..)</p> <p>We have to choose 2 numbers in four for the first segment, that's <b>12</b> possible arrangements.</p> <p>For the middle segment, the two remaining numbers may only be permuted, that is a factor <b>2</b></p> <p>But we have another factor <b>5</b> for counting the five alternatives for the middle segment.</p> <p>For the three operators, as they may repeat we have a factor <b>4^3=64</b></p> <p>So the size of the problem is the product of the numbers in bold:12 2 5 64 =<b> 7680</b>. No optimization is needed, we may go ahead by brute force.</p> <p>The rest of the problem is to build the 7680 arrangements and the RPN evaluator. Both relatively easy tasks. </p> <p>I'll post it ...it's still a draft but here is too late! Will follow tomorrow!</p> <h2>Edit: RPN Evaluator</h2> <p>Here is the code for the recursive RPN evaluator. I choose to do it in a functional language (<a href="http://www.wolfram.com/" rel="noreferrer">Mathematica</a>) to simplify the operator parsing </p> <pre><code>rpn[listipt_, stackipt_: {}] := Module[{list=listipt,stack=stackipt}, (*recursive rpn evaluator*) If[list == {}, Return[stack[[1]]]]; (*end*) If[NumberQ[list[[1]]], (*if numeric*) Return@rpn[Rest[list], PrependTo[stack,list[[1]]]]; (*push nbr and recurse*) , (stack[[2]]=list[[1]][stack[[2]], stack[[1]]]; (*if not, operate*) Return@rpn[Rest[list], Rest[stack]];); (*and recurse*) ]; ]; </code></pre> <p>Usage examples</p> <pre><code>rpn[{1, 1, 1, Plus, Plus}] 3 rpn[{2, 2, 2, Plus, Plus}] 6 rpn[{2, 3, 4, Plus, Times}] (* (4+3)*7 *) 14 rpn[{2, 3, 4, Plus, Divide}] (* (2+3)/4 *) 2/7 </code></pre> <p>a bit later I'll post the tuples generator, show that they are 7680 and some funny results about the distribution of the possible results of the operations (in fact for the {1,2,3,4} set you can only get 230 different results!).</p> <h2> Edit : Tuples construction </h2> <p>First we explicitly construct the possibilities for the middle segment</p> <pre><code>t1 = {{n3, n4, o1, o2}, {n3, o1, n4, o2}, {o1, n3, o2, n4}, {o1, n3, n4, o2}, {n3, o1, o2, n4}}; </code></pre> <p>Now we prepend the two variations for {n1,n2} and the last operator</p> <pre><code>t2 = Join[Map[Join[{n1, n2}, #, {o3}] &amp;, t1], Map[Join[{n2, n1}, #, {o3}] &amp;, t1]] ( bahh ... don't mind the code*) </code></pre> <p>Resulting in our 10 different configurations</p> <p><img src="https://i.stack.imgur.com/Qa1Me.png" alt="alt text"></p> <p>Now we have to populate all those configurations with all the possible permutations of the numbers and operators.</p> <p>We first construct all number permutations as assignment rules for our tuples</p> <pre><code> repListNumbers = (*construct all number permutations*) Table[{n1 -&gt; #[[1]], n2 -&gt; #[[2]], n3 -&gt; #[[3]], n4 -&gt; #[[4]]} &amp;[i], {i, Permutations[{1, 2, 3, 4}]}]; </code></pre> <p>These little beast have the form</p> <pre><code> {n1 -&gt; 1, n2 -&gt; 2, n3 -&gt; 3, n4 -&gt; 4} </code></pre> <p>And we can use them to replace vallues in our tuples. For example:</p> <pre><code> {n1,n2,n3,o1,o2,n4,o3} /. {n1 -&gt; 1, n2 -&gt; 2, n3 -&gt; 3, n4 -&gt; 4} </code></pre> <p>Results in </p> <pre><code> {1,2,3,o1,o2,4,o3} </code></pre> <p>Of course we may have constructed the replacement rules as a function to be able to change the number set at will. We do now something similar with the operators</p> <pre><code>repListOps = (*Construct all possible 3 element tuples*) Table[{o1 -&gt; #[[1]], o2 -&gt; #[[2]], o3 -&gt; #[[3]]} &amp;[i], {i, Tuples[{Plus, Times, Divide, Subtract}, 3]}]; </code></pre> <p>So we get a collection of things like </p> <pre><code> {o1-&gt;Plus, o2-&gt;Plus, o3-&gt;Divide} </code></pre> <p>Now we combine our tuples and all our replacement rules in one big list:</p> <pre><code>t3 = Flatten[t2 /. repListNumbers /. repListOps, 2]; </code></pre> <p>Which results in 15360 different calculations. But we know that there overcounted for a factor of two, so now we drop the repeated elements:</p> <pre><code>t3 =Union[t3] </code></pre> <p>And that give us our expected <b>7680</b> elements.</p> <p>There are still some overcounting, because {2,3,Times} = {3,2,Times} = 6, but that is ok for our current purpouses.</p> <h2> Evaluating the results</h2> <p>Now we have our RPN evaluator and all those tuples, and we want to know if a certain final result is possible.</p> <p>We simply have to ask if that number is contained in the set of results:</p> <pre><code>In[252]:= MemberQ[rpn /@ t3, 24] Out[252]= True In[253]:= MemberQ[rpn /@ t3, 38] Out[253]= False </code></pre> <p>In fact the bounds for the result set are:</p> <pre><code>In[254]:= Max[rpn /@ t3] Out[254]= Max[36, ComplexInfinity] In[255]:= Min[rpn /@ t3] Out[255]= Min[-23, ComplexInfinity] </code></pre> <p>The infinity results are due to the fact that I didn't care about divisions by zero, so they are there , just inside the set. The numeric interval is [-23,36].</p> <p>If you want to know how many of the results are equal to 24, just count them</p> <pre><code> In[259]:= Length@Select[t3, rpn[#] == 24 &amp;] Out[259]= 484 </code></pre> <p>Of course many of them are trivial permutations due to the commutative properties of "Plus" and "Times", but not all:</p> <pre><code> {1, 2, Plus, 3, Plus, 4, Times} -&gt; ((1+2)+3)*4 = 24 {2, 1, 4, 3, Times, Divide, Divide} -&gt; 2/(1/(4*3)) = 24 </code></pre> <p>There are none sequence using "Subtract" that gives 24!</p> <pre><code> In[260]:= MemberQ[Flatten@Select[t3, rpn[#] == 24 &amp;], Subtract] Out[260]= False </code></pre> <h2>Results Spectrum sample</h2> <p><img src="https://i.stack.imgur.com/aJ702.png" alt="alt text"></p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload