競プロの世界の端っこを覗いてみた（AtCoder Beginners Selection）

# はじめに

最近なぜか競プロ系のツイートがタイムラインに流れてくるので、ちょっとその世界の端っこを覗いてみることに。

**DISCLAIMER: これは感想文です。競技プログラミングについては、ためになる記事が他にたくさんあるのでそちらをご覧ください**

# プログラミング系サイト

ざっと調べてみたところ結構あるみたい。

- [AOJ](http://judge.u-aizu.ac.jp/onlinejudge/index.jsp?lang=ja)
    - 大学系のコンテストサイトっぽい
- [AtCoder](https://atcoder.jp/)
    - コンテスト系サイト。日本では一番有名？
- [LeetCode](https://leetcode.com/)
    - グローバルで一番有名か。過去問集みたいな感じ。GAFAなどの実際の面接にだされた問題もあるとかないとか
- [HackerRank](https://www.hackerrank.com/)
    - デベロッパと企業のマッチングサイト。コード書いてアピールするタイプっぽい
- [CodeChef](https://www.codechef.com/)
    - ぱっと見、コンテスト系サイト
- [exercism](https://exercism.io/)
    - 好きな言語選んで、コード提出したらメンターがみてくれる感じの学習サイト
- [CodeWars](https://www.codewars.com/)
    - [ここに説明があります](https://qiita.com/javacommons/items/7c473cda7825ab99e08c)


~~英語には抵抗ないので、`LeetCode`やろうとしたのだが、回答をどう書けばいいのかわかりにくくて、結局 `Atcoder` にする~~ 。

`2019/12/22` - `LeetCode` やってみたらこっちの方が遥かにUIはいいし、わかりやすい。今後は`LeetCode` にすると思う。英語に抵抗なければこっちをおすすめ。

# 自分なりの遊び方
- 全問を `ruby` と `go` で書き比べてみたら面白いかも。解きやすさや、解答のスコア（メモリ量や速度）をみてみるのは面白いかも。`go` の勉強にもなるだろう（あとでやってみる）
- テストを書きながらやってもいいかも

# AtCoder

Atcoderはいろいろと丁寧なガイドがある

- [AtCoder に登録したら次にやること ～ これだけ解けば十分闘える！過去問精選 10 問 ～](https://qiita.com/drken/items/fd4e5e3630d0f5859067)
- [こんなガイドのようなものまで発見](http://compro.tsutajiro.com/archive/190415_abs.pdf)
- 標準入力から値受けとって標準出力から結果をだす形式なので、どう書くかはわかりやすい。
- `Ruby` のバージョンは `2.3` しか選べない

# AtCoder Beginners Selection

### 解答
[ここ](https://github.com/narutaro/atcoder)に解答。まだ `ruby` だけ。

### Welcome to AtCoder
特に書くことがない

### Product
特に書くことがない

### Placing Marbles
特に書くことがない

### Shift only
特に書くことがない

### Coin
順列組み合わせ的な数学的手法できれいに解こうとするが失敗。単純に三重ループをぶん回すほうがよいというオチ

### Some Sums
`array.sum` が2.3では実装されていないところでちとハマったが、それ以外は簡単

### Card Game
文字列を `delete` で値で消すと、マッチする部分が全て消えるので、`delete_at` を使う。このために`ary.index` する。計算回数を無闇に増やさないしないようにしたいところ

### Kagami Mochi
`uniq` 使えば一行でかける。もちの個数 `N` は使わなくても解ける

### Otoshidama
各お札の枚数の組み合わせをつくるのに少し時間かかった。あと「複数の可能性が考えられるときは、そのうちどれを出力してもよい」という条件なのでテストがいままでと書き方変わる。

### Daydream
- このあたりから面白くなってくる
- `S` から配列の文字列を消していって、最終的に `S` がなくなるかどうかかという判定をすることにした
- `T` を考えるときに、前方一致でやると S = `dreameraser` は T = `dream` と `dreamer` に一致してしまう。前者は次に `eraser` を持ってくることで S = T つまり`YES` となるが、後者の場合は `NO` になってしまう。つまり最初のマッチだけでなく、マッチした全て（`dream` と `dreamer`）を`T`の候補としてあつかうことになるので、分岐が増えてうまくない
- `1≦|S|≦105` なので入力する文字はめっちゃ長いことがありえる。下手すると制限時間内（2sec）に終わらない（ここで、解けるのに時間がオーバ... となる）
- どうやら、前方一致ではなく、後方一致するといいようだ（後ろからマッチしていくと上記のようなことはなく候補は一意に決まる）
- 後方一致で書いてみるものの、それでも制限時間オーバ `TLE (Time Limit Exceeded)` をくらう
- 後方一致してその部分を消すときの正規表現が遅い `gsub!(/word$/, '')` と気付き、予め文字の長さを整数を渡して、文字を消すときには正規表現を使わずに `slice!(x..y)`で削除することで、全テストをパス（2s以上が100msへ）
- あとで気づくのが、消していく順番さえ間違えなければ `S` に対する全置換 `gsub!` だけで対応でき、3行くらいのコードで書ける。OMG...

### Traveling
このあたりになると、まず計算量のオーダが気になるようになる。この問題で正攻法で `N` 回動いた場合に到達する点を列挙とかやると、`N` が `10^5` までありえるので、死ぬことがすぐにわかる。

### 総評
それなりに楽しみながら解くことができました。

# スタックしたと思ったら
なんでうまくいかないんだ...  となったら

- [提出したコードのジャッジステータスはここ](https://atcoder.jp/contests/abc074/glossary?lang=ja)。回答が間違えているのか、時間かかりすぎているのか
- [公式コンテストのテストケースはここ](https://www.dropbox.com/sh/arnpe0ef5wds8cv/AAAk_SECQ2Nc6SVGii3rHX6Fa?dl=0)。一部のテストケースだけこける場合もどんなケースでこけるのか確認できそう。
- ググればいっぱい回答が出てくくるのでスタックはしないはず。

# 参考にさせていただいたサイト
- [こうしてGoogleに入社した(Kumagi編)](http://kumagi.hatenablog.com/entry/how-i-enter-google)
- [コーディング面接対策のために解きたいLeetCode 60問](https://1kohei1.com/leetcode/)
- [Googleからオファーをもらうまで](https://1kohei1.com/google/)

競技プログラミング系のサイトをググるとGoogle入社の話につながっていく法則を発見した。

# 感想文
- ああ、みんなこんなふうにプログラミングを楽しんでいるのね
- この Beginners Selection、いい感じの問題が揃っている印象
- 🐜本とか、🐅本とか、🌀本とかで基礎をやり直したくなる
- 競プロは数学じゃない。問題を数学的に綺麗に解こうとせず、ループぶん回して解決する方がいいものもある
- アイデアをコードにするのはやっぱり面白い
- やっぱり `ruby` の書きやすさは、ぱんぱねぇ
- 今回のやつを `go` でも書いてみる
- 普段はメタレイヤの業務で死んでいるが、プログラミングは今後も暇をみつけてやるぜ
- 開始時間指定のコンテストじゃなくて、空き時間にコツコツ問題といてスコア上げていく系のがやりたい