fizzBuzz で Nim と Golang と Haskell を勉強する

これまでは、PHP とか Ruby とかを書いてきましたので、まずは Golang, Nim で fizzBuzz してみます。
Haskell は全然勝手がわからなかったので、インストールから書いてみたいともいます。

# Golang

```go: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()))
}
```

```bash
$ 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: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
```

```bash
$ 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 使えるようなので、簡単です。

```bash
$ brew cask install haskell-platform
```

これだけで、 `ghci` も `runghc` も `ghc` も使えるようになりました 😀

```haskell: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
```

```bash
$ 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 を教えてくれた人が書いたもの。

```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 を早くする方法をおしえていただいた。

```go: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))
}
```