XQuery/Fizzbuzz

see 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 := Fizz Buzz

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),   "&#10;" )

Execute

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

Execute

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)])

Execute

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)

Execute

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]