paizaプログラミング問題Rank C, D (Python)

[paiza×Qiita記事投稿キャンペーン](https://paiza.jp/pages/campaign/paiza-qiita)に参加しました．
ここに書いたプログラムの関連リポジトリは，以下になります．

https://github.com/tomtkg/Python-Sample/tree/main/paiza

ここでは，Rank C, D問題の解答と簡単な解説を公開します．
言語はPythonを選択しました．結果は以下のようになりました．

# Rank C
## 残り物の量
https://paiza.jp/works/mondai/c_rank_skillcheck_archive/leftover

```python:leftover.py
m, p, q = map(int, input().split())
print(m * (100 - p) * (100 - q) / 1e4)
```
入力文字列を数値`m`，`p`，`q`に分配し，数値演算します．
なるべく整数で計算して，一番最後で小数表記に直す除算を適用しています．

パーセント表記は，安易に小数表記に直さない方が良いです．
`print(m * (1-p/100) * (1-q/100)) = 0.11999999999999997`みたいになる可能性があります．

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

```python:fizz_buzz.py
for i in range(1, int(input()) + 1):
    print(
        "Fizz Buzz" if i % 15 == 0
        else "Fizz" if i % 3 == 0
        else "Buzz" if i % 5 == 0
        else i
    )
```
`0`始まりではなく，`1`始まりでループしています．
`i`が15，3，5の倍数である場合とそれ以外の場合で条件分岐しています．

## みかんの仕分け
https://paiza.jp/works/mondai/c_rank_skillcheck_archive/mikan

```python:mikan.py
N, M = map(int, input().split())
for _ in range(M):
    print(max(N, (int(input()) + N // 2) // N * N))
```
この問題は，`if`による条件分岐なしで記述可能です．
`(x + N // 2) // N * N`で，数値`x`は一番近い`N`の倍数に変換されます．
`max(N, x)`で出力の最小値は0から`N`に変化します．

`//`は切り捨て除算をする演算子で，割り算の商を整数で返します．余りは無視します．
<details><summary><code>(x + N // 2) // N * N</code>の計算例</summary>

* (11 + 8 // 2) // 8 * 8) ⇒ 15 // 8 * 8 ⇒ 1 * 8 ⇒ 8
* (12 + 8 // 2) // 8 * 8) ⇒ 16 // 8 * 8 ⇒ 2 * 8 ⇒ 16
* (13 + 8 // 2) // 8 * 8) ⇒ 17 // 8 * 8 ⇒ 2 * 8 ⇒ 16
<p></p>

* (12 + 9 // 2) // 9 * 9) ⇒ 16 // 9 * 9 ⇒ 1 * 9 ⇒ 9
* (13 + 9 // 2) // 9 * 9) ⇒ 17 // 9 * 9 ⇒ 1 * 9 ⇒ 9
* (14 + 9 // 2) // 9 * 9) ⇒ 18 // 9 * 9 ⇒ 2 * 9 ⇒ 18
</details>

Pythonの`round`関数は偶数丸め（銀行丸め）のため，利用は不適切です．
四捨五入（R丸め）を実装するか，`Decimal`の`quantize`関数を使うのが良いです．
(自分も最初`round`関数を利用していました．コメントありがとうございます)

## 野球の審判
https://paiza.jp/works/mondai/c_rank_skillcheck_archive/umpire

```python:umpire.py
for _ in range(int(input()) - 1):
    print(input() + "!")
print("fourball!" if input() == "ball" else "out!")
```
最後の入力とそれ以前の入力で処理を分けました．
今回の入力形式の場合，最後のコールは最後の入力だけで判別できます．

## 宝くじ
https://paiza.jp/works/mondai/c_rank_skillcheck_archive/lottery

```python:lottery.py
b = input()
for _ in range(int(input())):
    v = input()
    print(
        "first" if b == v  # 1等：当選番号と一致する番号
        else "adjacent" if abs(int(b) - int(v)) == 1  # 前後賞：当選番号±1の番号
        else "second" if b[-4:] == v[-4:]  # 2等：当選番号と下4桁が一致する番号
        else "third" if b[-3:] == v[-3:]   # 3等：当選番号と下3桁が一致する番号
        else "blank"
    )
```
Fizz Buzz問題と同様に条件分岐をたくさん書く必要があります．
前後賞の判定時のみ入力を数値に変換しています．

文中に`下4桁`と書かれていて，入力への依存もなるべく減らしたかったため，
`b[2:] == v[2:]`ではなく，`b[-4:] == v[-4:]`と記述しています．

# Rank D
## N倍の文字列
https://paiza.jp/works/mondai/d_rank_skillcheck_archive/square

```python:square.py
print("*" * int(input()))
```
`N倍`と書いてあるので，素直に掛け算を使います．

## Eメールアドレス
https://paiza.jp/works/mondai/d_rank_skillcheck_archive/email_address

```python:email_address.py
print(input() + "@" + input())
```
`+`で文字列を結合します．

## 足し算
https://paiza.jp/works/mondai/d_rank_skillcheck_sample/addition

```python:addition.py
print(sum(map(int, input().split())))
```
足し算(`+`)ではなく合計(`sum`)を使うと，3個以上の数値にも対応できます．
以下のようにリスト内包表記を使う方法もあります．
```python
print(sum(int(x) for x in input().split()))
```

## 一番小さい値
https://paiza.jp/works/mondai/d_rank_skillcheck_sample/min_num

```python:min_num.py
print(min(int(input()) for _ in range(5)))
```
リスト内包表記で，`input()`を5回呼び出しています．

## 文字の一致
https://paiza.jp/works/mondai/d_rank_skillcheck_sample/diff_str

```python:diff_str.py
print("OK" if input() == input() else "NG")
```
`print`の内部で三項演算子を利用しています．

# 終わりに
Rank C, D問題は比較的簡単に解けました．
pythonの基本的な文法や標準入力の方法を復習するのにちょうど良い問題だと思います．

関連記事

https://qiita.com/tomtkg/items/22810085c548b134e8ce

https://qiita.com/tomtkg/items/2c3b737848e47ff91903