From Wikibooks, open books for an open world
Jump to: navigation, search

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 :=
<range min="1" max="100"/>
   <mod value="3" test="0">Fizz</mod>
   <mod value="5" test="0">Buzz</mod>

   for $i in ($config/range/@min to $config/range/@max)
   let $s :=  
       for $mod in $config/test/mod
         if ($i mod $mod/@value = $mod/@test)
         then string($mod)
         else ()
     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"
  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)
    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))
            let $results :=
                      ($start, $start+1,
                      'buzz', 'fizz',
                      $start+6, $start+7, 
                      $start+12, $start+13,
                      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 .)