Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I wrote the solver you mentioned at the end of your post, and I apologise in advance that the code isn't very readable.</p> <p>At its heart the code for any solver to this sort of problem is simply a depth-first search, which you imply you already have working.</p> <p>Note that if you go with your "solution WITHOUT the use of parentheses, which is solved from left to right" then there are input sets which are not solvable. For example, 11,11,11,11,11,11 with a target of 144. The solution is ((11/11)+11)*((11/11)+11). My solver makes this easier for humans to understand by breaking the parentheses up into different lines, but it is still effectively using parentheses rather than evaluating from left to right.</p> <p>The way to "use parentheses" is to apply an operation to your inputs and put the result back in the input bag, rather than to apply an operation to one of the inputs and an accumulator. For example, if your input bag is 1,2,3,4,5,6 and you decide to multiply 3 and 4, the bag becomes 1,2,12,5,6. In this way, when you recurse, that step can use the result of the previous step. Preparing this for output is just a case of storing the history of operations along with each number in the bag.</p> <p>I imagine what you mean about more "sophisticated" solutions is just the simplicity heuristic used in my javascript solver. The solver works by doing a depth-first search of the entire search space, and then choosing the solution that is "best" rather than just the one that uses the fewest steps.</p> <p>A solution is considered "better" than a previous solution (i.e. replaces it as the "answer" solution) if it is closer to the target (note that <em>any</em> state in the solver is a candidate solution, it's just that most are further away from the target than the previous best candidate solution), or if it is equally distant from the target and has a lower heuristic score.</p> <p>The heuristic score is the sum of the "intermediate values" (i.e. the values on the right-hand-side of the "=" signs), with trailing 0's removed. For example, if the intermediate values are 1, 4, 10, 150, the heuristic score is 1+4+1+15: the 10 and the 150 only count for 1 and 15 because they end in zeroes. This is done because humans find it easier to deal with numbers that are divisible by 10, and so the solution appears "simpler".</p> <p>The other part that could be considered "sophisticated" is the way that some lines are joined together. This simply joins the result of "5 + 3 = 8" and "8 + 2 = 10" in to "5 + 3 + 2 = 10". The code to do this is absolutely horrible, but in case you're interested it's all in the Javascript at <a href="https://github.com/jes/cntdn/blob/master/js/cntdn.js" rel="nofollow">https://github.com/jes/cntdn/blob/master/js/cntdn.js</a> - the gist is that after finding the solution which is stored in array form (with information about how each number was made) a bunch of post-processing happens. Roughly:</p> <ul> <li>convert the "solution list" generated from the DFS to a (rudimentary, nested-array-based) expression tree - this is to cope with the multi-argument case (i.e. "5 + 3 + 2" is not 2 addition operations, it's just one addition that has 3 arguments)</li> <li>convert the expression tree to an array of steps, including sorting the arguments so that they're presented more consistently </li> <li>convert the array of steps into a string representation for display to the user, including an explanation of how distant from the target number the result is, if it's not equal</li> </ul> <p>Apologies for the length of that. Hopefully some of it is of use.</p> <p>James</p> <p>EDIT: If you're interested in Countdown solvers in general, you may want to take a look at my letters solver as it is far more elegant than the numbers one. It's the top two functions at <a href="https://github.com/jes/cntdn/blob/master/js/cntdn.js" rel="nofollow">https://github.com/jes/cntdn/blob/master/js/cntdn.js</a> - to use call solve_letters() with a string of letters and a function to get called for every matching word. This solver works by traversing a trie representing the dictionary (generated by <a href="https://github.com/jes/cntdn/blob/master/js/mk-js-dict" rel="nofollow">https://github.com/jes/cntdn/blob/master/js/mk-js-dict</a>), and calling the callback at every end node.</p>
    singulars
    1. This table or related slice is empty.
    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.
 

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