*** sudoku.orig.xslt	2018-06-14 07:56:51.000000000 +0200
--- sudoku.xslt	2018-06-14 09:26:03.131234570 +0200
***************
*** 1,4 ****
! <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="sudoku" xmlns:saxon="http://saxon.sf.net/" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0" exclude-result-prefixes="xs" extension-element-prefixes="saxon fn">
  
  <xsl:param name="board" select="(
  7,0,0, 3,0,2, 0,5,0,
--- 1,4 ----
! <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fn="sudoku" xmlns:xs="http://www.w3.org/2001/XMLSchema" version="2.0" exclude-result-prefixes="xs" extension-element-prefixes="fn">
  
  <xsl:param name="board" select="(
  7,0,0, 3,0,2, 0,5,0,
***************
*** 30,56 ****
  <xsl:variable name="bottomGroup" select="(58, 59, 60, 67, 68, 69, 76, 77, 78)" as="xs:integer+" />
  <xsl:variable name="bottomRightGroup" select="(61, 62, 63, 70, 71, 72, 79, 80, 81)" as="xs:integer+" />
  
! <xsl:function name="fn:getRowStart" as="xs:integer+" saxon:memo-function="yes">
      <xsl:param name="index" as="xs:integer" />
      <xsl:sequence select="xs:integer(floor(($index - 1) div 9) * 9) + 1" />
  </xsl:function>
  
! <xsl:function name="fn:getRowNumber" as="xs:integer+" saxon:memo-function="yes">
      <xsl:param name="index" as="xs:integer" />
      <xsl:sequence select="(($index - 1) idiv 9) + 1" />
  </xsl:function>
  
! <xsl:function name="fn:getColNumber" as="xs:integer+" saxon:memo-function="yes">
      <xsl:param name="index" as="xs:integer" />
      <xsl:sequence select="(($index - 1) mod 9) + 1" />
  </xsl:function>
  
! <xsl:function name="fn:getRowIndexes" as="xs:integer+" saxon:memo-function="yes">
      <xsl:param name="index" as="xs:integer+" />
      <xsl:sequence select="fn:getRowStart($index) to fn:getRowStart($index) + 8" />
  </xsl:function>
  
! <xsl:function name="fn:getColIndexes" as="xs:integer+" saxon:memo-function="yes">
      <xsl:param name="index" as="xs:integer+" />
      <xsl:variable name="gap" select="($index - 1) mod 9" as="xs:integer" />
      <xsl:sequence select="for $x in $rowStarts return $x + $gap" />
--- 30,62 ----
  <xsl:variable name="bottomGroup" select="(58, 59, 60, 67, 68, 69, 76, 77, 78)" as="xs:integer+" />
  <xsl:variable name="bottomRightGroup" select="(61, 62, 63, 70, 71, 72, 79, 80, 81)" as="xs:integer+" />
  
! <xsl:template name="message">
!     <xsl:param name="msg" as="xs:string" required="yes"/>
!     <xsl:param name="severity" as="xs:string" select="'INFO'"/> <!-- INFO or ERROR -->
!     <xsl:message select="$msg"/>
! </xsl:template>
!     
! <xsl:function name="fn:getRowStart" as="xs:integer+"> <!-- saxon:memo-function="yes" -->
      <xsl:param name="index" as="xs:integer" />
      <xsl:sequence select="xs:integer(floor(($index - 1) div 9) * 9) + 1" />
  </xsl:function>
  
! <xsl:function name="fn:getRowNumber" as="xs:integer+"> <!-- saxon:memo-function="yes" -->
      <xsl:param name="index" as="xs:integer" />
      <xsl:sequence select="(($index - 1) idiv 9) + 1" />
  </xsl:function>
  
! <xsl:function name="fn:getColNumber" as="xs:integer+"> <!-- saxon:memo-function="yes" -->
      <xsl:param name="index" as="xs:integer" />
      <xsl:sequence select="(($index - 1) mod 9) + 1" />
  </xsl:function>
  
! <xsl:function name="fn:getRowIndexes" as="xs:integer+"> <!-- saxon:memo-function="yes" -->
      <xsl:param name="index" as="xs:integer+" />
      <xsl:sequence select="fn:getRowStart($index) to fn:getRowStart($index) + 8" />
  </xsl:function>
  
! <xsl:function name="fn:getColIndexes" as="xs:integer+"> <!-- saxon:memo-function="yes" -->
      <xsl:param name="index" as="xs:integer+" />
      <xsl:variable name="gap" select="($index - 1) mod 9" as="xs:integer" />
      <xsl:sequence select="for $x in $rowStarts return $x + $gap" />
***************
*** 69,75 ****
      <xsl:sequence select="for $x in $colIndexes return $board[$x]" />
  </xsl:function>
  
! <xsl:function name="fn:getGroupIndexes" as="xs:integer+" saxon:memo-function="yes">
      <xsl:param name="index" as="xs:integer+" />
      <xsl:choose>
          <xsl:when test="$index = $topLeftGroup">
--- 75,81 ----
      <xsl:sequence select="for $x in $colIndexes return $board[$x]" />
  </xsl:function>
  
! <xsl:function name="fn:getGroupIndexes" as="xs:integer+"> <!-- saxon:memo-function="yes" -->
      <xsl:param name="index" as="xs:integer+" />
      <xsl:choose>
          <xsl:when test="$index = $topLeftGroup">
***************
*** 109,115 ****
      <xsl:sequence select="for $x in $groupIndexes return $board[$x]" />
  </xsl:function>
  
! <xsl:function name="fn:getOtherValuesInTriple" as="xs:integer+" saxon:memo-function="yes">
      <xsl:param name="num" as="xs:integer" />
      <xsl:sequence select="(xs:integer(((($num -1) idiv 3) * 3) + 1) to xs:integer(((($num - 1) idiv 3) * 3) + 3))[. ne $num]" />
  </xsl:function>
--- 115,121 ----
      <xsl:sequence select="for $x in $groupIndexes return $board[$x]" />
  </xsl:function>
  
! <xsl:function name="fn:getOtherValuesInTriple" as="xs:integer+"> <!-- saxon:memo-function="yes" -->
      <xsl:param name="num" as="xs:integer" />
      <xsl:sequence select="(xs:integer(((($num -1) idiv 3) * 3) + 1) to xs:integer(((($num - 1) idiv 3) * 3) + 3))[. ne $num]" />
  </xsl:function>
***************
*** 120,126 ****
      <xsl:sequence select="for $x in fn:getOtherValuesInTriple($index) return $board[$x]" />
  </xsl:function>
  
! <xsl:function name="fn:getCellIndexesOfColFriends" as="xs:integer+" saxon:memo-function="yes">
      <xsl:param name="index" as="xs:integer" />
      <xsl:sequence select="for $x in fn:getOtherValuesInTriple(fn:getRowNumber($index)) return (($x * 9) - 8) + (($index - 1) mod 9)" />
  </xsl:function>
--- 126,132 ----
      <xsl:sequence select="for $x in fn:getOtherValuesInTriple($index) return $board[$x]" />
  </xsl:function>
  
! <xsl:function name="fn:getCellIndexesOfColFriends" as="xs:integer+"> <!-- saxon:memo-function="yes" -->
      <xsl:param name="index" as="xs:integer" />
      <xsl:sequence select="for $x in fn:getOtherValuesInTriple(fn:getRowNumber($index)) return (($x * 9) - 8) + (($index - 1) mod 9)" />
  </xsl:function>
***************
*** 197,204 ****
  </xsl:function>
  
  
! <xsl:function name="fn:removeNakedTuples" as="element()+">
!     <xsl:param name="emptyCellsXML" as="element()+" />
      <xsl:variable name="allowedValuesTable" as="element()+">
              <byRow>
                  <xsl:for-each select="$rowStarts">
--- 203,216 ----
  </xsl:function>
  
  
!     <!-- Pieter Masereeuw (June 14, 2018), changed fn:removeNakedTuples type to element()* instead of element()+ because we get an exception at the 2006 "Extremely hard board".
!          Don't know if this change is OK or if there is some deeper problem.
!     -->
!     <xsl:function name="fn:removeNakedTuples" as="element()*">
!     <!-- Pieter Masereeuw (June 14, 2018), changed emptyCellsXML type to element()* instead of element()+ because we get an exception at the 2006 "Extremely hard board".
!          Don't know if this change is OK or if there is some deeper problem.
!     -->
!     <xsl:param name="emptyCellsXML" as="element()*" />
      <xsl:variable name="allowedValuesTable" as="element()+">
              <byRow>
                  <xsl:for-each select="$rowStarts">
***************
*** 229,235 ****
              </byBlock>
      </xsl:variable>
  
!     <xsl:variable name="newTable" as="element()+">
          <xsl:for-each select="$allowedValuesTable/row">
              <xsl:call-template name="nakedTuples" />
          </xsl:for-each>
--- 241,250 ----
              </byBlock>
      </xsl:variable>
  
!     <!-- Pieter Masereeuw (June 14, 2018), changed newTable type to element()* instead of element()+ because we get an exception at the 2006 "Easy board".
!          Don't know if this change is OK or if there is some deeper problem.
!     -->
!     <xsl:variable name="newTable" as="element()*">
          <xsl:for-each select="$allowedValuesTable/row">
              <xsl:call-template name="nakedTuples" />
          </xsl:for-each>
***************
*** 240,247 ****
              <xsl:call-template name="nakedTuples" />
          </xsl:for-each>
      </xsl:variable>
! 
!     <xsl:variable name="newDistinctTable" as="element()+">
          <xsl:for-each-group select="$newTable" group-by="@index">
              <xsl:copy-of select="current-group()[@possibleValues = min(current-group()/@possibleValues)][1]" />
          </xsl:for-each-group>
--- 255,265 ----
              <xsl:call-template name="nakedTuples" />
          </xsl:for-each>
      </xsl:variable>
!     
!     <!-- Pieter Masereeuw (June 14, 2018), changed newDistinctTable type to element()* instead of element()+ because we get an exception at the 2006 "Easy board".
!          Don't know if this change is OK or if there is some deeper problem.
!     -->
!     <xsl:variable name="newDistinctTable" as="element()*">
          <xsl:for-each-group select="$newTable" group-by="@index">
              <xsl:copy-of select="current-group()[@possibleValues = min(current-group()/@possibleValues)][1]" />
          </xsl:for-each-group>
***************
*** 297,305 ****
      <xsl:variable name="newBoard" select="(subsequence($board, 1, $index - 1), $possibleValues[1], subsequence($board, $index + 1))" as="xs:integer+" />
  
      <xsl:if test="$verbose">
!         <xsl:message>
!             <xsl:value-of select="concat('Trying ', $possibleValues[1], ' out of a possible ', string-join(for $i in $possibleValues return xs:string($i), ' '), ' at index ', $index)" />
!         </xsl:message>
      </xsl:if>
  
      <xsl:variable name="result" select="fn:populateValues($newBoard, subsequence($emptyCells, 2))" as="xs:integer*" />
--- 315,323 ----
      <xsl:variable name="newBoard" select="(subsequence($board, 1, $index - 1), $possibleValues[1], subsequence($board, $index + 1))" as="xs:integer+" />
  
      <xsl:if test="$verbose">
!         <xsl:call-template name="message">
!             <xsl:with-param name="msg" select="concat('Trying ', $possibleValues[1], ' out of a possible ', string-join(for $i in $possibleValues return xs:string($i), ' '), ' at index ', $index)"/>
!         </xsl:call-template>
      </xsl:if>
  
      <xsl:variable name="result" select="fn:populateValues($newBoard, subsequence($emptyCells, 2))" as="xs:integer*" />
***************
*** 324,330 ****
  
      <xsl:choose>
          <xsl:when test="empty($emptyCells)">
!             <xsl:message>Done!</xsl:message>
              <xsl:sequence select="$board" />
          </xsl:when>
          <xsl:otherwise>
--- 342,350 ----
  
      <xsl:choose>
          <xsl:when test="empty($emptyCells)">
!             <xsl:call-template name="message">
!                 <xsl:with-param name="msg">Done!</xsl:with-param>
!             </xsl:call-template>
              <xsl:sequence select="$board" />
          </xsl:when>
          <xsl:otherwise>
***************
*** 333,348 ****
              <xsl:choose>
                  <xsl:when test="count($possibleValues) eq 0">
                      <xsl:if test="$verbose">
!                         <xsl:message>! Cannot go any further !</xsl:message>
                      </xsl:if>
                      <xsl:sequence select="()" />
                  </xsl:when>
                  <xsl:when test="count($possibleValues) eq 1">
                      <xsl:variable name="newBoard" select="(subsequence($board, 1, $index - 1), $possibleValues[1], subsequence($board, $index + 1))" as="xs:integer+" />
                      <xsl:if test="$verbose">
!                         <xsl:message>
!                             <xsl:value-of>Only one value <xsl:value-of select="$possibleValues[1]" /> for index <xsl:value-of select="$index" /></xsl:value-of>
!                         </xsl:message>
                      </xsl:if>
                      <xsl:sequence select="fn:populateValues($newBoard, subsequence($emptyCells, 2))" />
                  </xsl:when>
--- 353,371 ----
              <xsl:choose>
                  <xsl:when test="count($possibleValues) eq 0">
                      <xsl:if test="$verbose">
!                         <xsl:call-template name="message">
!                             <xsl:with-param name="msg">! Cannot go any further !</xsl:with-param>
!                             <xsl:with-param name="severity" select="'ERROR'"/>
!                         </xsl:call-template>
                      </xsl:if>
                      <xsl:sequence select="()" />
                  </xsl:when>
                  <xsl:when test="count($possibleValues) eq 1">
                      <xsl:variable name="newBoard" select="(subsequence($board, 1, $index - 1), $possibleValues[1], subsequence($board, $index + 1))" as="xs:integer+" />
                      <xsl:if test="$verbose">
!                         <xsl:call-template name="message">
!                             <xsl:with-param name="msg">Only one value <xsl:value-of select="$possibleValues[1]" /> for index <xsl:value-of select="$index" /></xsl:with-param>
!                         </xsl:call-template>
                      </xsl:if>
                      <xsl:sequence select="fn:populateValues($newBoard, subsequence($emptyCells, 2))" />
                  </xsl:when>
***************
*** 354,360 ****
                      <xsl:choose>
                          <xsl:when test="count($possibleValues) eq 0">
                              <xsl:if test="$verbose">
!                                 <xsl:message>! Cannot go any further !</xsl:message>
                              </xsl:if>
                              <xsl:sequence select="()" />
                          </xsl:when>
--- 377,386 ----
                      <xsl:choose>
                          <xsl:when test="count($possibleValues) eq 0">
                              <xsl:if test="$verbose">
!                                 <xsl:call-template name="message">
!                                     <xsl:with-param name="msg">! Cannot go any further !</xsl:with-param>
!                                     <xsl:with-param name="severity" select="'ERROR'"/>
!                                 </xsl:call-template>
                              </xsl:if>
                              <xsl:sequence select="()" />
                          </xsl:when>
***************
*** 406,412 ****
              <xsl:sequence select="fn:processEmptyCells($newBoard)" />
          </xsl:when>
          <xsl:otherwise>
!             <xsl:variable name="emptyCellsXML_afterRemovingNakedTuples" select="fn:removeNakedTuples($emptyCellsXML)" as="element()+" />
              <xsl:variable name="newBoard" select="fn:populateSingleValueCells($board, $emptyCellsXML_afterRemovingNakedTuples)" as="xs:integer+" />
              <xsl:sequence select="$newBoard" />
          </xsl:otherwise>
--- 432,441 ----
              <xsl:sequence select="fn:processEmptyCells($newBoard)" />
          </xsl:when>
          <xsl:otherwise>
!             <!-- Pieter Masereeuw (June 14, 2018), changed emptyCellsXML_afterRemovingNakedTuples type to element()* instead of element()+ because we get an exception at the 2006 "Extremely hard board".
!                  Don't know if this change is OK or if there is some deeper problem.
!             -->
!             <xsl:variable name="emptyCellsXML_afterRemovingNakedTuples" select="fn:removeNakedTuples($emptyCellsXML)" as="element()*" /> 
              <xsl:variable name="newBoard" select="fn:populateSingleValueCells($board, $emptyCellsXML_afterRemovingNakedTuples)" as="xs:integer+" />
              <xsl:sequence select="$newBoard" />
          </xsl:otherwise>
***************
*** 433,439 ****
      <xsl:variable name="endBoard" select="fn:populateValues($board, fn:getEmptyCellsOrdered($board))" 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>
--- 462,471 ----
      <xsl:variable name="endBoard" select="fn:populateValues($board, fn:getEmptyCellsOrdered($board))" as="xs:integer*" />
      <xsl:choose>
          <xsl:when test="empty($endBoard)">
!             <xsl:call-template name="message">
!                 <xsl:with-param name="msg">! Invalid board - The starting board is not correct</xsl:with-param>
!                 <xsl:with-param name="severity" select="'ERROR'"/>
!             </xsl:call-template>
              <xsl:sequence select="$startBoard" />
          </xsl:when>
          <xsl:otherwise>
