TOYPRO TTC001 解説/参加記

#TOYPROとは？
> 小学校5年生くらいから始める競技プログラミング、そしてPython！楽しく・飽きないように進められるようにシステムを目指しています! 

**公式Twitterより引用**

#はじめに
ならべくわかりやすく解説を書いていますが、自分より強い方々が先に解説をしているのもあるのでそちらもぜひご参照ください。
[TOYPRO TTC001 解説](https://qiita.com/cpcznksutbeoa/items/42abe29f3ac03fe5eb11) - @cpcznksutbeoa 
[TOYPRO TTC001 解説放送](https://www.youtube.com/watch?v=4_STwnZifEw) - @rute_not_route 

cpcさんの解説記事にもありますが、AtCoder経験者の参入によりコンテスト終了後の順位表が全完率90%とずいぶん面白いことになりました。

自分は普段C++でAtCoderなどのコンテストに参加しているのでPythonで競技プログラミングをするのは初めてです。
いい勉強になったと同時に記載するACコードにC++時の癖が残っていることに注意してください。

#おもちゃ 50点
推定AtCoder diff - 5

文字列Sが「toy」であるか否かを判定すればよいです。
この判定はif-else文を知っていると書くことができます。

ACコード

```python
s = "toy"

if s == "toy": 
    print("おもちゃ")
else: 
    print("おもちゃではありません")
```

#買って！買って！ 100点
推定AtCoder diff - 10

類題を解いたことがあるので解法はすぐ生えた。

pythonの文字列にはcountというメンバ関数があります。
これはcount(文字列)がもとの文字列に何回出現するかをカウントしてその値を返してくれます。
例えば、以下のような文字列Sで"Here"をcountすると3と表示されます。

```python
S = "HereThereHereHere"
print(S.count("Here"))
```

これを利用して簡単に解くことができます。
まず、「買って！」の回数はそれをつかってカウントするとして、その回数がnより多ければ「もう買わないよ」。
n以下であれば「買ってあげる」。
と表示することにします。

ACコード

```python
s = "買って！買って！"
n = 2

if s.count("買って！") <= n:
    print("買ってあげる")
else:
    print("もう買わないよ")
```

類題 : [ZONeエナジー プログラミングコンテスト “HELLO SPACE” A - UFO襲来](https://atcoder.jp/contests/zone2021/tasks/zone2021_a)

#トイproザラス 100点
推定AtCoder diff - 20 (難しめのA問題相当)

小学校の算数をつかって解くことができます。
簡単ですが、**小学五年生からの競技プログラミングと考えると適正難易度です。**

まず、購入額NがA以上であるか否かを判定します。
A円以上であれば割引してくれますが、逆にA円未満であればN円払う必要があります。

割引が効くときに払う金額は

```math
N - N \times \frac{B}{10} [円]
```
となります。

ここで、B/10をかける理由ですが、Bは割合なのでパーセント表示に直してあげる必要があるからです。
割り算を使いたくない場合は $B\times0.1$でも計算できます。

あとはこれをPythonで実装してやるとよいです。

注意点としては、出力に円をつけることと、割り算の計算により型が浮動小数点型になっていることです。
これは浮動小数点型をかっこで囲ってint形に変換してやるとよいです。

また、数値型と文字列型の計算はできないので、代金を文字列型に変換してから円と合成しましょう。

ACコード

```python
N = 197
A = 438
B = 10

if N < A:
    print(str(N)+"円")
else:
    print(str(int(N-(N*(B/10))))+"円")
```

#駄菓子屋に行こう 200点
推定AtCoder diff - 30

参加者が問題文で困惑していたので下のように問題文を言い換えることにします。

:::note warn
駄菓子屋に行くことにしました。
駄菓子屋へは家→大通→駄菓子屋の道をたどります。

ここで、家から大通にいくまでに$A$通りの道がありそれぞれ$A_i$分かかります。
同様に大通から駄菓子屋に行くまでに$B$通りの道があり、それぞれ$B_i$分かかります。

このとき、$m$分ぴったりで駄菓子屋に到着する道の選び方はありますか？
そのような選び方が存在するとき"Yes"を。
存在しないときは"No"を出力してください。
:::

このような問題においては考えられる道のりをすべて探索してやるとよいです。
$A_i$ の選び方がA通り。$B_i$ の選び方がB通り。
よって、すべての道の選び方は$A \times B$となります。

この組み合わせを調べるには2重ループを書いてあげるとよいです。

ACコード

```python
m = 10
a = [1, 1, 2, 5, 6, 5]
b = [4, 6, 7, 2, 5, 3]

for i in a:
    for j in b:
        if (i+j == m):
            print("Yes")
            exit()

print("No")
```

#お腹がすいた 200点
推定AtCoder diff - 30~50

見た目や問題文がナップザック問題に見えて少し怖いのですが、どうやらそんなことはないようです(ジャッジ時の想定解によると)

ここでは貪欲に満腹度が小さい食べ物から選んでいくことによって料理の最大数を達成することができます。

Pythonではリスト型のメンバ関数sortを使うことによって小さい順でリストを並べなおす(昇順ソートする)ことができます。

```python
A = [5, 4, 3, 2, 1]
print(A) #[5, 4, 3, 2, 1]

A.sort()
print(A) $[1, 2, 3, 4, 5]
```

これを利用することで簡単に解くことができます。

ACコード

```python
m = 10
a = [1, 2, 2, 1, 4, 5]

a.sort()

ans = 0
stuffed = 0

for i in a:
    stuffed = stuffed + i
    if stuffed <= m:
        ans = ans+1
    else:
        break

print(ans)
```

#お菓子いっぱい！ 300点
推定AtCoder diff - 30

問題文がわかりずらいやつです。

:::note warn
K円以上買うとくじびきが引けます。

Aから一つ。Bから一つ選んでK円以上にしてくじ引きを引くことにしました。
安いほうが嬉しいのでK円以上の組み合わせの最小値を出力してください。
:::

これもまた、2重ループで全探索をして、最小値を更新していくことで解くことができます。
300点問題ですが、解き方さえ知っていればほかの問題よりも簡単に解くことができると思います。


また、min関数を使うと、min(A, B)のうちAとBで小さいほうを返してくれます。
C++では内包表記で複数個の要素をmin関数に渡すことができますが、pythonでは普通にカンマで区切ってかいてしまってよいです。

```cpp:C++でのmin
#include <algorithm>

int main(){
    min({a, b, c, d, e})
}
```

```python:Pythonでのmin
min(a, b, c, d, e)
```

ACコード

```python
K = 10
A = [8, 5, 4]
B = [4, 1, 9]

ans = 1<<30

for i in A: 
    for j in B:
        if (i+j >= K):
            ans = min(ans, i+j)

print(ans)
```

#感想
やはり対象年齢層が低いのもあってかなり簡単な問題が出題されています。
しかしその分、プログラミング言語(Python)の学習的な問題に重きを置くことができていると思うので、これはこれでよい難易度だとも思います。(AtCoderなんかはもう数学なのでプログラミング言語の勉強やスキルアップというよりは受験勉強に近しいものがある。)

まだテスト段階のようですが、これから開催されるコンテストなどに期待していきたいですし、興味を持つ人が増えればよいなと思いました。

一方で、制約に配列のサイズを記してくれないなど、必要な制約の情報が抜け落ちていることが多いのでWriterの方はそのあたりをしっかり書いてくれると嬉しいなと思いました。

みなさんもTOYPRO。よかったらやってみてください。