Go で競技プログラミング攻略１ (AtCoder Beginners Selection 1~6)

# はじめに
この記事は自分のためにメモとして書いてあるので書き方はテキトー
間違っていたりこうしたらいいよっていうのは教えていただけるとありがたいです
競プロはマジの初心者スタートでやっていきたいと思います


# Tutrial
## [A - Welcome to AtCoder](https://atcoder.jp/contests/practice/tasks/practice_1)

答え見えちゃったので忘れたフリして書いていく。。。うまくいかねぇ
仕方なく答えチラ見

<strong>ポインタ使ってやってるヤンケーーー!!</string>

ポインタはC言語学ぶ上でつまづいてなんだか分からず使ってたあのやつ！！！(結局わからん)


調べてみると Scanfに指定する変数はポインタで渡さないと行けないらしい。
```Scanf("%d", &a)```
fmtはCから派生したものらしい

しかたねえ、、、
良さそうな記事見つけたのでそれ読んで理解できなかったら、なんとなくで、、、、
[Goで学ぶポインタとアドレス](https://qiita.com/Sekky0905/items/447efa04a95e3fec217f)


んー、、、まあ、なんとなく
どんな時に使うといいのか正直わからん。
まあいいや。　次いこう
<br>
<br>
##[ABC086A - Product](https://atcoder.jp/contests/abs/tasks/abc086_a)

```main.go
package main
 
import "fmt"
 
func main() {
	var a, b int
	fmt.Scanf("%d %d", &a, &b)
	if (a*b)%2 == 0 {
		fmt.Printf("Even")
	} else {
		fmt.Printf("Odd")
	}
}
```

hahaha!!! 行けるやんおれ

次
<br>
<br>
##[ABC081A - Placing Marbles](https://atcoder.jp/contests/abs/tasks/abc081_a)

１数字ずつ読み込むのって
```fmt.Scanf("%d%d%d", &s1, &s2, &s3)```
でええんか？？
うまくいかんよなw　だと思った
<br>
標準入力で一文字ずつを入力する方法をggる

数学的に処理する方法を発見
[Go で int を1桁ずつ slice に入れる](https://qiita.com/Asuforce/items/42ea19ed10b68de53afb)

これ通りに書いていこう

###拡張forの書き方

```go

	for index, value := range numList {
		処理内容
	}
```
<br>
### intを一桁ずつ配列にいれる

```main.go
func splitNumber(num int, numList []int) []int {
	for 0 > num {
		return splitNumber(num/10, append(numList, num%10))
	}
	return numList
}

```

むむっ！！！！

ここで問題発生
配列にappendしても数値が思い通りに入ってくれていない

これはまたしてもポインタのせいか？？？
これは、、、
~~<strong> 参照渡しになっているからだあぁぁぁ！！！ </strong>~~
心優しい方がgoには、参照渡しなんて存在しねえ。戻り値を変数に代入し忘れてるだけや

ということであっさり解決

```main.go
package main

import "fmt"

func main() {
	var S int
	var numList []int
	var sum int
	fmt.Scanf("%d", &S)

	numList = splitNumber(S, numList)
//合計値を算出
	for _, v := range numList {
		sum += v
	}
	fmt.Printf("%d", sum)
}

//numを一桁ずつnumListに格納
func splitNumber(num int, numList []int) []int {
	for num > 0 {
		return splitNumber(num/10, append(numList, num%10))
	}
	return numList
}
```

おっけい！クリア！！
<b>
## [ABC081B - Shift only](https://atcoder.jp/contests/abs/tasks/abc081_b)

これは入力をスプリットして配列に格納してなんとかすんじゃね？
って思ったので書いてみることに
<br>
### 文字列1行を読み込む

```go
func scanStringLine() string {
	var strLine string
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Scan()
	strLine = scanner.Text()
	return strLine
}
```

入力をスプリットしていろいろするならstring型の配列からint型の配列の方がいいよね
ってことで変換する関数を書いてみる


### []string から []intに変換
```go
func StrToInt(strList []string) []int {
	var numList []int
	var toInt int
	for _, v := range strList {
		toInt, _ = strconv.Atoi(v)
		numList = append(numList, toInt)
	}
	return numList
}
```

ok ok~~
問題文は　与えられた数字が全て２で割れるなら、与えられた数字を2で割る。それができる回数を求めよ
なので
カウンターを書いていく

```go
func counter(count int, numList []int) int {
	flag := false
	for flag == false {
		for i, v := range numList {
			if v%2 == 0 {
				numList[i] = v / 2
			} else {
				flag = true
				return count
			}
		}
		count++
	}
	return count
}
```
<br>
......絶対もっと上手い書き方がある気がする
とりあえずガッチャンコしてみよう

```main.go
package main

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

func main() {
	var N int
	var strNumbers string
	var numList []int
	var arr []string

	//最初の一文字
	fmt.Scanf("%d", &N)
	strNumbers = scanStringLine()

	arr = strings.Split(strNumbers, " ")
	numList = StrToInt(arr)
	fmt.Println(counter(0, numList))
}

func counter(count int, numList []int) int {
	flag := false
	for flag == false {
		for i, v := range numList {
			if v%2 == 0 {
				numList[i] = v / 2
			} else {
				flag = true
				return count
			}
		}
		count++
	}
	return count
}

//文字列を１列入力
func scanStringLine() string {
	var strLine string
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Scan()
	strLine = scanner.Text()
	return strLine
}

//string型の配列からint型の配列に変換
func StrToInt(strList []string) []int {
	var numList []int
	var toInt int
	for _, v := range strList {
		toInt, _ = strconv.Atoi(v)
		numList = append(numList, toInt)
	}
	return numList
}

```

これでテイシュッツ！

クリア！！


## [ABC087B - Coins](https://atcoder.jp/contests/abs/tasks/abc087_b)

うーん、、、
上手いやり方が思いつかない、、、

詰まってしまったのでggる。
ほう、普通に総当たり的に全てを試して行っている、、、

思いついたけどこれが正解みたい。
<strong>原始的な方法もやってみることが大事そう</strong>

ということで書いていく

~~~go
package main

import "fmt"

func main() {
	//500円玉の枚数
	var a int
	//100円玉の枚数
	var b int
	//50円玉の枚数
	var c int
	//合計金額
	var x int

	fmt.Scanf("%d\n", &a)
	fmt.Scanf("%d\n", &b)
	fmt.Scanf("%d\n", &c)
	fmt.Scanf("%d\n", &x)
	fmt.Println(counterCoins(a, b, c, x))
}

func counterCoins(a int, b int, c int, x int) int {
	count := 0

	for i := 0; i <= a; i++ {
		for j := 0; j <= b; j++ {
			for k := 0; k <= c; k++ {
				if i*500+j*100+k*50 == x {
					count++
				}
			}
		}
	}
	return count
}

~~~

## [ABC083B - Some Sums](https://atcoder.jp/contests/abs/tasks/abc083_b)

みた感じ　ABC081A - Placing Marbles　で使った1桁を配列にいれるのを使いそう
チャチャット書いてみる

### 1桁ずつ配列にいれ桁ごとの総和を戻り値にして返す
~~~go
//1桁ずつ配列にいれ桁ごとの総和を戻り値にして返す
func splitNumberSum(num int, numList []int) int {
	sum := 0
	for num > 0 {
		return splitNumberSum(num/10, append(numList, num%10))
	}
	for _, v := range numList {
		sum += v
	}
	return sum
}
~~~


これだとあんまりカッコよくない(numListらへんが)ので改造

### 桁の総和を戻り値にして返す
~~~go
//桁の総和を戻り値にして返す
func splitNumberSum(num int, tmp int) int {
	for num > 0 {
		tmp += num % 10
		return splitNumberSum(num/10, tmp)
	}
	return tmp
}
~~~
ええやん
カッコよくなった！！

あとは
A,Bの条件に合うものは加算する
をNまでfor文で回す

~~~go
//A,Bの条件に合うかどうか判定し、真であればAnswerSumに加算する
func countSum(N int, A int, B int) int {
	AnswerSum := 0
	sum := 0
	for i := 1; i <= N; i++ {
		sum = splitNumberSum(i, 0)
		if A <= sum && sum <= B {
			AnswerSum += i
		}
	}
	return AnswerSum
}
~~~

あとはこの二つとmain関数をガッチャンコ

~~~go
package main

import "fmt"

func main() {
	var N int
	var A int
	var B int

	fmt.Scanf("%d %d %d", &N, &A, &B)
	fmt.Println(countSum(N, A, B))
}

func countSum(N int, A int, B int) int {
	AnswerSum := 0
	sum := 0
	for i := 1; i <= N; i++ {
		sum = splitNumberSum(i, 0)
		if A <= sum && sum <= B {
			AnswerSum += i
		}
	}
	return AnswerSum
}

//桁の総和を戻り値にして返す
func splitNumberSum(num int, tmp int) int {
	for num > 0 {
		tmp += num % 10
		return splitNumberSum(num/10, tmp)
	}
	return tmp
}

~~~
できた！！！！

#思ったこと

最初だからか標準入力系が多い気がした。自分だけの便利パッケージ作っておくと後々楽そう。
意外とつまずきまくってたので、なんとなく勉強しただけなんだなぁと実感。
でも、こういうのが成長には大切だと思うので頑張るんば。