Go は AtCoder に向いているのか
最近 Go の標準的な package には max 関数がなかったり、型の縛りがかなりキツかったり、色々厳しい面があるという話を聞いたので、Python3 と比較して実際にどれぐらい厳しいのか試してみた。
ABC188 を解いてみる
A
https://atcoder.jp/contests/abc188/tasks/abc188_a
バスケでスリーポイントを決めると逆転する展開かどうかを判定するという問題。
入力は宣言した型に対して、fmt.Scan(&a)
で入れられるらしい。
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 で記述すると
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)
みたいな書き方は流石にあるだろうと思ったが、そんなものは存在せず、ググって書いてみた所
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文を使用するのは若干きつい。
この辺りはテンプレ作って簡単に入れられるようにしたい。
_ = 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 を保持して最後に比較する感じになりそう。
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)
}
}
Pow
で float64
が、for loop の index の i
で int
になってしまうなど、場面場面に応じて int
か float64
にするのかとか考えないと駄目。脳死の float64
は通用しませんでした。
slice と自作 max
関数を使えばもう少しスマートな書き方にできそう。
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問解いただけだが、
-
int
とfloat64
の使い分け -
max
関数などのどの言語にもありそうな関数が標準の package には存在しなさそう - 配列の初期化だるい
上記の3点はテンプレを作ってしまえば解決しそうなレベルなので Go で AtCoder をやっていくのは厳しい、ということはなさそうだが、Go も AtCoder も初心者という方にはあまりおすすめできない。Python の最低限の記法だけ覚えて AtCoder の問題を解くことに専念する方が変な所で躓かず楽しめそう。