1
0

More than 3 years have passed since last update.

AtCoder 緑が Go で解いてみた

Last updated at Posted at 2021-01-17

Go は AtCoder に向いているのか

最近 Go の標準的な package には max 関数がなかったり、型の縛りがかなりキツかったり、色々厳しい面があるという話を聞いたので、Python3 と比較して実際にどれぐらい厳しいのか試してみた。

ABC188 を解いてみる

A

https://atcoder.jp/contests/abc188/tasks/abc188_a
バスケでスリーポイントを決めると逆転する展開かどうかを判定するという問題。

入力は宣言した型に対して、fmt.Scan(&a) で入れられるらしい。

a.go
package main

import (
    "fmt"
    "math"
)

func main() {
    var X, Y int
    fmt.Scan(&X, &Y)
    if math.Abs(X-Y) < 3 {
        fmt.Print("Yes")
    } else {
        fmt.Print("No")
    }
}

これで問題無いだろうと思ったが、どうやら math.Abs() は引数に float64 しか受け付けていないらしい。よって var X, Y int ではなく var X, Y float64 と宣言すれば動いた。
https://golang.org/pkg/math/
math パッケージは基本 float64 しか受け付けていないらしく int を使用する意味はあまりなさそうだ。
これ以降の宣言は全て float64 にしようと決意。
ちなみにこちらを Python3 で記述すると

a.py
X, Y = map(int, input().split())
if abs(X - Y) < 3:
    print("Yes")
else:
    print("No")

当然といえば当然だが Python の abs() は int も float もいける。

B

https://atcoder.jp/contests/abc188/tasks/abc188_b
Vector の内積が0になるかという問題。
配列の入力は先程の fmt.Scan(&A) でいけるとすると、

var X float64
var A, B []float64
fmt.Scan(&X, &A, &B)

みたいな書き方は流石にあるだろうと思ったが、そんなものは存在せず、ググって書いてみた所

b.go
package main

import "fmt"

func main() {
    var N int
    fmt.Scan(&N)
    A, B := make([]float64, N), make([]float64, N)
    for i := 0; i < N; i++ {
        fmt.Scan(&A[i])
    }
    for i := 0; i < N; i++ {
        fmt.Scan(&B[i])
    }

    total := float64(0)
    for i := 0; i < N; i++ {
        total += A[i] * B[i]
    }
    if total == 0 {
        fmt.Print("Yes")
    } else {
        fmt.Print("No")
    }
}

配列の際の標準入力で for文を使用するのは若干きつい。
この辺りはテンプレ作って簡単に入れられるようにしたい。

b.py
_ = int(input())
X = list(map(int, input().split()))
Y = list(map(int, input().split()))

total = 0
for i in range(len(X)):
    total += X[i] * Y[i]

if total == 0:
    print("Yes")
else :
    print("No")

Python であれば list(map(type, input().split())) の一行でかけるのでいいですね。

C

配列を前半と後半に分け、それぞれの最大値と index を保持して最後に比較する感じになりそう。

c.go
package main

import (
    "fmt"
    "math"
)

func main() {
    var N int
    fmt.Scan(&N)
    sN := int(math.Pow(2, float64(N)))
    A := make([]int64, sN)
    for i := 0; i < sN; i++ {
        fmt.Scan(&A[i])
    }
    fmax, smax := int64(0), int64(0)
    findex, sindex := -1, -1
    for i, rating := range A {
        if i < sN/2 {
            if rating > fmax {
                fmax = rating
                findex = i
            }
        } else {
            if rating > smax {
                smax = rating
                sindex = i
            }
        }
    }
    if fmax < smax {
        fmt.Println(findex + 1)
    } else {
        fmt.Println(sindex + 1)
    }
}

Powfloat64 が、for loop の index の iint になってしまうなど、場面場面に応じて intfloat64 にするのかとか考えないと駄目。脳死の float64 は通用しませんでした。
slice と自作 max 関数を使えばもう少しスマートな書き方にできそう。

c.py
N = int(input())
sNh = 2 ** (N - 1)
A = list(map(int, input().split()))
fA = A[:sNh]
sA = A[sNh:]
print(A.index(min(max(fA), max(sA))) + 1)

Python3 に関しては min, max 関数と Array の index 関数がある為お手軽に実装できた。

個人的な感想

まだ3問解いただけだが、

  • intfloat64 の使い分け
  • max 関数などのどの言語にもありそうな関数が標準の package には存在しなさそう
  • 配列の初期化だるい

上記の3点はテンプレを作ってしまえば解決しそうなレベルなので Go で AtCoder をやっていくのは厳しい、ということはなさそうだが、Go も AtCoder も初心者という方にはあまりおすすめできない。Python の最低限の記法だけ覚えて AtCoder の問題を解くことに専念する方が変な所で躓かず楽しめそう。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0