Goの競技プログラミングチートシート

# このチートシートについて

「**Trackなどのコードテスト**」や「**Atcoder**」や「**Paiza**」などといった競技プログラミングでよく使われる処理をサンプルコードとして書いていきます。

また、何か追加情報やより良いものなど変更があった場合は更新していきます。

:::note warn
私自信が競技プログラミングを受けた時に、頻出したコードを随時更新していきます。

なので、実際には足りていないところもあると思います。
そこはご了承いただけると幸いです。
:::

# 概要
自動の目次生成のあるがあるため必要ないかもしれないが、念の為目次の作成

|No|概要|
|:--|:--:|
|1| [標準出力](#標準出力) |
|2| [標準入力](#標準入力) |
|3| [文字列分割して配列に格納](#文字列分割して配列に格納) |
|4|[文字列、整数変換](#文字列、整数変換)|
|5|[スライス](#スライス) |
|6| [マップ](#マップ)  |
|7| [ソート](#ソート)  |

## 標準出力
主に使われる、**fmt.Println()** と **fmt.Printf()** を紹介します。

### fmt.Println()

```go:main.go
package main

import "fmt"

func main() {
	name := "佐藤"
	age := 21
    fmt.Println(name)
	fmt.Println(name, age)
	fmt.Println("名前は", name, "です。年齢は", age, "際です。")
}
```
```terminal:実行結果
佐藤
佐藤 21
名前は 佐藤 です。年齢は 21 際です。
```

### fmt.Printf()

↑と同じようにこちらでも表示してみます。

```go:main.go
package main

import "fmt"

func main() {
	name := "佐藤"
	age := 21
    fmt.Printf("%s\n", name)
	fmt.Printf("%s %d\n", name, age)
	fmt.Printf("名前は%sです。年齢は%d際です。\n", name, age)
}
```
```terminal:実行結果
佐藤
佐藤 21
名前は佐藤です。年齢は21際です。
```

#### デフォルトフォーマット「%v」
Goでは、先ほど使用した「%s」や「%d」を使用せずに、「**%v**」でフォーマットすることができます。

```go:main.go
package main

import "fmt"

func main() {
	name := "佐藤"
	age := 21
	fmt.Printf("%v\n", name)
	fmt.Printf("%v %v\n", name, age)
	fmt.Printf("名前は%vです。年齢は%v際です。\n", name, age)
}
```
```terminal:実行結果
佐藤
佐藤 21
名前は佐藤です。年齢は21際です。
```


## 標準入力
### 標準入力する方法
**fmt.Scan()** で標準入力を行う
```go:main.go
package main

import (
	"fmt"
)

func main() {
	var str string
	fmt.Scan(&str)    //　データを格納する変数のアドレスを指定
	fmt.Println(str)
}
```
```terminal:実行結果
123
123
```
競技プログラミングでは、スペースで区切って複数の文字列を取得しますが、このままだと取得できません。


```terminal:複数の文字列の実行結果
abc def 123
abc
```

↑"def 123"が取得できていない！！


### 複数の文字列を取得する方法

変数を**配列型**にすると複数受けとることができます。

```go:main.go
package main

import (
	"fmt"
)

func main() {
	vvar str [3]string
	fmt.Scan(&str[0], &str[1], &str[2])
	fmt.Println(str)
}
```
```terminal:実行結果
abc def 123
[abc def 123]
```
しかし、配列で**3つまで**と格納できないよう指定しているため、4つ目以降の文字列を取得するできなくなってしまいます。

### 上限なしで複数の文字列を取得する方法

bufioパッケージの**Newcanner()**メソッドを使います。

```go:main.go
package main

import (
	"bufio"
	"fmt"
	"os"
)

func main(){
	scanner := bufio.NewScanner(os.Stdin) // 標準入力を受け付けるスキャナー
	scanner.Scan()                        // 入力を取得する
	fmt.Println(scanner.Text())
}
```
```terminal:実行結果
123 456 abc def ghi
123 456 abc def ghi
```

こちらは半角スペースも含めた文字列で複数の文字列を取得します。

### 複数行の文字列を入力する

先ほどを少し改良して１行だけでなく複数行の文字列を取得する方法です。


```go:main.go
package main

import (
	"bufio"
	"fmt"
	"os"
)

func main(){
	var str []string
	n := 3
	scanner := bufio.NewScanner(os.Stdin) // 標準入力を受け付けるスキャナー
	for i := 0; i < n; i++ {
		scanner.Scan()
		str = append(str, scanner.Text())
	}

	for i, v := range str {
		fmt.Printf("line[%d]: %v\n", i, v)
	}
}
```
```terminal:実行結果
123 456 789
abc def ghi
ABC DEF GHI
line[0]: 123 456 789
line[1]: abc def ghi
line[2]: ABC DEF GHI
```

### 複数行の文字列を入力する(その2)
最後に**Track**さんでのコードテストであった標準入力を紹介します。

```go:main.go
package main

import (
	"fmt"
	"io/ioutil"
	"os"
	"strings"
)

func main() {
    lines := getStdin()
	for i, v := range lines {
		fmt.Printf("line[%d]: %v\n", i, v)
	}
}

func getStdin() []string {
	stdin, _ := ioutil.ReadAll(os.Stdin)
	return strings.Split(strings.TrimRight(string(stdin), "\n"), "\n")
}
```
```terminal:実行結果
123 456 789
abc def ghi
ABC DEF GHI
line[0]: 123 456 789
line[1]: abc def ghi
line[2]: ABC DEF GHI
```

こちらは、回数制限がないので、自由に複数行の文字列を取得することができます。



## ファイル読み込み


main.goと同じディレクトリに「test.txt」を用意しました。
```test.txt
テスト用ファイル
こんにちは！
```

```go:main.go
package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"os"
)

func main() {
    f, err := os.Open("./test.txt")
	if err != nil {
		log.Fatal(err)
	}
	defer f.Close()

	b, err := ioutil.ReadAll(f)
	if err != nil {
		log.Fatal(err)
	}

	str := string(b)
	fmt.Println(str)
}
```
```terminal:実行結果
テスト用ファイル
こんにちは！
```

## 文字列分割して配列に格納

```go
arr := strings.Split(str, " ")
```

```go:main.go
package main

import (
	"fmt"
	"strings"
)

func main() {
	str := "abc def ghi"
	fmt.Println("文字列: ", str)

	arr := strings.Split(str, " ")
	fmt.Println("配列: ", arr)
}
```
```terminal:実行結果
文字列:  abc def ghi
配列:  [abc def ghi]
```


## 文字列、整数変換
```go
num, _ := strconv.Atoi("123")
str, _ := strconv.Itoa(123)
```

```go:main.go
package main

import (
	"fmt"
	"strings"
)

func main() {
	strNum := "123"
	fmt.Println(strNum, reflect.TypeOf(strNum))

	num, _ := strconv.Atoi(strNum)
	fmt.Println(num, reflect.TypeOf(num))
}
```
```terminal:実行結果
123 string
123 int
```

## スライス

### 初期化
```go
var sInt []int
var sStr []string
```
```go
var sInt = []int{1, 2, 3}
var sStr = []string{"apple", "banana", "lemon"}
```

### 追加
```go
sInt = append(sInt, 100)
```

```go:main.go
package main

func main() {
    var sInt = []int{1, 2, 3}
    sInt = append(sInt, 100)
    fmt.Println(sInt)
}
```
```terminal:実行結果
[1 2 3 100]
```

### 長さ
```go
var sInt = []int{1, 2, 3}
len(sInt)    // 3
```

## マップ

### 初期化

```go
makeMap := make(map[int]string)
```

### 追加
```go
makeMap[1] = "apple"
makeMap[2] = "banana"
```
```go:main.go
package main

import "fmt"

func main() {
    makeMap := make(map[int]string)
	makeMap[1] = "apple"
	makeMap[2] = "banana"
	
	fmt.Println(makeMap)
    fmt.Println("makeMap[1]: ", makeMap[1])
}
```
```terminal:実行結果
map[1:apple 2:banana]
makeMap[1]:  apple
```


## ソート

### スライスのソート

#### 整数のソート
```go
// 昇順
sort.Ints(sInt)
// 降順
sort.Sort(sort.Reverse(sort.IntSlice(sInt)))
```
```go:main.go
package main

import (
	"fmt"
	"sort"
)

func main() {
    sInt := []int{3, 2, 6, 1, 6, 3, 9, 3, 2, 1}

	// 昇順
	sort.Ints(sInt)
	fmt.Println("昇順: ", sInt)

	// 降順
	sort.Sort(sort.Reverse(sort.IntSlice(sInt)))
	fmt.Println("降順: ", sInt)
}
```
```terminal:実行結果
昇順:  [1 1 2 2 3 3 3 6 6 9]
降順:  [9 6 6 3 3 3 2 2 1 1]
```

#### 文字列のソート
```go
// 昇順
sort.Strings(sStr)
// 降順
sort.Sort(sort.Reverse(sort.StringSlice(sStr)))
```
```go:main.go
package main

import (
	"fmt"
	"sort"
)

func main() {
    sStr := []string{"b", "a", "z", "r", "d"}

	// 昇順
	sort.Strings(sStr)
	fmt.Println("昇順: ", sStr)

	// 降順
	sort.Sort(sort.Reverse(sort.StringSlice(sStr)))
	fmt.Println("降順: ", sStr)
}
```
```terminal:実行結果
昇順:  [a b d r z]
降順:  [z r d b a]
```


### マップのソート

#### 整数のキー順
```go
// スライスにキーだけを格納してソートする
slice := make([]int, len(map1))
index := 0
for key := range map1 {
	slice[index] = key
	index++
}
sort.Ints(slice)
```
```go:main.go
package main

import (
	"fmt"
	"sort"
)

func main() {
    map1 := map[int]string{
		3: "e", 2: "q", 5: "a", 1: "r",
	}

	// キーをソートする
	slice := make([]int, len(map1))
	index := 0
	for key := range map1 {
		slice[index] = key
		index++
	}
	sort.Ints(slice)

	//列挙
	for _, key := range slice {
		fmt.Println(key, map1[key])
	}
}
```
```terminal:実行結果
1 r
2 q
3 e
5 a
```


#### 文字列のキー順
```go
// スライスにキーだけを格納してソートする
slice := make([]string, len(map1))
index := 0
for key := range map1 {
	slice[index] = key
	index++
}
sort.Strings(slice)
```
```go:main.go
package main

import (
	"fmt"
	"sort"
)

func main() {
    map1 := map[string]int{
		"z": 1, "a": 10, "c": 4, "d": 5,
	}

	// キーをソートする
	slice := make([]string, len(map1))
	index := 0
	for key := range map1 {
		slice[index] = key
		index++
	}
	sort.Strings(slice)

	//列挙
	for _, key := range slice {
		fmt.Println(key, map1[key])
	}
}
```
```terminal:実行結果
a 10
c 4
d 5
z 1
```

# 参考サイト

[fmt - Go Packages](https://pkg.go.dev/fmt)

[bufio - Go Packages](https://pkg.go.dev/bufio)

[sort - Go Packages](https://pkg.go.dev/sort)

[備忘】Go 言語の標準入力の基本的なこと](https://qiita.com/t-yama-3/items/99ecf0466e5e0f080815)

[【Go】基本文法④(配列・スライス)](https://qiita.com/k-penguin-sato/items/daad9986d6c42bdcde90)

[【Go】基本文法⑤(連想配列・ Range)](https://qiita.com/k-penguin-sato/items/a320072fa09502bde3e9)

[Go の map を「キーの辞書順に」列挙する](https://qiita.com/zetamatta/items/2f8d8002c01de73807e6)


# よかったら他の記事も見ていってね！
[動かして覚える！Goでデータベースの基本的な接続方法とCRUD操作](https://qiita.com/Rqixy/items/bcac0f84a537ecbc1ab4)

[動かして覚えるGoのモジュールの使い方](https://qiita.com/Rqixy/items/b906fcb54cf162427775)

[動かして覚えるGoのWorkspaceモードの使い方](https://qiita.com/Rqixy/items/6bdead71dc02eb233376)