HTMLで最も短い湯婆婆(記事内で試せます)

# はじめに
@Nemesis さんの [Javaで湯婆婆を実装してみる](https://qiita.com/Nemesis/items/c7192a7c510788d2cba2)と@belq さんの[Perlのワンライナーで湯婆婆を実装してみる](https://qiita.com/belq/items/6320124c3d18091dc4e0)のリスペクト記事です。
上記のPerlはワンライナーの湯婆婆ですがhtmlで頑張った所、もっと短くなりました。
***追記***
短縮点が発見されたので2020/11/17にコードと記事を書き換えました。191文字から**34文字**短縮され**157文字**になりました。短縮のヒントを与えてくださった @ksk1015 さんにはこの場を借りて感謝致します。

```html
<!doctype html>契約書だよ。そこに名前を書きな。<input onchange='outerHTML=`フン。${n=value}というのかい。贅沢な名だねぇ。今からお前の名前は${m=n[new Date%n.length]}だ。いいかい、${m}だよ。分かったら返事をするんだ、${m}!!`'>
```

<font color=red>**多分これが一番短いと思います**</font>

# 契約書だよ。そこに名前を書きな。
<p class="codepen" data-height="200" data-theme-id="light" data-default-tab="result" data-user="td12734" data-slug-hash="RwRdZOW" style="height: 200px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="湯婆婆new">
  <span>See the Pen <a href="https://codepen.io/td12734/pen/RwRdZOW">
  湯婆婆new</a> by T.D (<a href="https://codepen.io/td12734">@td12734</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

上のCodePenから記事内でも湯婆婆を試せます。
文字を入力した後にEnterを押すなどすれば続きの台詞が表示されます。
※コピー用：荻野千尋

# 解説
## 要件について
湯婆婆の要件は千と千尋の神隠しを見ても分からなかったのでこちらで勝手に決めました。

- 名前を外部から入力可能
- 入力された名前からランダムに1文字抜き出した新たな名前を作成する
 - このときに使用する乱数は完全乱数でなくても良い
 - 例外処理の実装は不要
- 最終的に `契約書だよ。そこに名前を書きな。フン。(名前)というのかい。贅沢な名だねぇ。今からお前の名前は(新しい名前)だ。いいかい、(新しい名前)だよ。分かったら返事をするんだ、(新しい名前)!!` の文字を画面に表示する。
 - 改行は任意
 - 上記の文字全てが1つの画面に表示されるべき(だと思われる)

## 使用テクニック
### タグの省略
bodyタグやpタグは閉じタグが無くても動きます。
また、bodyタグの開始タグも特定の状況を除いて省略できます。
buttonタグも後ろに何もなければタグを省略できます。

### テンプレートリテラルの使用
+で文字列結合するよりテンプレートリテラルを使う方が非常に短いです。

### 変数宣言の簡略化
varを消してグローバル変数扱いします。
また、変数の値を最初に使用するタイミングで変数に値を代入します。(`${n=value}`など)

### this省略
`${n=value}`のvalueとは`this.value`のことで、このthisはinputを指します。
thisが無くても普通に動作するので消しました。

### outerHTMLを変更
名前を入力された後にinputのouterHTML(this省略済み)を変えています。
こうすることでinputが消えて「フン。」以降の台詞が表示されます。
旧バージョンのようにpタグをわざわざ作る必要は無く、body.innerHTMLを変更するせいで上記の要件が満たせなくなることも無く、それでいて前2つどちらの手法よりも短くなります。

### 新しい名前の取得
一番工夫した所です。
普通に実装した場合は以下のようになると思います。

```js
m=n.charAt(Math.floor(Math.random()*n.length))
```

まず、charAtはリストの要素の取得時のように `[number]` で代用可能です。
次に乱数ですが、 `new Date()` 、最後のカッコは省略可能なので `new Date`を人間が使う場合は乱数として使え、Math.random()より短いのでこちらを使いたいです。
その場合、new Dateは巨大な自然数ですのでnew Dateをn.lengthで割った余りは0から(n.length-1)になります。
また、Math.floorも不要になります。

よって、以下のように新しい名前を取得する処理を大幅に短縮できました。

```js
m=n.charAt(Math.floor(Math.random()*n.length)) //旧、46文字
m=n[new Date%n.length] //新、22文字
```

### getElementByIdの省略
旧版でのみ使用したテクニックです。
getElementByIdで取得したい要素のidと同じ名前の変数を定義していない場合、そのidの名前の変数に取得したい要素が代入されているのでそれを使用します。

# 備考
## DOCTYPE宣言について
筆者の環境では**<!doctype html>**を省略しても動作しますが、省略したら動かない環境も多いと思われるので今回は消さずに書きました。

## onchangeイベントについて
動作的にonchangeが一番自然な流れで湯婆婆できると考えたのでこのイベントを使っています。
onblurイベントの方が短いのですが、名前を入力した後に入力フォーム以外の所をクリックさせるという不自然な動作をさせるべきではないと考えたので今回は使いませんでした。

# おまけ
## 2020/11/17以前のコード

```html
<!doctype html>契約書だよ。そこに名前を書きな。<input id=N><button onclick='P.innerHTML=`フン。${n=N.value}というのかい。贅沢な名だねぇ。今からお前の名前は${m=n[new Date%n.length]}だ。いいかい、${m}だよ。分かったら返事をするんだ、${m}!!`'>記</button><p id=P>
```

### 契約書だよ。そこに名前を書きな。
<p class="codepen" data-height="200" data-theme-id="light" data-default-tab="result" data-user="td12734" data-slug-hash="abZPLZd" style="height: 200px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="湯婆婆">
  <span>See the Pen <a href="https://codepen.io/td12734/pen/abZPLZd">
  湯婆婆</a> by T.D (<a href="https://codepen.io/td12734">@td12734</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

### 湯婆婆の台詞を一度に画面に表示しなくても良い場合
buttonタグの閉じタグなどを省略できるので微妙に短くなりますが新コードよりかは長いです。

追記
@vf8974 さんの指摘で更に短くなりました。

```html
<!doctype html>契約書だよ。そこに名前を書きな。<input id=N><button onclick='body.innerHTML=`フン。${n=N.value}というのかい。贅沢な名だねぇ。今からお前の名前は${m=n[new Date%n.length]}だ。いいかい、${m}だよ。分かったら返事をするんだ、${m}!!`'>記
```

#### 契約書だよ。そこに名前を書きな。
<p class="codepen" data-height="200" data-theme-id="light" data-default-tab="result" data-user="td12734" data-slug-hash="pobqLgy" style="height: 200px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="湯婆婆min">
  <span>See the Pen <a href="https://codepen.io/td12734/pen/pobqLgy">
  湯婆婆min</a> by T.D (<a href="https://codepen.io/td12734">@td12734</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

## 外部から入力できなくても良い場合

```js
n=>`フン。${n}というのかい。贅沢な名だねぇ。今からお前の名前は${m=n[new Date%n.length]}だ。いいかい、${m}だよ。分かったら返事をするんだ、${m}!!`
```

たった**94文字**です。
関数を変数に代入しても96文字で100文字切ってます。
ですが、外部から名前を入力できそうにないので今回はこちらに移動させました。
環境を構築してやればコマンドプロンプトやターミナルから引数を与えて実行できそうな気はします。

# 追記
コメントで指摘して頂きましたが、以下の記事にあるコードを詰めるとRubyで無慈悲に最短記録が更新されるそうです。(悲しみ)
[Rubyで湯婆婆を実装してみる](https://qiita.com/takaram/items/31643adbe69940f77c7b)

まだ記事にはなっていないので、
~~<font color=red>**記事になっている湯婆婆では多分これが一番短いと思います**</font>~~

## 更に追記
置き無慈悲されてました。
[Jで湯婆婆を実装してみる](https://qiita.com/unsigned-wrong-wrong-int/items/8e7754049b18a0481ba7)

投稿後にも無慈悲されました。
[PHPで湯婆婆を短く書く](https://qiita.com/myr/items/d0f597588b0b12e470d1)

jsよりも短く書ける言語って結構存在するものですね。