Go言語に手を出した

Elixir は先月うまくいかなくてめげてしまったので、ここ最近は Go 言語に手を出している。ま、Web ページを見ながら見様見真似でやってるんだけど、言語の雰囲気はなんとなくわかったってところかな。OS ネイティブの実行ファイルが作れるのはいいね。ツールを作って他人に配るのにはいい。goroutine はよくわかんない。

で、ちょっと整数の素因数分解をするプログラムを作ってみた。

package main

import (
    "fmt"
    "os"
    "flag"
    "strconv"
)

func primes(n int) []int {
    p := make([]bool, n + 1)
    // スライス p はゼロ値(false)で初期化されるので、2 と 3 以上の奇数だけ true に初期化する。
    if 2 < n {
        p[2] = true
        for i := 3; i <= n; i += 2 {
            p[i] = true
        }
    }
    // 3 以上の奇数を順にふるいにかける。
    for i := 3; i * i < n; i += 2 {
        if p[i] {
            for j := i + i; j <= n; j += i {
                p[j] = false
            }
        }
    }
    // 素数だけ pn に追加。
    pn := make([]int, 0)
    for i := 2; i <= n; i++ {
        if p[i] {
            pn = append(pn, i)
        }
    }
    return pn
}

func primeFactors(n int) []int {
    // n が合成数だと仮定すると、可能性として考えられる最大の素因数は n/2。
    ps := primes(n / 2)
    // n/2 以下の素数の中から素因数を探す。
    facts := make([]int, 0)
    for _, p := range ps {
        for n != 1 {
            if n % p == 0 {
                facts = append(facts, p)
                n = n / p
            } else {
                break
            }
        }
    }
    // n/2 までに素因数が見つからない場合、n 自身が素数。
    if len(facts) == 0 {
        facts = append(facts, n)
    }
    return facts
}

func main() {
    Usage := func() {
        fmt.Fprintf(os.Stderr, "Usage: %s \n", os.Args[0])
    }
    opt_help := flag.Bool("h", false, "Help message")
    flag.Parse()

    if *opt_help || flag.NArg() < 1 {
        Usage() os.Exit(0)
    }
    n, err := strconv.Atoi(flag.Arg(0))
    if err != nil {
        fmt.Fprintln(os.Stderr, "Invalid argument.")
        os.Exit(1)
    }
    if n < 2 {
        fmt.Println("Nothing prime factors.")
    } else {
        f := primeFactors(n)
        s := fmt.Sprintf("%v", f)
        l := len(s) fmt.Println(s[1:l-1])
    }
}

コンパイルせずにそのまま実行するには go run コマンド。

^o^ > go run primefactors.go 12345
3 5 823

コンパイルするには go build コマンド。

^o^ > go build primefactors.go

^o^ > ls
primefactors.exe  primefactors.go

^o^ > primefactors 12345
3 5 823