XQuery/Fizzbuzz
see [1] for the full set of executable scripts and timing comparisons.
Here's an XQuery solution to the FizzBuzz problem posed in David Patterson's blog.. who wrote an XSLT solution.
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.
Here is a solution from Dino Fancellu, pure XPath 3.0:
(1 to 30)!(if (. mod 15=0) then "fizzbuzz" else if (. mod 3 = 0) then "fizz" else if (. mod 5 = 0) then "buzz" else .)
Here is a solution by Benito van der Zander, pure XPath 3.0 without if:
for $i in 1 to 100 return (("fizz"[$i mod 3=0] || "buzz"[$i mod 5=0])[.],$i)[1]