算数が苦手な人にページネーションを教える方法

先生、ページネーションのやり方がわかりません！

こんな相談が来たらみなさんはどのように対応しますか？
答えを教えますか？ヒントを出しますか？それとも「ググってね」で放置しますか？

エンジニア・プログラマ志望の人がみな算数・数学が得意なわけではありませんので、必ず教えなければならない場面が来ると思います。
なので、分かりやすい教え方を考えましょう。

コード例は Python で記述しています。

## TL;DR

- 具体例で考えるときに、思考のプロセスをすべて紐解く作業をさせましょう
- あなたの教え方次第でその人の人生が決まるといっても過言ではありません

## こんな問題を考えます

とある在庫管理システムの一覧画面では、在庫を 1 ページに最大で 100 件表示します。
その際、以下の項目を合わせて表示します。

- 在庫は全部で何件あるか
- 全部で何ページあるのか
- 現在、何ページ目か

そこで、在庫の件数が与えられたとき、全部で何ページあるかを返す関数を作成してください。

## アプローチ

**ここからは問題の意味を理解できた前提で進めます。**

解法の切り口が思いつかない場合、どうすればいいでしょうか。
中学数学で文字が出てきてややこしくなったのを思い出しましょう。

そうです。具体例で考えるのでした。

### 在庫 n 件なら何ページある？

以下の例を考えます。

- 在庫が 5 件あったら全部で何ページある？
- 在庫が 200 件あったら全部で何ページある？
- 在庫が 210 件あったら全部で何ページある？

在庫が 5 件のときはどうでしょうか？
1 ページに最大 100 件表示できるので、全部で 1 ページで収まりそうです。

200 件のときはどうでしょう？
2 ページですね。

205 件のときは・・・
2 ページだと足りませんね。
3 ページあったら 300 件まで表示できるので足りそうです。

#### その数字はどうやって出したの？

以上のアプローチだけではコードになりませんので、もう少し頑張りましょう。

例えば

**「在庫が 200 件」→「2 ページ」はどうやって出しましたか？**

これを自分の力で考えましょう。意地でも自分で考えましょう。

> 「100 で割った」

これが出てくればベストかと思います。

> 「1 ページだと 100 件までで、これだと 100 件足りないからもう 1 ページ増やして 2 ページ」

これでも理屈的には合っています。だけど 100 万件のときに 1 ページずつ増やしていたら日が暮れます。

「200 = 100 × 2」→「200 ÷ 100 = 2」という方向に持っていけるといいですね。

では **「在庫が 205 件」→「3 ページ」はどうやって出しましたか？**

> 「2 + 1 = 3」・・・？

なるほど。その 2 と 1 はどうやって出したか、考えましょう。

「205 = 200 + 5」→「2 ページ + 1 ページ」という考えになったらもう一息です。

どうして 205 を 200 と 5 に分けたんでしょうか？

きっと無意識的に「200 = 100 × 2」の計算をしていたのですね。とすると？

「205 = 100 × 2 + 5」となります。
これは 205 を 100 で割ると商が 2 で余り 5 であることと同じです。
**余りがあるときは 1 ページ増やした** ということですね。

すると、先ほどの 200 件の場合は **余りが 0 なので 1 ページ増やす必要がない** とも取れます。

#### コード

今までのことをまとめると以下のようになります。

- 在庫件数を 100 で割る
  - 余りがあるときは「商 + 1」がページ数になる
  - 余りがないときは「商」がページ数になる

```python
def get_page_count(item_count: int) -> int:
    # 在庫件数
    item_count: int
    # ページ数
    page_count: int

    q: int # 商
    r: int # 余り
    q, r = divmod(item_count, 100)
    if r > 0:
        page_count = q + 1
    else:
        page_count = q

    return page_count
```

短くする例

```python
def get_page_count(item_count: int) -> int:
    q, r = divmod(item_count, 100)
    return q + int(r > 0)
```

### n ページになる場合の在庫件数で考えられるのは？

この方法は個人的にちょっとトリッキーな気がします。難しいです。

以下の例を考えます。

- 全部で 1 ページになる場合の在庫で考えられるのは？
- 全部で 2 ページになる場合の在庫で考えられるのは？
- 全部で 3 ページになる場合の在庫で考えられるのは？

順に「1 から 100」「101 から 200」「201 から 300」です。

この時点で暗雲が立ち込めている人はどれくらいいるでしょうか？

コードにしてみましょう。まとめると

- 在庫件数が 1 から 100 件のとき 1 ページ
- 在庫件数が 101 から 200 件のとき 2 ページ
- 在庫件数が 201 から 300 件のとき 3 ページ
- ...

```python
def get_page_count(item_count: int) -> int:
    if 1 <= item_count <= 100:
        return 1
    elif 101 <= item_count <= 200:
        return 2
    elif 201 <= item_count <= 300:
        return 3
    # 以後永遠に続く
```

これはプログラマではないです。ただのコード書く人です。

#### 共通点を見つけよう

ドツボにはまってしまったので、以下のようにアプローチします。

> 例えば「在庫件数が 101 から 200 件のとき 2 ページ」とありますが、
> 101 から 200 までの整数にはある共通点があります。それは何でしょう？

これをパッと分かる人は算数が得意というか好きな人だと思います。

想定解としてはこちら。

**1 を引くと 100 の位が 1 となる（100 で割ると商が 1 となる。商に 1 を足せば答えである。）**

これは正直天下り的に教えることになっても仕方ないと思います。

で、コードにすると

```python
def get_page_count(item_count: int) -> int:
    # 例えば、在庫件数が 101 から 200 件のとき 2 ページ
    # 101 から 200 までの整数は、1 を引くと 100 の位がすべて 1 となる
    return (item_count - 1) // 100 + 1
```

これは半年たって見返したときに負の遺産になりかねないのでコメント記載しておきました。
エンジニアにとっては超気持ちいいんですが、算数苦手だと理解が大変なこともあります。

天の声を使ってしまったので、知識が定着しない可能性があります。私は最初に書いた「在庫件数が n 件のとき」のアプローチをおすすめします。

---

## まとめ

2 つのアプローチに共通することは「無意識でやっていたことの言語化」です。
私のつたない経験上ですが、コードを書いていてつまずく場合のほとんどはこの言語化にありました。
逆にこの言語化が得意になるとプログラミングが楽しくなりそうだということが容易に想像できるでしょう。
文系がエンジニアで活躍する理由の一つな気がします。

今回この記事を書くにあたり、一つの問題に対していろいろな解法を考えるという経験を積むことができます。
その考えにより、柔軟な発想ができる、会議でアイデアがたくさん出る、セキュリティ対策を攻撃者の視点からとらえることができるなど、様々なメリットがある気がしました。

この記事が参考になったらうれしいです。