【Go】AtCoderでよく使う関数

はじめに

goでAt Coderを解くにあたってC++で書かれた解説コードをGoに焼き直す作業を頻繁に行っています。その際「C++に有ってgoにはない」メソッドや文法が多くて結構困ります

冗長なだけなら「goだし仕方ないか」で済むのですが、明らかにあった方が良いメソッドが標準パッケージに搭載されていない事もしばしば

そこで幾つか自分で実装してみよう!

配列操作

C++vectoriteratorで使われる関数をもうちょい足したい

count

func Count(s []int, n int) int {
    var cnt int
    for _, v := range s {
        if v == n {
            cnt++
        }
    }

    return cnt
}

unique

func Unique(s []int) []int {
    uniq := make([]int, len(s))
    m := make(map[int]bool)
    cnt := 0

    for _, ele := range s {
        if !m[ele] {
            m[ele] = true

            uniq[cnt] = ele
            cnt++
        }
    }

    return uniq[:cnt]
}

文字列に対する関数

find

第1引数の集合に第2引数の値が存在した場合、そのindexを返す関数

引数にinterface{}型を取り、reflectで型判別しながら異なる処理を呼び出すことで実装できますが、実行速度が大幅に遅くなる為文字列に絞って実装します。

可変長配列ならソートしてからsort.Searchで二分探索すれば良いはず

func find(str string, char string) int {
    for i := range str {
        if string(str[i]) == char {
            return i
        }
    }

    return -1
}

O(N)

汎用計算関数

  • std::abs
  • std::max
  • std::min
  • std::pow
  • std::sqrt
func max(x, y int) int {
    if x > y {
        return x
    }
    return y
}

func min(x, y int) int{
    if x > y {
        return y
    }
    return x
}

func abs(a int) int {
    return int(math.Abs(float64(a)))
}

func pow(p, q int) int {
    return int(math.Pow(float64(p), float64(q)))
}

func squart(x, y int) float64 {
    dif := x*x - y*y
    return math.Sqrt(float64(dif))
}

func pow(x, y int) int {
    return int(math.Pow(float64(x), float64(y)))
    // 2, 3 = 8
    // 10, 2 = 100

permulation

順列を扱う際にお世話になるメソッドです

func Factorial(n int)(result int) {
    if (n > 0) {
        result = n * Factorial(n-1)
        return result
    }
    return 1
}

/*
fmt.Println(0, intSlice)
for i := 1; nextPermutation(sort.IntSlice(intSlice)); i++ {
   fmt.Println(i, intSlice)
}
*/
func nextPermutation(x sort.Interface) bool {
    n := x.Len() - 1
    if n < 1 {
        return false
    }
    j := n - 1
    for ; !x.Less(j, j+1); j-- {
        if j == 0 {
            return false
        }
    }
    l := n
    for !x.Less(j, l) {
        l--
    }
    x.Swap(j, l)
    for k, l := j+1, n; k < l; {
        x.Swap(k, l)
        k++
        l--
    }
    return true
}

Factorialは日本語で「階乗」の意味でN!を算出します。(3! は 3、10! は 45)

次にnextPermulationはC++nextPermulationと同じ挙動です。順列の全パターンを出力し、最大値まで並べ終えるとfalseを返します

最後に

同じ様なコンセプトで「標準パッケージにないけど欲しい」関数があれば是非教えていただきたいです!

c++ちゃんと勉強したい