see  for the full set of executablescripts and timing comparisons.
Chris Wallace wrote this solution to David's configurable version of the problem:
let $config := <fizzbuzz> <range min="1" max="100"/> <test> <mod value="3" test="0">Fizz</mod> <mod value="5" test="0">Buzz</mod> </test> </fizzbuzz> return string-join( for $i in ($config/range/@min to $config/range/@max) let $s := for $mod in $config/test/mod return if ($i mod $mod/@value = $mod/@test) then string($mod) else () return if (exists($s)) then string-join($s,' ') else string($i), " " )
The parameterisation of the algorithm was in the original problem as proposed by David Patterson. Simpler solutions are possible if the parameters are fixed.
Here is a solution from Jim Fuller:
for $n in (1 to 100) let $fizz := if ($n mod 3) then () else "fizz" let $buzz := if ($n mod 5) then () else "buzz" return if ($fizz or $buzz) then concat($fizz,$buzz) else $n
Here is a short and simple solution by Dimitre Novatchev -- note that there isn't any explicit if ... then ... else. (Also, this can be shortened to 3 lines if the $fizz and $buzz variables are eliminated):
for $n in (1 to 100), $fizz in not($n mod 3), $buzz in not($n mod 5) return concat("fizz"[$fizz], "buzz"[$buzz], $n[not($fizz or $buzz)])
One may notice that the above solution doesn't use any XQuery features that aren't also in XPath -- therefore this is a pure XPath 2.0 solution.
Another solution by Dimitre, which might be faster as it doesn't use any mod operator at all:
for $k in 1 to 100 idiv 15 +1, $start in 15*($k -1) +1, $end in min((100, $start + 14)) return let $results := ($start, $start+1, 'fizz', $start+3, 'buzz', 'fizz', $start+6, $start+7, 'fizz', 'buzz', $start+10, 'fizz', $start+12, $start+13, 'fizzbuzz') return subsequence($results, 1, $end -$start +1)
Again, the above solution doesn't use any XQuery features that aren't also in XPath 3.0 -- therefore this is a pure XPath 3.0 solution.Last modified on 4 March 2012, at 19:48