【paiza×Qiita】対象問題を解いてみた【C問題編】

# はじめに
近々，全く分野の異なる開発にチャレンジする機会があり，そちらの技術をキャッチアップするためにコーディングをしていたが，エラーが続き……
そんな萎えていたところに，面白そうなこちらのイベントを発見した．

という訳で，気分転換に，サクッと解いてみた．
気分転換が目的なので，解説や裏どりが雑かもしれませんが，それでも良ければ読んでやってください．

:::note
言語は普段の研究で利用しているPythonです
:::

**D問題編はこちら**

https://qiita.com/Yorozuya59/items/e96de37df88d914f31c1

**コードの一覧**

https://github.com/Yorozuya-59/paiza_qiita_colab/tree/main


# 残り物の量

https://paiza.jp/works/mondai/c_rank_skillcheck_archive/leftover

残りの残りを計算すれば良いので，

```math
\begin{align}
(\text{答え}) &= (\text{お惣菜に使った生鮮食品}) \times (100 - q)[\%] \\
&= \left\{ m[kg] \times (100 - p)[\%] \right\} \times (100 - q)[\%]
\end{align}
```

となります．
実装は以下の通り．

```python
m, p, q = map(int, input().split())

print(m * (1 - p / 100) * (1 - q / 100))
```

余談になりますが，上記の実装では誤差が発生します．
しかし，今回の問題設定では$10^{-4}$までの精度で良いので，特別な処理はおこなっていません．
この辺りの誤差についての説明は，非常に分かりやすい記事がたくさん存在するので，そちらに任せたいと思います．


# Fizz Buzz

https://paiza.jp/works/mondai/c_rank_skillcheck_sample/fizz-buzz

非常に有名な問題ですね．よくチュートリアルなどで紹介されているのを見かけます．
注意点は15の倍数（３と5の最小公倍数）の扱いをどうするかという点です．
実装は以下の通り．

```python
N = int(input())

for num in range(1, N+1):
    if num % 15 == 0:
        print('Fizz Buzz')
    elif num % 3 == 0:
        print('Fizz')
    elif num % 5 == 0:
        print('Buzz')
    else:
        print(num)
```


# みかんの仕分け

https://paiza.jp/works/mondai/c_rank_skillcheck_archive/mikan

ナイーブな実装（丁寧に区切りを確認する）でも良いのですが，つまらないので変わった実装を試してみます．

$i$番目の箱に入るみかんの重さの上限を考えてみると，

```math
N \times i + \frac{N}{2} [g]
```

となり，これ以上の重さのみかんは1つ上の重さの箱に仕分けられます．
従って，みかんの重さ$w$に対して，

```math
w < N \times i + \frac{N}{2} 
```

が成り立つのですが，$w$が整数で与えられていることから少し工夫して，以下のように与えておきます．（$N$の偶奇に注意する必要があります．）

```math
\begin{align}
w &\leq N \times i + \frac{N}{2} - 0.5 \\
i + 0.5 &\geq \frac{w + 0.5}{N} \\
i &\geq \frac{w + 0.5}{N} - 0.5
\end{align}
```

となり，上式から何番目の箱に仕分けられるかが求まります．

:::note warn
多少（かなり），説明を省いている箇所があります……
また，本実装は趣味の色が強めなので，そんな実装もあるのか程度に見てもらえると幸いです．
:::

以下，実装です．

```python
import math 


N, M = map(int, input().split())

for _ in range(M):
    w = int(input())

    boarder = (w + 0.5) / N - 0.5
    idx = math.ceil(boarder)
    print(N * idx if idx > 0 else N)
```

# 野球の審判

https://paiza.jp/works/mondai/c_rank_skillcheck_archive/umpire

こちらの問題は丁寧にカウントができるかを問うている問題ですね．
分岐が増えますが，身近な題材（野球のルールを知らない人が言うのも何ですが…）なので，混乱することも少ないと思います．
以下，実装です．

```python
N = int(input())

ball_count = 0
strike_count = 0

for _ in range(N):
    s = input()

    if s == 'ball':
        if ball_count == 3:
            print('fourball!')
            ball_count = 0
        else:
            print('ball!')
            ball_count += 1
    elif s == 'strike':
        if strike_count == 2:
            print('out!')
            strike_count = 0
        else:
            print('strike!')
            strike_count += 1
```


# 宝くじ

https://paiza.jp/works/mondai/c_rank_skillcheck_archive/lottery

本問題も先の問題と同じく，丁寧に分岐を処理できるかが問われていますね．
また，細かいところですが，当選番号が整数になっているため，文字列で処理するよりも整数型で処理する方が簡単かなと思います．（アルファベットが入ってくると文字列でどうにかするのが良いかもしれません．）
というわけで，以下実装です．

```python
b = int(input())
n = int(input())

for _ in range(n):
    a = int(input())
    
    # 1st Prize
    if a == b:
        print('first')
    # Adjacent Prize
    elif a == b - 1 or a == b + 1:
        print('adjacent')
    # 2nd Prize
    elif a % 10000 == b % 10000:
        print('second')
    # 3rd Prize
    elif a % 1000 == b % 1000:
        print('third')
    # Others
    else:
        print('blank')
```


# 最後に
今回の対象問題（Cランク）は以上です．
少し趣味の入った問題もありましたが，如何でしたでしょうか？