Subject: Re: Sudoku - A solution in XSLT 2
From: andrew welch <andrew.j.welch@xxxxxxxxx>
Date: Thu, 16 Feb 2006 14:18:42 +0000
|
> which means that fn:getGroup can be simplified to
>
> <xsl:function name="fn:getGroup" as="xs:integer+">
> <xsl:param name="board" as="xs:integer+"/>
> <xsl:param name="index" as="xs:integer"/>
> <xsl:variable name="group" select="$groups[$index]"/>
> <xsl:sequence select="$board[for $x in position() return
$groups[$x]= $group]"/>
> </xsl:function>
>
>
> where $groups is a global variable
>
> <xsl:variable name="groups" select="(
> 1,1,1, 2,2,2, 3,3,3,
> 1,1,1, 2,2,2, 3,3,3,
> 1,1,1, 2,2,2, 3,3,3,
>
> 4,4,4, 5,5,5, 6,6,6,
> 4,4,4, 5,5,5, 6,6,6,
> 4,4,4, 5,5,5, 6,6,6,
>
> 7,7,7, 8,8,8, 9,9,9,
> 7,7,7, 8,8,8, 9,9,9,
> 7,7,7, 8,8,8, 9,9,9
> )" as="xs:integer+"/>
This is a great idea :) seems so obvious now....
Also, if you process the center cells first you reduce the processing
time considerably (by around a second in my simple tests).
Replace the solveSoduko function with this one (and implement Davids
suggestions):
<xsl:function name="fn:solveSudoku" as="xs:integer+">
<xsl:param name="startBoard" as="xs:integer+"/>
<!-- First process the center cells, then do the rest of the board -->
<xsl:variable name="centerCells" select="for $x in 1 to 81 return
$x[$groups[$x] = 5]" as="xs:integer+"/>
<xsl:variable name="theRest" select="for $x in 1 to 81 return
$x[$groups[$x] != 5]" as="xs:integer+"/>
<xsl:variable name="emptyCells" select="for $x in (centerCells,
$theRest) return if ($startBoard[$x] = 0) then $x else ()"
as="xs:integer*"/>
<xsl:variable name="endBoard" select="fn:populateValues($startBoard,
$emptyCells)" as="xs:integer*"/>
<xsl:choose>
<xsl:when test="empty($endBoard)">
<xsl:message>! Invalid board - The starting board is not
correct</xsl:message>
<xsl:sequence select="$startBoard"/>
</xsl:when>
<xsl:otherwise>
<xsl:sequence select="$endBoard"/>
</xsl:otherwise>
</xsl:choose>
</xsl:function>
cheers
andrew
|