07 March, 2020
AtCoder Beginers Selectionをgoで解いてみる(前編)
はじめに
自分が文系出身ということもあり、コンピューターサイエンスの基礎があまりにもわからない。
ここらでちゃんと勉強しようと思い、まずはデータ構造とアルゴリズムの基礎から勉強していくことにした。
とりあえず、AtCoder Beginers Selection(以下 ABS)をやってみる。
ABS とは、初心者向けに AtCoder の過去問から 10 問ピックアップされたもので、競プロ初心者が最初に解いてみると良いらしい。
実業務にも活かしていく前提なので、言語はGo
で!
Go 言語で競プロの問題を解くために
入力値の受け取り
兎にも角にも入力を受け取らないと話にならない。
Go 言語で AtCoder からの入力値を受け取るには、こんな感じになります。
この組み合わせで大体の入力は処理できるはず。
/*
入力形式
--------
n (数字)
--------
*/
var n int
fmt.Scanf("%d", &n)
/*
入力形式
--------
s (文字列)
--------
*/
var s string
fmt.Scanf("%d", &s)
/*
入力形式
--------
n1 n2
--------
*/
var n1, n2 int
fmt.Scanf("%d %d", &n1, &n2)
/*
入力形式
--------
N
n1
.
.
nN
--------
*/
var N int
fmt.Scanf("%d", &N)
list := make([]int, n)
for i := 0; i < n; i++ {
fmt.Scanf("%d", &list[i])
}
/*
入力形式
--------
N
s1 s2 .. sN
--------
*/
var N int
fmt.Scanf("%d", &n)
s := bufio.NewScanner(os.Stdin)
s.Scan()
sList := strings.Fields(s.Text())
ABS を解いていく
0. Welcome to AtCoder
【概要】
チュートリアル
整数 3 個と、文字列が与えられ、その整数の和と、文字列を出力します。
この問題は特に悩むところもないです。
package main
import (
"fmt"
)
func main() {
var a, b, c int
var s string
fmt.Scanf("%d", &a)
fmt.Scanf("%d %d", &b, &c)
fmt.Scanf("%s", &s)
fmt.Printf("%d %s\n", a+b+c, s)
}
1. Product
【概要】
偶奇の判定。
これも特に悩むところは無し。
package main
import "fmt"
func main() {
var a, b int
fmt.Scanf("%d %d", &a, &b)
r := (a * b) % 2
if r == 0 {
fmt.Println("Even")
} else {
fmt.Println("Odd")
}
}
2. Placing Marbles
【概要】
与えられた数列を受け取り、その中に ”1”が何個あるか求めます。
全探索です。
これは for 文で一文字ずつ判定しても良いですが、go のstrings.Count()
を使用すレバサクッとできます。
package main
import (
"fmt"
"strings"
)
func main() {
var s string
fmt.Scanf("%s", &s)
fmt.Println(strings.Count(s, "1"))
}
3. Shift only
【概要】
N 個の整数が与えられ、その全てが偶数である時、その整数を 2 で割った値に変換します。これを何回行うことができるか求めるもの。
全探索を使用して、行う操作をそのまま実装すると以下のようになります。
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
var cnt, n int
var ns []int
var existOdd bool
fmt.Scanf("%d", &n)
s := bufio.NewScanner(os.Stdin)
s.Scan()
ss := strings.Fields(s.Text())
for _, v := range ss {
j, _ := strconv.Atoi(v)
ns = append(ns, j)
}
for {
// 与えたれた整数が全て2で割り切れるか確認
for _, v := range ns {
if v%2 == 1 {existOdd = true}
}
// 与えたれた整数が全て2で割り切れなければfor文を抜ける
if existOdd {break}
// 各数字を2で割る
for i, v := range ns {
ns[i] = v / 2
}
cnt++
}
fmt.Println(cnt)
}