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

More than 1 year has passed since last update.

これまでは、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

これだけで、 ghcirunghcghc も使えるようになりました 😀


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