跳转到内容

XQuery/Fizzbuzz

来自维基教科书,开放的书籍,为开放的世界


查看 [1] 以获取完整的可执行脚本集和计时比较。

这是对 David Patterson 在 David Patterson 的博客中提出的 FizzBuzz 问题 的 XQuery 解决方案。他写了一个 XSLT 解决方案。

Chris Wallace 为 David 的可配置版本问题编写了此解决方案

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),
   "
"
 )

执行

该算法的参数化是在 David Patterson 提出的原始问题中。如果参数固定,则可以实现更简单的解决方案。

以下是由 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

执行

以下是由 Dimitre Novatchev 提供的简短而简单的解决方案 - 请注意,没有显式的 if ... then ... else。 (另外,如果消除 $fizz 和 $buzz 变量,则可以缩短为 3 行)

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

执行

可以注意到,以上解决方案没有使用任何 XPath 中没有的 XQuery 特性 - 因此这是一个纯 XPath 2.0 解决方案

Dimitre 的另一个解决方案,它可能更快,因为它根本不使用任何 mod 运算符

      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)

执行

同样,以上解决方案没有使用任何 XPath 3.0 中没有的 XQuery 特性 - 因此这是一个纯 XPath 3.0 解决方案


以下是由 Dino Fancellu 提供的解决方案,纯 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 .)

以下是由 Benito van der Zander 提供的解决方案,纯 XPath 3.0,无 if


for $i in 1 to 100 return (("fizz"[$i mod 3=0] || "buzz"[$i mod 5=0])[.],$i)[1]
华夏公益教科书