[Home] [By Thread] [By Date] [Recent Entries]
On 9/4/07, Alain <alainb06@xxxxxxx> wrote:
> I think there's a "missing feature" in XSL (or I just haven't found it)[snip] > Well, don't tell me it is a bad algorithm, I know it ! It is just "brute[snip] > You had the "fun" part, now comes the question. Have a look at: http://andrewjwelch.com/code/xslt/sudoku/sudoku-solver.html Hi Andrew, very nice program ! And I'm reassured about my question (Sudoku was just the example). If I understood your algorithm correctly Andrew, you used the technique I named "clean" to end the recursion. That is, if you go down to the part where your "brute force" algorithm is (function tryValues), you : - recurse 1 by 1 on empty cells (because you have to, that's how it works !) - and also recurse 1 by 1 on possible values (because of what I called the XSL limitation) Let's step down the algorithm to point out the things we have to do to work around the limitation I'm pointing. When you come to the point where you have to use "brute force", let's say your first emptyCells has (4, 7, 9) as possibleValues. Your stack : [...] fn:populateValues => stack params : board => stack params : emptyCell => stack params : (4,7,9) => call fn:tryValues
You then enter the xsl:choose in your tryValues which calls itself recursively. New stack at this point : [...] fn:populateValues => stack params : board => stack params : emptyCell => stack params : (4,7,9) => call fn:tryValues ====> stack params : board ====> stack params : emptyCell ====> stack params : (7, 9) ====> call fn:tryValues
Here we don't really care, because we are speaking of stacking 3 sequences of integers, let's say around 1KB of data plus function call overhead. But if we had bigger recursions this bad construct will quickly lead to stack-overflow ! Andrew, when I wrote "bad construct", I don't mean your program is bad at all! On the contrary it looks fine to me, especially because being still novice, a specialist as you are came to the same solution as mine for the end of recursion. So it might be the unique normalised solution because of limitations of loop constructs in XSL (they don't allow to "see" the variables build in previous iterations). If you could have used a for-each, instead of a recurse 1 by 1, it would have saved stack... and may be time (for your contest) as stack/heaping sequences and calling is certainly longer than a test.
Documentation of Saxon 7.5 has : saxon:assignable saxon:assign As the documentation says, these extensions "cheat" XSL. But hey, when there are limitations and the only way is to "cheat", we might just use them (reasonably)! So now I have to try if they still work with saxon 8.9 With that, your function tryValues can do <!-- global variable to end recursion --> <xsl:variable name="theEnd" select="false()" saxon:assignable="yes"/> <xsl:function name="tryValues"> [snip params] <xsl:for-each select="$possibleValues> <xsl:if test="not($theEnd)"> [snip your code]
[... and no more need to recurse on tryvalues for possibleValues
here, that's what the for-each does properly, with the
intial test to stop the unnecessary recursions !]</xsl:if> </for:each> </xsl:function> In the function populateValues, when you found the solution, you do a saxon:assign to theEnd and set it to true().
So, Andrew, if the exact rules of your contest were to be XSLT2.0-every-processor compliant you are stuck... but if you were allowed to use whichever XSL processor you like, you might get a try removing the "useless" recursion, although I'm quite sure the time difference won't be noticeable at the precision of your computer's clock ! Alain.
|

Cart



