LoginSignup
91
34

More than 3 years have passed since last update.

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

Last updated at Posted at 2020-11-13

はじめに

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

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

多分これが一番短いと思います

契約書だよ。そこに名前を書きな。

See the Pen 湯婆婆new by T.D (@td12734) on CodePen.

上の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つどちらの手法よりも短くなります。

新しい名前の取得

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

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も不要になります。

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

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以前のコード

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

契約書だよ。そこに名前を書きな。

See the Pen 湯婆婆 by T.D (@td12734) on CodePen.

湯婆婆の台詞を一度に画面に表示しなくても良い場合

buttonタグの閉じタグなどを省略できるので微妙に短くなりますが新コードよりかは長いです。

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

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

契約書だよ。そこに名前を書きな。

See the Pen 湯婆婆min by T.D (@td12734) on CodePen.

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

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

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

追記

コメントで指摘して頂きましたが、以下の記事にあるコードを詰めるとRubyで無慈悲に最短記録が更新されるそうです。(悲しみ)
Rubyで湯婆婆を実装してみる

まだ記事にはなっていないので、
記事になっている湯婆婆では多分これが一番短いと思います

更に追記

置き無慈悲されてました。
Jで湯婆婆を実装してみる

投稿後にも無慈悲されました。
PHPで湯婆婆を短く書く

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

91
34
19

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
91
34