1<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
2
3<xsl:template match="towerheight">
4
5
6  <xsl:output encoding="utf-8"/>
7
8
9    <xsl:variable name="height">
10        <xsl:value-of select="."/>
11    </xsl:variable>
12
13    <xsl:variable name="tower">
14        <xsl:call-template name="initialize">
15            <xsl:with-param name="height" select="$height"/>
16        </xsl:call-template>
17    </xsl:variable>
18
19    <towers>
20        <xsl:copy-of select="$tower"/>
21        <xsl:call-template name="transferstack">
22            <xsl:with-param name="tower" select="$tower"/>
23            <xsl:with-param name="source" select="'left'"/>
24            <xsl:with-param name="target" select="'center'"/>
25            <xsl:with-param name="spare" select="'right'"/>
26            <xsl:with-param name="howmany" select="$height"/>
27        </xsl:call-template>
28    </towers>
29
30</xsl:template>
31
32<xsl:template name="initialize">
33    <xsl:param name="height"/>
34    <tower>
35        <leftstack>
36            <xsl:call-template name="initstack">
37                <xsl:with-param name="height" select="$height"/>
38            </xsl:call-template>
39        </leftstack>
40        <centerstack/>
41        <rightstack/>
42    </tower>
43</xsl:template>
44
45<xsl:template name="initstack">
46    <xsl:param name="height"/>
47    <xsl:param name="size" select="0"/>
48    <xsl:if test="$size > 0">
49        <disc size="{$size}"/>
50    </xsl:if>
51    <xsl:if test="$size &lt; $height">
52        <xsl:call-template name="initstack">
53            <xsl:with-param name="height" select="$height"/>
54            <xsl:with-param name="size" select="$size + 1"/>
55        </xsl:call-template>
56    </xsl:if>
57</xsl:template>
58
59<xsl:template name="transferstack">
60    <xsl:param name="tower"/>
61    <xsl:param name="source"/>
62    <xsl:param name="target"/>
63    <xsl:param name="spare"/>
64    <xsl:param name="howmany"/>
65
66    <xsl:if test="$howmany > 0">
67
68        <xsl:variable name="firstpart">
69            <xsl:call-template name="transferstack">
70                <xsl:with-param name="tower" select="$tower"/>
71                <xsl:with-param name="source" select="$source"/>
72                <xsl:with-param name="target" select="$spare"/>
73                <xsl:with-param name="spare" select="$target"/>
74                <xsl:with-param name="howmany" select="$howmany - 1"/>
75            </xsl:call-template>
76        </xsl:variable>
77
78        <xsl:variable name="lasttower">
79            <xsl:choose>
80                <xsl:when test="$firstpart/tower[last()]">
81                    <xsl:copy-of select="$firstpart/tower[last()]"/>
82                </xsl:when>
83                <xsl:otherwise>
84                    <xsl:copy-of select="$tower"/>
85                </xsl:otherwise>
86            </xsl:choose>
87        </xsl:variable>
88
89        <xsl:variable name="secondpart">
90            <xsl:call-template name="transferdisc">
91                <xsl:with-param name="tower" select="$lasttower"/>
92                <xsl:with-param name="source" select="$source"/>
93                <xsl:with-param name="target" select="$target"/>
94            </xsl:call-template>
95        </xsl:variable>
96
97        <xsl:copy-of select="$firstpart"/>
98        <xsl:copy-of select="$secondpart"/>
99
100        <xsl:call-template name="transferstack">
101            <xsl:with-param name="tower" select="$secondpart"/>
102            <xsl:with-param name="source" select="$spare"/>
103            <xsl:with-param name="target" select="$target"/>
104            <xsl:with-param name="spare" select="$source"/>
105            <xsl:with-param name="howmany" select="$howmany - 1"/>
106        </xsl:call-template>
107
108    </xsl:if>
109</xsl:template>
110
111<xsl:template name="transferdisc">
112    <xsl:param name="tower"/>
113    <xsl:param name="source"/>
114    <xsl:param name="target"/>
115
116    <xsl:variable name="disc">
117        <xsl:choose>
118            <xsl:when test="$source = 'left'">
119                <xsl:copy-of select="$tower/tower/leftstack/disc[1]"/>
120            </xsl:when>
121            <xsl:when test="$source = 'center'">
122                <xsl:copy-of select="$tower/tower/centerstack/disc[1]"/>
123            </xsl:when>
124            <xsl:otherwise>
125                <xsl:copy-of select="$tower/tower/rightstack/disc[1]"/>
126            </xsl:otherwise>
127        </xsl:choose>
128    </xsl:variable>
129
130    <xsl:variable name="newleft">
131        <xsl:choose>
132            <xsl:when test="$source = 'left'">
133                <leftstack>
134                    <xsl:copy-of select="$tower/tower/leftstack/disc[position() > 1]"/>
135                </leftstack>
136            </xsl:when>
137            <xsl:when test="$target = 'left'">
138                <leftstack>
139                    <xsl:copy-of select="$disc"/>
140                    <xsl:copy-of select="$tower/tower/leftstack/disc"/>
141                </leftstack>
142            </xsl:when>
143            <xsl:otherwise>
144                <xsl:copy-of select="$tower/tower/leftstack"/>
145            </xsl:otherwise>
146        </xsl:choose>
147    </xsl:variable>
148
149    <xsl:variable name="newcenter">
150        <xsl:choose>
151            <xsl:when test="$source = 'center'">
152                <centerstack>
153                    <xsl:copy-of select="$tower/tower/centerstack/disc[position() > 1]"/>
154                </centerstack>
155            </xsl:when>
156            <xsl:when test="$target = 'center'">
157                <centerstack>
158                    <xsl:copy-of select="$disc"/>
159                    <xsl:copy-of select="$tower/tower/centerstack/disc"/>
160                </centerstack>
161            </xsl:when>
162            <xsl:otherwise>
163                <xsl:copy-of select="$tower/tower/centerstack"/>
164            </xsl:otherwise>
165        </xsl:choose>
166    </xsl:variable>
167
168    <xsl:variable name="newright">
169        <xsl:choose>
170            <xsl:when test="$source = 'right'">
171                <rightstack>
172                    <xsl:copy-of select="$tower/tower/rightstack/disc[position() > 1]"/>
173                </rightstack>
174            </xsl:when>
175            <xsl:when test="$target = 'right'">
176                <rightstack>
177                    <xsl:copy-of select="$disc"/>
178                    <xsl:copy-of select="$tower/tower/rightstack/disc"/>
179                </rightstack>
180            </xsl:when>
181            <xsl:otherwise>
182                <xsl:copy-of select="$tower/tower/rightstack"/>
183            </xsl:otherwise>
184        </xsl:choose>
185    </xsl:variable>
186
187    <tower>
188        <xsl:copy-of select="$newleft"/>
189        <xsl:copy-of select="$newcenter"/>
190        <xsl:copy-of select="$newright"/>
191    </tower>
192</xsl:template>
193
194</xsl:stylesheet>
195