HackerRankの30Days of Codeで学んだことメモ

# [HackerRank](https://www.hackerrank.com/dashboard)とは
- 課題を通じてプログラミング言語を学習できるサイト
- 無料
- 扱っている言語は多数
- その中の30Days of Codeというカリキュラムに挑戦

# 背景
- Goの基本的な書き方を学ぶために始めます
- 初心者です
- 自分の解答やEditorialの内容を基に書きます

# Day 1  Data Types

## ポイント
- 標準入力から整数、浮動少数点数、文字列を取得する

## メモ
- 標準入力の取得にはfmtパッケージの[Scanf関数](https://golang.org/pkg/fmt/#Scanf)が使える
- 引数にアドレスを指定することで、スペース区切りで順繰りに値を格納してくれる

```:入力
12 
4.0
```

```go
    //標準入力取得用変数
    var stdin_i uint64
    var stdin_f float64

    //標準入力から整数と浮動少数点数を取得
    fmt.Scanf("%d\n%f\n", &stdin_i, &stdin_f)
```

## 参考
- [文字列をscanf関数で扱うとき](https://qiita.com/Tsutajiro/items/a5620b17ac530cc96e87)
    - C言語を扱っているが考え方は同じ

# Day 2 Operators
## ポイント
- 入力された数値から簡単な演算を行い、四捨五入した整数を出力する

## メモ
- 出力時にフォーマットを指定できる`fmr.Printf()`を使用する
- 主なフォーマット指定方法
    - `%v` デフォルトのフォーマット
    -  `%f`　浮動小数点型の桁数を指定
        -  `%4.2f`では、4が幅、2が桁数を表す
            -  幅には整数部と小数点も含まれる
            -  0.3333333なら、0.33と表示される
    -  `%b` ビット表示

# Day 3 Intro to Conditional Statements

## ポイント
- 入力された整数の値に応じて条件分岐をif文で記載する

# Day 4 Class vs. Instance

## ポイント
- 新しく宣言した型にメソッドを定義する

## メモ
- 新しい型を宣言するときは、`type`を使用する
    - 新しい型を導入することでコードが読みやすくなったり、エラーを防ぎやすくなることがある

```go
type age int
```

- 構造体を使って複数の値を1つのグループにまとめて定義することもできる

```go
type person struct {
	age int
    name string
}
```

- メソットを使うと、関数を型に割り当てることができる

```go
// person型のageフィールドに1を加算するメソッド
func (p person) yearPasses() person {
    p.age += 1
	return p
}
```

- ここでの`(p person)`は「レシーバ」と呼ばれる


- メソッドを呼び出すときはドッド表記を使う

```go
p := person{age : 8}
p = p.yearPasses
fmt.Print(p.age) //9
```

# Day 5 Loops
## ポイント
- for文の書き方と標準出力(Day2参照)

## メモ
- 単純に`int`と宣言すると、ハードウェアに依存して32ビットや64ビットになる
- ただし、`int`、`int32`、`int64`はそれぞれ別の型
- 型が違うと代入も演算もできない

# Day 6 Let's Review

## ポイント 
- 標準入力の文字列を偶数番目の要素と奇数番目の要素に分けて出力する

##  メモ
- ここでは改行区切りの標準入力をbufioのScannerで読み込む
    - 標準入力の取得 : `std_in := bufio.NewScanner(os.Stdin)`
    - 一行読み込み : `std_in.Scan()`
    - 読み込んだ行を文字列として取り出す : `std_in.Text()`

## 参考
- [Go 言語で標準入力から読み込む競技プログラミングのアレ --- 改訂第二版](https://qiita.com/tnoda_/items/b503a72eac82862d30c6)

# Day 7 Arrays
## ポイント
- 入力された整数の配列を逆の順序で出力する

# Day 8 Dictionaries and Maps
## ポイント
- 標準入力から名前と電話番号から成るMapを作成
- その後入力される名前がマップに存在するかを判定する

## メモ
- 初期化する必要がない場合は、make関数で割り当てる
    - `phoneBook := make(map[string] string)`
    - これは、Key、ValueがどちらもStringのMapを表す
- マップに値を設定するには以下のようにする
    - phoneBook["sam"] = "99912222"
- mapにStringを渡すと、値とbool値の2つが返ってくる
    - 存在する場合に処理を行うときは、以下のようなif文を書く

```
if number, ok := phoneBook["sam"]; ok{
    [マップにKeyが存在した場合の処理]
}
```

# Day 9 Recursion 3
## ポイント
- 入力された自然数`n`から`n!`を出力する

## メモ
- 遅延実行の`defer`
    - `defer`によって指定されたアクションは、その関数からリターンされる前に必ず実行されることが保証される
    - ファイルのクローズなどに使える

# Day 10 Binary Numbers
## ポイント
- 入力された自然数を二進数に変換し、最大で"1"がいくつ連続しているかを出力する

## メモ
- `fmt.Sprintf`は指定した書式に合わせて文字列を返す
    - 5の二進数を文字列で取得する場合は、`fmt.Sprintf("%b", 5)`と記載すればよい
- 文字列中の個々の文字にアクセスすることができるが、返ってくるのはUnicodeの符号位置になる
    - 例えば、`s="101"`という文字列に対し、`s[1]`を出力すると`48`が出力される
    - これは0の符号位置が48のためである
    - 文字そのものを表示するには書式指定子に`%c`を指定すればよい
    - 先ほどのSprintfを使って、`c=fmt.Sprintf("%c", s[1])`とすれば、`c`は0になる

# Day 11 2D Arrays
## ポイント 
- 6×6の二次元配列から、3×3の大きさの砂時計型で切り取れる部分の和を計算し、最大値を出力する

# Day 20 Sorting
##ポイント
- 整数の配列をバブルソートで並び替える

# Day 25 Running Time and Complexity
## ポイント
- 入力された自然数が素数であるかを判定する

# Day 26 Nested Logic
##ポイント
- 入力された2つの日付を比較する

## メモ
- 指定されたDate型の変数を作成するには`time.Date()`を指定する
    - 引数には、年、月、日、時、分、秒、ナノ秒、タイムゾーンを指定する
    - `targetDate := time.Date(2001, 2, 3, 4, 5, 6, 0, time.Local)`
- 2つの日付を比較する場合はTime型のBeforeメソッド、Afterメソッドを使う
    - `if timeA.Before(timeB) {...}`

# Day 28 RegEx, Patterns, and Intro to Databases
## ポイント
- 入力される名前とメールアドレスから成る文字列から、メールアドレスがgmailのユーザーの名前だけを抽出し、アルファベット順にソートして出力する

## メモ
- メールアドレスがgmailかどうかは後方一致で判定する
    - 後方一致には`strings.HasSuffix`関数を使用する
    - `if strings.HasSuffix(emailID, "@gmail.com"){...}`
- Stringの並び替えであれば、`sort.Strings`関数が使える
    - `sort.Strings(gmailUser)`