Bashの機能だけでズンドコキヨシ

株式会社船井総研デジタルのよもぎたと申します。よろしくお願いいたします。

## ズンドコしてみる

最近、ズンドコキヨシというのを知りました。流行ったのは数年前のようなので、周回遅れもいいところですが、Bashの機能（ビルトインコマンドなど）だけでズンドコキヨシをやってみました。

```bash:zdk.sh
     1  #!/bin/bash
     2
     3  readonly z="ズン"
     4  readonly d="ドコ"
     5  readonly k="キ☆ヨ☆シ"
     6
     7  list=""
     8  c=0
     9
    10  zd(){
    11          [ $((${RANDOM} % 2)) -eq 0 ] && echo -n ${z} && return 0 || echo -n ${d} && return 1
    12  }
    13
    14  zdk(){
    15          while [ "${list}" != "dzzzz" ]
    16          do
    17                  zd; [ $? -eq 0 ] && list="z${list}" || list="d${list}"
    18                  list="${list::5}"
    19                  ((c++))
    20          done
    21          echo ${k}
    22          echo $c
    23  }
    24
    25  zdk
```

> Qiitaのプログラムに行番号を追加するうまいやり方をご存知の方いらっしゃったら、教えてください。上記は```cat -n zdk.sh```しています。

9行目まではShebangと変数の代入です。
10～12行目のzd関数で、[Bashの変数](https://www.gnu.org/software/bash/manual/bash.html#Bash-Variables)の```RANDOM```を取得して偶数奇数判定をして、偶数なら**ズン**を出力して```0```を返す、奇数なら**ドコ**を出力して1を返しています。```${RANDOM}``` は参照するたびに0から32767までのいずれかの整数を返してくれます。

そのzd関数を呼び出すのが14～23行目のzdk関数です。```list```変数が```dzzzz```になるまで15～20行目をループします。
17行目でzd関数を呼び出し、戻り値が0なら**ズン**を出力したので```list```の先頭に```z```を追加します。返り値が1なら```d```を追加します。
18行目で```list```変数を[Bashのパラメータ展開](https://www.gnu.org/software/bash/manual/bash.html#Shell-Parameter-Expansion)の```${parameter:offset:length}```を使って、先頭5文字までを切り出します。直近で**ズンズンドコズンドコ**と出力していたら```list```の値は`dzdzz`となります。パラメータ展開での切り取りがしやすかったので、逆順にしました。
19行目は何回ズンドコしたかを数えています。何回くらいズンドコしたら**キ☆ヨ☆シ**を出力できるのか気になったので、数えることにしました。

めでたく**ズンズンズンズンドコ**と出力できたら```while```ループを抜けて21行目で**キ☆ヨ☆シ**を出力します。ついでに**ズンドコ**試行回数も出力します。

実行例はこちら。
```
$ ./zdk.sh
ドコズンドコドコドコズンドコズンズンズンドコドコズンドコドコドコドコドコドコドコドコズンズンズンズンドコキ☆ヨ☆シ！
26
```
---

さて、 **「興味があるなら試してみればいいじゃない」** という悪魔の囁きに逆らえなくて、zdk.sh を100万1回ほど動かしてみました。

```bash
$ for((i=1;i<=1000001;i++)); do ./zdk.sh | tail -1; done > zdk_cnt.txt
```

もう一つのターミナル開いて ```tail -f zdk_cnt.txt``` を眺めていると、桁数は分かるけど数字は読めない位のスピードで流れていきます。意外と2桁で **キヨシ！** に到達しているしているようです。

その間に```Awk```ワンライナーでのズンドコキヨシを作成します。

```Awkワンライナー```作成中...

作成完了しました。 ```watch wc -l zdk_cnt.txt``` で進捗見ているのですが、Bash版ズンドコキヨシスクリプトは45万回くらい実行されたようです。まだ半分です。いったんこの記事を下書き保存して、```Awk```版の記事の作成にかかりたいと思います。

```Awkワンライナー```記事作成中...

記事作成しました。ズンドコ試行の進捗は75万回程度です。待ちきれません。この記事はひとまず公開して、後から集計を追記するようにしたいと思います。

---

## ズンドコ集計してみる（2022/09/29追記）

100万1回ズンドコ完了しました。昨日の始業の前には終わっていたようですが、**ズンドコ集計を業務というのは無理がある**ので終業後夕食後に作業しました。**昨日の執務中はズンドコが頭から離れませんでした**。大した集計はしていないので、せめて昼休みにやっつけてしまえばよかったな、と反省しています。夜中の変なノリとテンションで書いた文章なので、翌朝見直してから公開しています。

まず、100万1回ズンドコさせます。100万1回なのは、お気づきでしょうが中央値を見るためです。
```bash
$ for((i=1;i<=1000001;i++)); do ./zdk.sh | tail -1; done > zdk_cnt.txt
$ wc -l zdk_cnt.txt
1000001 zdk_cnt.txt
```

まずは結果をソートとカウントします。

```bash
$ sort -n zdk_cnt.txt > zdk_cnt_sorted.txt
$ uniq -c zdk_cnt_sorted.txt > zdk_cnt_sorted_count.txt
$ sort -rn zdk_cnt_sorted_count.txt > zdk_cnt_sorted_count_sort.txt
$ wc -l zdk_cnt*
    300 zdk_cnt_sorted_count_sort.txt
    300 zdk_cnt_sorted_count.txt
1000001 zdk_cnt_sorted.txt
1000001 zdk_cnt.txt
```

カウントしたファイルの先頭20行をみると、約3万1千回、割合で3.1%、最短でキヨシ！していたことが分かります。

```bash
$ head  -20 zdk_cnt_sorted_count.txt
  31118 5
  31289 6
  31158 7
  31430 8
  30991 9
  30167 10
  29274 11
  28341 12
  27287 13
  26157 14
  25403 15
  24165 16
  23471 17
  22739 18
  21611 19
  20908 20
  20701 21
  20001 22
  18578 23
  18170 24
```

同ファイルのお尻の方もみてみます。最悪のパターンでは393回もズンドコしていました。**ターミナルがズンドコで埋め尽くされたら発狂してしまいます**。リダイレクトしていてよかったです。

```bash
$ tail -n 20 zdk_cnt_sorted_count.txt
      2 290
      5 291
      1 292
      2 298
      1 299
      1 300
      2 301
      1 304
      2 305
      1 309
      1 314
      1 318
      1 320
      2 321
      1 322
      2 325
      1 341
      1 351
      1 356
      1 393
```

中央値を見てみます。なんと2の5乗の32を大幅に下回ってきました。

```bash
$ cat -n zdk_cnt_sorted.txt | sed -n '499999,500001p'
499999  24
500000  24
500001  24
```

最頻値をみてみます。これはびっくりで、わずか8回でキヨシ！しているケースが最多でした。最短の5から9までで上位を独占しているのも驚きです。

```bash
$ head -20 zdk_cnt_sorted_count_sort.txt
  31430 8
  31289 6
  31158 7
  31118 5
  30991 9
  30167 10
  29274 11
  28341 12
  27287 13
  26157 14
  25403 15
  24165 16
  23471 17
  22739 18
  21611 19
  20908 20
  20701 21
  20001 22
  18578 23
  18170 24
```

2の5乗の32近辺はどれくらいの順位か？みてみました。

```bash
$ cat -n zdk_cnt_sorted_count_sort.txt | awk '$3 ~ /^3[0-4]$/'
    26    14462 30
    27    14197 31
    28    13685 32
    29    13121 33
    30    12637 34
```

さて、気になる平均何回のズンドコでキヨシ！しているか？集計しました。数が大きくなりそうだったので、Excelに計算してもらいました

![20220928_zundoko_shukei.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2822136/ddd2a9de-b404-9499-1f97-805be1eb8b4c.png)


ズバリ、平均32.08719991回のズンドコでキヨシ！してました。乱数ちゃんと乱数してるんですね。

> 303行目はExcelのFORMULATEXT関数でひとつ上のセルの数式を表示させてます。

**しばらく、いや、少なくとも10年は、ズンドコは見たくありません。**

最後までお付き合いいただきありがとうございました。



---

# 参考にした記事
* [ズンドコキヨシ on LISP](https://qiita.com/hisawotakase/items/2e7c2a1a3e4dcb518f85)
* [ズンドコキヨシまとめ](https://qiita.com/shunsugai@github/items/971a15461de29563bf90)
* [Qiitaの「ズンドコキヨシ」タグ](https://qiita.com/tags/%e3%82%ba%e3%83%b3%e3%83%89%e3%82%b3%e3%82%ad%e3%83%a8%e3%82%b7)
* [Bash Reference Manual](https://www.gnu.org/software/bash/manual/bash.html)

最後までお付き合いいただきありがとうございました。