ランダムな文字列を生成してみた

## はじめに
ランダムな文字列（今回は6文字の英小文字）を生成するプログラムをいくつかの言語で実装しました。
記事の作成者のスキルは、素人がほぼ独学でプログラミングを学んだ程度です。
記事中にコードの記述がありますが、おかしい箇所やアンチパターンなどありましたらコメントいただけると幸いです。

## 目次
1. [Herokuでアプリ名を自前にしたかった](#herokuでアプリ名を自前にしたかった)
1. [実装](#実装)
 1. [C](#1-c言語)
 2. [C++](#2-c)
 3. [Python](#3-python)
 4. [Ruby](#4-ruby)
 5. [PHP](#5-php)
 6. [Node.js](#6-nodejs)
 7. [Swift](#7-swift)
 8. [シェルスクリプト](#8-シェルスクリプト)
 9. [JavaScript(HTML埋め込み)](#9-javascripthtml埋め込み)
 10. [実装まとめ](#10-実装まとめ)
10. [結論](#結論)
11. [終わりに](#終わりに)

## Herokuでアプリ名を自前にしたかった
先日、初めてHerokuを使いました。とても使い勝手が良いのですが自動生成のアプリ名ではなんのアプリかわかりません。任意のアプリ名を付けるにはHeroku上にあるアプリ名との重複を避けなければいけないようです。
単純な方法として、命名規則を

**`ランダムな文字列-app-name (ex. fjofez-hello-app)`**

とすれば、重複する可能性を減らしつつ理解しやすい名前を付けることができます。
そこで、ランダムな文字列を生成するプログラムを複数言語で書いてみることにしました。
ちなみに、アプリ名の制限には次のようなものがあります

    $ heroku rename MyApp
    Renaming Old-App to NewyApp... !
    ▸ Name must start with a letter, end with a letter or digit and can 
      only contain lowercase letters, digits, and dashes.

`名前は、最初が文字で始まり、最後が文字または数字である必要があり、小文字、数字、ダッシュのみを含めることができます。`

さらに、文字数の上限は30文字のようです。
ランダムな文字列の生成は以下のパターンで実装しました。

**C, C++, Python, Ruby, PHP, Node.js, Swift, シェル, JavaScript(HTML埋め込み)**

時間がない人は [結論](#結論) に飛んでください。

## 実装
**実装のルール**は大まかに以下の通りです。

* コマンドラインで実行（ JavaScript(HTML埋め込み) 以外 ）
* コマンドラインで標準出力（ JavaScript(HTML埋め込み) 以外 ）
* 生成するランダムな文字列の長さは6文字で固定（ハードコーディング）
* 生成するランダムな文字列は英小文字のみ
* アプリ名が被らなければ良いので厳密なランダムでなくてOK

**実行環境**（Windows）

<table>
  <tr>
    <th>OS</th><td>Windows 10 Home (64bit) </td>
  </tr>
  <tr>
    <th>WSL</th><td>Ubuntu 18.04.4 LTS</td>
  </tr>
  <tr>
    <th>シェル</th><td>bash</td>
  </tr>
</table>

**実行環境**（Mac）

<table>
  <tr>
    <th>OS</th><td>Catalina 10.15.6 </td>
  </tr>
  <tr>
    <th>シェル</th><td>zsh</td>
  </tr>
</table>

##1. C言語
* コンパイラ　**gcc 7.5.0**

学生の頃にC言語の授業を1コマ分取ったのと、42Tokyoというエンジニアスクールの入学試験で1カ月ほど学びました。
私の中でプログラミングといえばC言語のイメージです。

```c:random_strings.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void)
{
    int num_of_char = 6;
    srand((unsigned int)time(NULL));

    for (int i = 0; i < num_of_char; i++)
        printf("%c", (rand() % 26 + 'a'));
    printf("\n");
}
```

    $ gcc random_strings.c
    $ ./a.out
    ucxjvx
    $ ./a.out
    asuprq
    $ ./a.out
    rveroj

参考
[【C言語入門】乱数(rand)の使い方](https://www.sejuku.net/blog/25352)

##2. C++
* コンパイラ　**g++ 7.5.0**

AtCoderという競技プログラミングコンテストを開催しているサービスにてコンテストに参加するためにC++を勉強しました。プログラミングを始めるとき、パズルが好きな人にとっては競技プログラミングは導入に最適だと思います。

```c++:random_strings.cpp
#include <iostream>
#include <random>
using namespace std;

int main()
{
    int num_of_char = 6;

    mt19937 mt{random_device{}()};
    uniform_int_distribution<int> dist(0, 25); // 26 letters of a~z

    for (int i = 0; i < num_of_char; i++)
        cout << char(dist(mt) + 'a');
    cout << endl;
}
```

    $ g++ random_strings.cpp
    $ ./a.out
    zotuxm
    $ ./a.out
    faoxwv
    $ ./a.out
    czoxwt

参考
[C++の乱数ライブラリが使いにくい話](https://qiita.com/_EnumHack/items/25fc998873d1bc7d2276)
##3. Python
* バージョン　**Python 2.7.17**

みんな大好きPython。ほとんど触ったことがありません。
C言語と比べると記述量が少なくなりました。参考文献が多かったです。

```python:random_strings.py
import random
import sys

for i in range(6):
    sys.stdout.write(chr(random.randrange(26) + ord("a")))
print("")
```

    $ python random_strings.py
    prnsro
    $ python random_strings.py
    nnaydv
    $ python random_strings.py
    uzejcc

参考
[Pythonでランダムな小数・整数を生成するrandom, randrange, randintなど](https://note.nkmk.me/python-random-randrange-randint/)
[【Python】データ型とキャスト](https://qiita.com/kenta1984/items/169e5dcbdbf0b4c8af27)
[Python Tips：改行なしで文字列を出力したい](https://www.lifewithpython.com/2013/12/python-print-without-.html) 
[Python Snippets](https://python.civic-apps.com/char-ord/)

##4. Ruby
* バージョン　**ruby 2.7.1**

Railsチュートリアルを取り組んでいる最中です。RailsチュートリアルでHerokuを使ったのがきっかけでこの記事を書きました。
コード量はまさかの1行。肌感ですが、実行速度は遅いような気がします。

```ruby:random_strings.rb
puts (0..5).map{ ("a".ord + rand(26)).chr }.join
```

    $ ruby random_strings.rb
    xgrqye
    $ ruby random_strings.rb
    cvijok
    $ ruby random_strings.rb
    ifmiau


**2020.9.5追記**
コメントでもう少しコードを短くする書き方を教えていただきました。
短いかつ拡張性（数字や大文字を含めるなど）があります。

```ruby:
puts (1..6).map{ [*"a".."z"].sample }.join
```


参考
[Rubyでランダムな文字列を生成する方法](https://www.xmisao.com/2014/02/15/how-to-generate-a-random-string-in-ruby.html)
[RubyでIntegerと文字を相互変換する](https://qiita.com/chezou/items/947900faef4c1032ed94)
[Array#sample (Ruby 2.7.0 リファレンスマニュアル)](https://docs.ruby-lang.org/ja/2.7.0/method/Array/i/sample.html)

##5. PHP
* バージョン　**PHP 7.2.24**

PHPをコマンドラインから実行したのはほぼ初でした。変数に$を付けるのが新鮮です。

```php:random_strings.php
<?php
    for ($i = 0; $i < 6; $i++)
        echo substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'), 0, 1);
    echo "\n"
?>
```

    $ php random_strings.php
    fclvjt
    $ php random_strings.php
    mcttjp
    $ php random_strings.php
    rdvole

**2020.9.5修正**
コメントでご指摘いただいた箇所を修正しました。
生成文字列の文字数が8文字　=> 6文字に修正
重複なし　　　　　　　　　 =>　重複ありに修正
<br><details><summary>修正前</summary><div>

---
PHPをコマンドラインから実行したのはほぼ初でした。コード量は実質1行。

```php:random_strings.php
<?php
    echo substr(str_shuffle('abcdefghijklmnopqrstuvwxyz'), 0, 8) . "\n";
?>
```

    $ php random_strings.php
    fwuxjhel
    $ php random_strings.php
    fcxmuypb
    $ php random_strings.php
    qkswgyjp

---

</div></details>

参考
[【PHPをコマンドラインで実行する方法【初心者向け】](https://techacademy.jp/magazine/19150)
[ランダムなパスワードを1行で生成する](https://qiita.com/suin/items/c958bcca90262467f2c0)

##6. Node.js
* バージョン　**v12.16.2**

初めて触りました。Node.jsというよりはJavaScriptをコマンドラインから実行するためにNode.jsを使った感があります。
JavaScript自体はWeb制作の勉強をしたときに少し触りました。

```javascript:random_strings.js
'use strict';
function make_random_string() {
    const num_of_char = 6;
    let random;
    let str1 = "";
    for (let i = 0; i < num_of_char; i++)
    {
        random = Math.floor( Math.random () * 26 + "a".charCodeAt(0));
        str1 += String.fromCharCode(random);
    }
    console.log(str1);
}
make_random_string();
```

    $ node random_strings.js
    fpysdy
    $ node random_strings.js
    hshgzk
    $ node random_strings.js
    bedysa

参考
[WSL環境におけるNode.jsの導入から利用](https://qiita.com/RoaaaA/items/17df30bf9400edfb7fb3)
[コピペで使える JavaScript逆引きリファレンス](https://javascript.programmer-reference.com/js-string-fromcharcode/)
[javascriptで乱数を取得](https://qiita.com/shosho/items/3f5fe0e18d032647f22e)
[JavaScriptで文字をASCIIコードに変換する](https://qa.codeflow.site/questions/94037/convert-character-to-ascii-code-in-javascript)


##7. Swift
* バージョン　**Apple Swift version 5.2.4**

初めて触りました。基本的にはiOSアプリを作るための言語だからか、今回の実装では一番苦戦しました。今回のような実装内容ではSwiftは向いていないように感じます。

```swift:random_strings.swift
let str = "abcdefghijklmnopqrstuvwxyz"

var i = 0
while i < 6 {
    let randomAlpha = Int.random(in: 0..<26)
    let fromIdx = str.index(str.startIndex, offsetBy: randomAlpha)
    let toIdx = str.index(str.endIndex, offsetBy: randomAlpha - 26)
    print(str[fromIdx...toIdx], terminator: "")
    i += 1
}
print("")
```

    $ swift random_strings.swift
    xwjrxd
    $ swift random_strings.swift
    pwqziz
    $ swift random_strings.swift
    psbhww

参考
[【Swift】乱数を生成する方法](https://capibara1969.com/2033/)
[Swiftで指定したindexの文字列を取得する方法](https://swift.tecc0.com/?p=136)
[繰り返し処理！Swiftで書くwhile/for文の使い方【初心者向け】](https://techacademy.jp/magazine/14546)

##8. シェルスクリプト
* バージョン　**GNU bash, version 4.4.20**

シェルスクリプトは効率化のために必要だったらその都度ググって作成し、3日後には忘れている感じの熟練度です。

```shell:random_strings.sh
#!/bin/bash
cat /dev/urandom | tr -dc 'a-z' | fold -w 6 | head -n 1
```

    $ bash random_strings.sh
    udhmsd
    $ bash random_strings.sh
    loxtxt
    $ bash random_strings.sh
    zxrbbe

参考
[ランダムな文字列を生成](https://hacknote.jp/archives/21995/)

##9. JavaScript(HTML埋め込み)
* 動作確認　下記表の通り

<table>
  <tr>
    <th>ブラウザ</th><th>バージョン</th>
  </tr>
  <tr>
    <td>Google Chrome</td><td>バージョン: 84.0.4147.135</td>
  </tr>
  <tr>
    <td>Microsoft Edge</td><td>バージョン 85.0.564.44</td>
  </tr>
  <tr>
    <td>Firefox</td><td>バージョン: 80.0.1</td>
  </tr>
  <tr>
    <td>Safari</td><td>バージョン: 13.1.2</td>
  </tr>
</table>

Node.jsで実装したコードをHTMLに埋め込んだだけです。1つのhtmlファイルにまとめるため、作法は無視しています。
とりあえず動けばOK。素人からするとブラウザがあれば実行できるJavaScriptは便利だと感じます。

```html:random_strings.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        html {background: #f7f7f7;}
        body {margin: 48px auto 0; padding-top: 12px; padding-left: 24px;}
        body {background: #fff; border: solid 1px #333; width: 640px;}
        .result {color: #F06060; font-size: 30px; font-weight: bold; margin-left: 2rem;}
        div {border-bottom: solid 2px #333; width: 300px;}
    </style>
</head>
<body>
    <h1>JavaScriptでランダムな文字列を生成する</h1>
    <div>
        <script>
            'use strict';
            function make_random_string() {
                const num_of_char = 6;
                let random;
                let str1 = "";
                for (let i = 0; i < num_of_char; i++)
                {
                    random = Math.floor( Math.random () * 26 + "a".charCodeAt(0));
                    str1 += String.fromCharCode(random);
                }
                console.log(str1);
                document.write("<span>生成文字列 => </span>");
                document.write("<span class = result>" + str1 + "</span>");
            }
            make_random_string();
        </script>
    </div>
    <p>(a ~ zから重複あり6文字)</p>
    <p>console.logにも表示されています。</p>
</body>
</html>
```
JavaScript(HTML埋め込み)をブラウザ（Microsoft Edge）で確認
![js_edge.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/600164/5edfc34a-b210-a267-586a-c57eec8cfbd8.png)

##10. 実装まとめ
Swift以外はWindows機で実行しましたが、WSLのおかけで環境を整えるのがとても簡単でした。私が学生の頃は、Windows機でC言語の開発環境を整えるのは一苦労だった記憶があります。さらに、現在はAWSのCloud 9といったようなクラウドIDEも充実しており、dockerを使えば共同開発でも開発環境を揃えるのが比較的簡単といったようにとても環境に恵まれているように感じます。

## 結論
手打ちが簡単かつ最速。(下記の例は私が適当にキーボードを叩きました)

    $ heroku rename wojwpd-hello-app

被っていたら別の名前を付ければいいのです。

他にも、接頭語に固定の単語をつけるだけでも重複することはないのではと思っています。

    $ heroku rename apple-hello-app


## 終わりに
様々な言語に触れられ、いい経験でした。
Hello Worldで物足りない人は新しい言語のとっかかりとしてでランダム文字列を生成してみてはいかがでしょうか。

以上。