はじめに
概要
@pikさんの公開された記事[Delphi][小ネタ]しかのこのこのここしたんたんのJellyfish版です。
なぜJellyfish?
お題が「配列で与えられた"しかのこたん"を元に」という趣旨であることから、メインの言語であるBrainf**k等ではなかなか合わないところから、文字列の加工・結合という意味でノリが合いそうな手持ちの言語として選んだのがJellyfishだったためです。
Jellyfishってなに?
Zennの記事Jellyfish(esolang)の紹介をご参照ください。
また、今回の構成はFizzBuzzの時の組み方を参考にしたものなので、Jellyfish版FizzBuzzもご覧になることをお勧めします。
コード解説その1
実装したコード
P
v,,,,,,S
Ev XvS
2v S
$ 0 ^S4
E ^ "しかのこたん
10 3#4
この通り、73B(UTF-8前提)のコードを実装しました。
tioでの実行例でオンライン実行を試すこともできます。
アイデア
まずは、FizzBuzzのようにv
,$
を組み合わせることで10要素の文字列配列 (今回は全て同じ文字列) を作成し、それを P
でまとめて出力することで目的の出力を得られると思いつきました。
ただ、今回文字列は"しかのこたん"から作っていきますから、これを要素に分解しておいて、,
により連結処理を行うコードに仕上げる必要があります。単純に分解した感じは次の通りです。( 同じ要素で済むところは使い回します )
こうしてみると、"しかのこ"というパーツは、そのままでも使えるし、"のこ"や"こ"、"し"と言った更に短い要素を作る元としても使えます。そこで、(文字列に対して)先頭数文字の削除に相当するv
や、先頭数文字の抽出に相当する^
を組み合わせて、次のようにまとめます。
ここまでくれば、お題の"しかのこたん"から、"しかのこ"と"たん"を、やはりv
や^
で切り出して適用すれば目的のコードになります。こうしてできた概形が次の図です。
実際のコードは、先ほどの構成から配置を最適化したり、矢印の曲がるところをE
,S
,X
で調整しています。
※また、最下段の 1 が隣の3,4とダンゴになるのを防ぐため、敢えて#
で 1 を作り出すように替えています。
コード解説その2
実装したコード
P
^R
$@"しかのこたん
bd",W_&`f
+6'F
4
ということで、よくよく考えたら、44B(UTF-8前提)のコード実装が可能でした。
tioでの実行例でオンライン実行を試すこともできます。
…記事のリリース直前に気付いてしまって、その1はなんだったんだという気もしていますが、まあ、そんなものです。
解説
実はJellyfishは、データ配列とインデクス配列の2引数に対する@
に対する間接参照が可能です。これは、データ配列ではなく文字列が対象でも可能で、なので 5,4,5,4,0,3,3,2,3,2,3,2,1,0 というインデクス配列を作って "しかのこたん" に間接参照すると、目的の文字列の逆順の"んたんたしここのこのこのかし"ができます。敢えて逆順にしているのは、インデクス配列の先頭を 0 にしたくないからです。
あとは、R
で逆順にして ^
,$
を組み合わせると同じ文字列10要素の配列にすることができます。これはその1の実装とv
を使ってないだけでほぼ同じです。
最後に問題のインデクス配列ですが、これは76072448022という数値をb
で6進数解釈してあげることで作ることができます。この数値をリテラルで書いても良いのですが、N進数変換のd
を使って"F"進数 (実際は70進数) 相当の文字列から変換してあげた方が少し短いです。
※もっといい方法もあるかも知れませんが、そこまでは精査しきれていません。
コード解説その3(2024/8/27追記)
実装したコード
\A'
P
@"しかのこたん
-bd"LtQS6
#6'}
なんか急にJellyfishの解像度が上がって、41B(UTF-8前提)のコードが実装できました。
tioでの実行例でオンライン実行を試すこともできます。
解説
実は、\
演算子を使うと「n回繰り返し」が実装できることが判明しました。
※そんなことも分かってなかったの? と思われるかも知れませんが、Jellyfishの演算子周りはなかなか利用するだけでも困難で、部分的にしか機能を把握していないのです…
\A10
P
"あいうえお
この例のように、\
演算子に P
関数と10という値の2入力を与えると「10回P
を実行する」という関数が合成されます。なので「あいうえお」で与えた文字列の出力が10回行われるということです。
41B短縮版では、数値の10の代わりに行末の '
で改行コード(ASCII 10)を与え、P
の下の領域で作った「しかのこのこのここしたんたん」を10回出力するコードを実装しています。
なお、制御文字としてのA
も地味に重要ですが、ここで説明するにはちょっと大変なので詳細は割愛します。簡単には、演算子の入力としての10はブロックしないが、合成関数への引数としての10の入力はブロックするという、B
の機能限定版になっています。
さて、その文字列の生成はその1やその2と同様、@
関数による間接参照で行っていますが、負のインデクスを活用することでちょっと効率化しています。
18782526054という数値をd
で作り、それをb
で6進数展開してから各要素1を引いて 0,1,2,3,2,3,2,3,3,0,4,-1,4,-1 という負数を含むインデクス配列にしています。
※「1引く」ことで、6進数展開時は先頭が非0でよくなる点が大きいです
おわりに
2次元にコードを詰めていく感覚はJellyfishの醍醐味なので、久しぶりに書いてみました。できた! と思ったら「もっと自明に短いのあるやん」と気付くのもあるあるではないかと思います。皆さんも機会があれば、一度体験してみてはいかがでしょうか。