これまでは、PHP とか Ruby とかを書いてきましたので、まずは Golang, Nim で fizzBuzz してみます。
Haskell は全然勝手がわからなかったので、インストールから書いてみたいともいます。
Golang
go_fizz.go
package main
import (
"bytes"
"os"
"strconv"
)
func main() {
n := 1000000
var buffer bytes.Buffer
for i := 1; i <= n; i++ {
if i%3 == 0 && i%5 == 0 {
buffer.WriteString("FizzBuzz\n")
} else if i%3 == 0 {
buffer.WriteString("Fizz\n")
} else if i%5 == 0 {
buffer.WriteString("Buzz\n")
} else {
buffer.WriteString(strconv.Itoa(i))
buffer.WriteString("\n")
}
}
os.Stdout.Write([]byte(buffer.String()))
}
$ go build -o go_fizz ./go_fizz.go
$ time ./go_fizz 1>/dev/null
./go_fizz > /dev/null 0.05s user 0.01s system 100% cpu 0.064 total
0.064 秒
Nim
nim_fizz.nim
let n = 1_000_000
var str = ""
for i in 1..n:
if i mod 3 == 0 and i mod 5 == 0: str.add "FizzBuzz\n"
elif i mod 3 == 0: str.add "Fizz\n"
elif i mod 5 == 0: str.add "Buzz\n"
else: str.add $i; str.add "\n"
write stdout, str
$ nim c -d:release nim_fizz.nim
$ time ./nim_fizz 1>/dev/null
./nim_fizz > /dev/null 0.05s user 0.01s system 91% cpu 0.061 total
0.061 秒
# 10回くらいまわしてみますか
$ time (for i in `seq 10`;do ./nim_fizz 1>/dev/null; done)
( for i in `seq 10`; do; ./nim_fizz > /dev/null; done; ) 0.39s user 0.06s system 93% cpu 0.478 total
Haskell
Haskell はまずはインストールからです。
https://www.haskell.org/platform/mac.html
ドキュメントを辿ると Mac なら homebrew 使えるようなので、簡単です。
$ brew cask install haskell-platform
これだけで、 ghci
も runghc
も ghc
も使えるようになりました 😀
hs_fizz.hs
main = fizzBuzz 1000000
fizzBuzz :: Integer -> IO()
fizzBuzz num = mapM_ (msg) [1..num]
msg :: Integer -> IO()
msg x
| x `mod` 3 == 0 && x `mod` 5 == 0 = putStrLn "FizzBuzz"
| x `mod` 3 == 0 = putStrLn "Fizz"
| x `mod` 5 == 0 = putStrLn "Buzz"
| otherwise = print x
$ ghc -o hs_fizz hs_fizz.hs
$ time ./hs_fizz 1>/dev/null
./hs_fizz > /dev/null 0.60s user 0.01s system 97% cpu 0.631 total
0.631 秒
ということで、僕の書いた、Haskell が Nim と Go と比べて 10倍くらい遅くなりました。
勉強しなくては、なりません。
以上、ありがとうございました。
追記1
ぼくに Nim を教えてくれた人が書いたもの。
fizz.nim
var
str = ""
i = uint(0)
while uint(1_000_000) > i:
i.inc
if i mod 15 == 0: str.add("FizzBuzz\n")
elif i mod 3 == 0: str.add("Fizz\n")
elif i mod 5 == 0: str.add("Buzz\n")
else:
str.add($i)
str.add("\n")
stdout.write(str)
追記2
Golang を早くする方法をおしえていただいた。
fizz.go
package main
import (
"fmt"
"strconv"
)
func main() {
n := 10000000
var m = make([]byte, 0, 10000000*60)
var fb = "FizzBuzz\n"
var f = "Fizz\n"
var b = "Buzz\n"
for i := 1; i <= n; i++ {
fizz := i%3 == 0
buzz := i%5 == 0
if fizz && buzz {
m = append(m, fb...)
} else if fizz {
m = append(m, f...)
} else if buzz {
m = append(m, b...)
} else {
m = append(m, strconv.FormatInt(int64(i), 10)...)
m = append(m, "\n"...)
}
}
fmt.Print(string(m))
}