跳轉到內容

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]
華夏公益教科書