Goで競技プログラミング

# [IPFactory Advent Calender 2019](https://qiita.com/advent-calendar/2019/ipfactory) 七日目
情報科学専門学校 1年 IPFactory所属  [よーでん](https://twitter.com/y0d3n) です。
最近はGolangで競技プログラミングをやってます。
「Goでやるならテンプレ作りなよ！」といわれたので、テンプレ作成ついでにメモとして書きます
**理解して使うことが大事**です。コピペは極力避けてください。

## 準備
```go:main.go

package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strconv"
)

var sc = bufio.NewScanner(os.Stdin)

func main() {
	sc.Split(bufio.ScanWords)
}
```
事前準備。他にもパッケージを使いたい場合は適宜`import`してもらえば良いです。
## 標準入力から読み込む
### stringで一つ読み込む
> hogehoge

```go
func scanText() string {
	sc.Scan()
	return sc.Text()
}

func main() {
	sc.Split(bufio.ScanWords)

	a := scanText()
}
```
`sc.Scan`で標準入力から一つ受け取り、そのまま返している。
### intで一つ読み込む
> 3

```go
func scanInt() int {
	sc.Scan()
	a, err := strconv.Atoi(sc.Text())
	if err != nil {
		fmt.Println(err)
	}
	return a
}

func main() {
	sc.Split(bufio.ScanWords)

	n := scanInt()
}
```
`strconv.Atoi`でint型に変換。
デバッグしやすいようにerrの出力をいれている。
### float64で一つ読み込む
> 3.14

```go
func scanFloat() float64 {
	sc.Scan()
	a, err := strconv.ParseFloat(sc.Text(), 64)
	if err != nil {
		fmt.Println(err)
	}
	return a
}
func main() {
	sc.Split(bufio.ScanWords)

	n := scanFloat()
}
```
`strconv.ParseFloat`でfloat型に変換。
### 上記の関数を活用
>hoge　hoge
3　4
3.1　1.2


```go
func scanText2() (string, string) {
	return scanText(), scanText()
}

func scanInt2() (int, int) {
	return scanInt(), scanInt()
}

func scanFloat2() (float64, float64) {
	return scanFloat(), scanFloat()
}

func main() {
	sc.Split(bufio.ScanWords)

	a, b := scanText2()
	c, d := scanInt2()
	e, f := scanFloat2()
}
```
こんな感じにしておけば、後々便利。かも。3とかも作ってもいいかもしれない。
### 複数受け取る
> hoge　hoge　hoge　hoge　hoge
1　2　3　4　5
1.2　3.4　5.6　7.8　9.0

```go
func scanTextSlice(n int) []string {
	a := make([]string, n)
	for i := 0; i < n; i++ {
		a[i] = scanText()
	}
	return a
}

func scanSlice(n int) []int {
	a := make([]int, n)
	for i := 0; i < n; i++ {
		a[i] = scanInt()
	}
	return a
}

func scanFloatSlice(n int) []float64 {
	a := make([]float64, n)
	for i := 0; i < n; i++ {
		a[i] = scanFloat()
	}
	return a
}

func main() {
	sc.Split(bufio.ScanWords)

	x := scanTextSlice(5)
	y := scanSlice(5)
	z := scanFloatSlice(5)
}
```
それぞれの型でループ回してるだけ。
mainからの引数は要素数。intはよく使うので名前を短く。
### 複数sliceを受け取る
> x1　y1
x2　y2
x3　y3

```go
func scanSlice2(n int) ([]int, []int) {
	a := make([]int, n)
	b := make([]int, n)
	for i := 0; i < n; i++ {
		a[i], b[i] = scanInt2()
	}
	return a, b
}

func scanFloatSlice2(n int) ([]float64, []float64) {
	a := make([]float64, n)
	b := make([]float64, n)
	for i := 0; i < n; i++ {
		a[i], b[i] = scanFloat2()
	}
	return a, b
}
func main() {
	sc.Split(bufio.ScanWords)

	x := scanSlice2()
	x := scanFloatSlice2()
}
```
問題ごとに数値の渡され方が違うため、こんな感じのも必要。

## 計算系
```go
func abs(a int) int {
	if a > 0 {
		return a
	}
	return -a
}
func main() {
	a = abs(a)
}
```
↑引数の絶対値を返す。

```go
func gcd(a, b int) int {
	if b == 0 {
		return a
	}
	return gcd(b, a%b)
}
func main() {
	a := gcd(b, c)
}
```
↑引数二つの最大公約数を返す。

```go
func larger(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func smaller(a, b int) int {
	if a < b {
		return a
	}
	return b
}

func main() {
	l := larger(a, b)
	s := smaller(a, b)
}
```
↑引数二つのうち、大きい方、小さい方を返す

```go
func largest(a, b, c int) (lgst int) {
	if a > b {
		lgst = a
	} else {
		lgst = b
	}
	if c > lgst {
		lgst = c
	}
	return
}

func smallest(a, b, c int) (slst int) {
	if a < b {
		slst = a
	} else {
		slst = b
	}
	if c < slst {
		slst = c
	}
	return
}

func main() {
	l := lergest(a, b, c)
	s := smallest(a, b, c)
}
```
↑引数三つのうち、一番大きい、一番小さいのを返す

## 回答送信
```go
func yesOrNo(b bool) string {
	if b {
		fmt.Println("Yes")
	}
	fmt.Println("No")
}

func yesorNO(b bool) string {
	if b {
		fmt.Println("YES")
	}
	fmt.Println("NO")
}
func main() {
	yesOrNo(true)
	yesOrNO(false)
}
```
Yes,NoもしくはYES,NOで答える。`NO/No`で区別。問題ごとに丁度良いのを使う。

### 感想
テンプレ作成を始めてから間もないので、足りないもの、エラーの見落とし等があるかもしれません。
何か間違いや、おすすめの関数等ありましたら教えてください。

最後まで読んでいただき、ありがとうございました。