F#で逆FizzBuzz問題
元ネタ
逆FizzBuzz問題 (Inverse FizzBuzz) - 猫とC#について書くmatarilloの雑記
http://d.hatena.ne.jp/matarillo/20120515/p1
面白いなあ / “逆FizzBuzz問題 (Inverse FizzBuzz) - 猫とC#について書くmatarilloの雑記” URL
逆FizzBuzz問題 解きなおし #c# #FizzBuzz URL
面白いですねえ。
無理矢理詰め込んでツイートしたけど、F#で140文字ゴルフプログラミングとか割と無茶ですから!(白目
fun x->List.map(fun x->List.map(fun y->x,y)[x..100])[1..100]|>List.collect id|>List.sortBy(fun(a,b)->b-a)|>List.find(fun(a,b)->fzbz[a..b]=x)
F#はゴルフに向いていないでござる
F#で逆FizzBuzz問題
二番煎じというのは、面白さ半減どころかほぼ面白みなし!的な雰囲気がありますが、ゴルフなスニペットだけ置いておくのもアレなので実装例全体をのっけとく。
open System let fzbz lst = let isFizzBuzz x = if x%3 = 0 || x%5 =0 then true else false let toFizzBuzz x = (x%3,x%5) |> function |0,0 -> "fizzbuzz" |0,_ -> "fizz" |_ -> "buzz" [for x in lst do if isFizzBuzz(x) then yield toFizzBuzz(x)] let range n = [1..n] |> List.map (fun x -> [x..n] |> List.map (fun y -> x,y)) |> List.collect id |> List.sortBy (fun (a,b) -> b - a) let inverses x = range 100 |> List.find (fun (a,b) -> fzbz [a..b] = x) printfn "%A" <| inverses ["fizz"] // (3,3) printfn "%A" <| inverses ["buzz"] // (5,5) printfn "%A" <| inverses ["fizz";"fizz";"buzz"] // (6,10) printfn "%A" <| inverses ["fizz";"buzz"] // (9,10) printfn "%A" <| inverses ["buzz";"fizz"] // (5,6) printfn "%A" <| inverses ["fizz";"buzz";"fizz"] // (3,6) printfn "%A" <| inverses ["fizz";"fizz"] // (6,9) printfn "%A" <| inverses ["fizz";"fizzbuzz"] // (12,15) Console.ReadLine () |> ignore
元ネタの元ネタのScalaでの解説は、確かにストーリー的には面白いものになっているけど、プログラムとしては結構無駄な計算が多くて、それってどうなの?ってー感じがしないこともなくもない。上記のように、探索対象を範囲が狭くて小さい順に先にソートしてから探索して、最初に一致したものを返すという考え方の方が、計算量も少なくなりますし自然ですね。
ので逆に F# 可読性高い! RT @zecl: F#はゴルフに向いていないでござる
F# は、ただただ短くかけるとか、なんだか小難しい抽象化なんかより、質実剛健で実務に役立つようなデザイン チョイスが現状なされていると思うし、ぜひこれからもそうあってほしい。 #fsharp
いげ太さんに禿同と言わざるを得ない。まぁ、抽象化の超パワーを無視することは(おれは)できないけどね!
ちなみに、F#は書き味のほうも最高峰レベルなので使ったら気に入ること間違いなしだよっウフフオッケー☆
追記:5/17
対象が見つからない場合も考慮したやつ
open System let fzbz lst = let isFizzBuzz x = if x%3 = 0 || x%5 =0 then true else false let toFizzBuzz x = (x%3,x%5) |> function |0,0 -> "fizzbuzz" |0,_ -> "fizz" |_ -> "buzz" [for x in lst do if isFizzBuzz(x) then yield toFizzBuzz(x)] let range n = [1..n] |> List.map (fun x -> [x..n] |> List.map (fun y -> x,y)) |> List.collect id |> List.sortBy (fun (a,b) -> b - a) let inverses = function | [] -> None | x -> range 100 |> List.tryFind (fun (a,b) -> fzbz [a..b] = x) let print = function | Some x -> printfn "%A" <| x | None -> printfn "None" print <| inverses ["fizz"] // (3,3) print <| inverses ["buzz"] // (5,5) print <| inverses ["fizz";"fizz";"buzz"] // (6,10) print <| inverses ["fizz";"buzz"] // (9,10) print <| inverses ["buzz";"fizz"] // (5,6) print <| inverses ["fizz";"buzz";"fizz"] // (3,6) print <| inverses ["fizz";"fizz"] // (6,9) print <| inverses ["fizz";"fizzbuzz"] // (12,15) print <| inverses [] // None print <| inverses ["orz"] // None print <| inverses ["fizzbuzz";"fizzbuzz"] // None Console.ReadLine () |> ignore