はじめに
Whitespaceという言語を使って「I love Izumi(大石泉すき)」を出力しました。
この言語ではASCII文字しか扱えないため、英語での出力になります。
ちなみに大石泉とはゲーム「アイドルマスターシンデレラガールズ」に登場するプログラミングが趣味のアイドルです。
Whitespaceについて
Whitespaceとは、「スペース」「タブ」「改行」の3つの空白文字のみを使って記述を行うプログラミング言語です。
「スタック操作」「ヒープ操作」「演算」「入出力」「フロー制御」の5つの命令をこなすことができます。
IMPで上記の命令を指定し、続けてコマンドを記述することでプログラムを動かしていきます。
詳しくは下記をご参照ください。
今回の記事を書くにあたり、参考にさせていただきました。
- Whitespace 超入門
- Rubyist のための他言語探訪 【第 14 回】 Whitespace
- AtCoder に登録したら解くべき精選過去問 10 問を Whitespace で解いてみた
コード
それでは実際にコードをみてみましょう。
実際に動作を確認したい場合はリンクから飛んでください。
https://ideone.com/Cw7y3f
何も見えませんね。空白文字なので当然ですが・・・
スペースをS
、タブをT
、改行をL
に置き換えて表示してみましょう。
また、今回は分かりやすいように一命令一行の形式にした上で、処理内容ごとにブロック分けしました。
実際にはL
の位置で改行が入ります。
SSSL //スタックに0をPUSH(ループ終了フラグ)
SSSTTSTSSTL //i(105)をPUSH
SSSTTSTTSTL //m(109)をPUSH
SSSTTTSTSTL //u(117)をPUSH
SSSTTTTSTSL //z(122)をPUSH
SSSTSSTSSTL //I(73)をPUSH
SSSTSSSSSL //半角スペースをPUSH
SSSTTSSTSTL //e(101)をPUSH
SSSTTTSTTSL //v(118)をPUSH
SSSTTSTTTTL //o(111)をPUSH
SSSTTSTTSSL //l(108)をPUSH
SSSTSSSSSL //半角スペースをPUSH
SSSTSSTSSTL //I(73)をPUSH
LSSSL //ラベル0を設定(ループ始点)
SLS //スタックの一番上の値を複製
LTSTL //スタックから取り出し、値が0ならラベル1へジャンプ
TLSS //スタックから値を取り出し、値とASCIIコードに対応する文字を出力
LSLS //ラベル0へ戻る(ループ終点)
LSSTL //ラベル1を設定
SLL //スタックの一番上を削除
LLL //プログラムを終了
出力する文字をスタックに積み込んでいきます。この時、積み込む順番と出力される順番は逆になります。
その後、ループ処理を使って一つずつ出力していきます。
出力開始地点にラベル0を設定し、出力が終わるたびに、このラベルに戻ることでループを再現しています。
スタックから取り出した値が0の場合、ラベル1へジャンプしてループから抜けます。
一番最初に、スタックに0を積んでいるのはこの処理を実行させるためです。
個別解説
今回使用した処理について、個別に解説していきます。
ここで紹介するのは一部であり、これらの他にもコマンドは数多く存在します。
スタック操作
IMP | コマンド | 引数 | 内容 |
---|---|---|---|
S | S (引数) L | 数値 | スタックの一番上に値を積む |
S | L S | なし | スタック一番上にある値を複製 |
S | L L | なし | スタック一番上にある値を削除 |
数値の表現ルール
1文字目が符号、2文字目以降は2進数(S=0、T=1)で数値を表記し、最後に終わりを示すL
を記述します。
ラベルの設定時など符号を記述しない場合もありますが、SとTを使った2進数表記はどの命令でも共通です。
符号(S=正,T=負) | ||||||||
---|---|---|---|---|---|---|---|---|
S | T | T | S | T | S | S | T | L |
+ | 1 | 1 | 0 | 1 | 0 | 0 | 1 |
S S S L //スタックに0をPUSH(ループ終了フラグ)
S S STTSTSST L //i(105)をPUSH
S LS //スタックの一番上の値を複製
S LL //スタックの一番上を削除
0を積む場合は、符号まで指定して数値は記述しないようです。
数値を0で埋めたらエラーになりました。このあたりの仕様はよく分かりません。
フロー制御
IMP | コマンド | 引数 | 内容 |
---|---|---|---|
L | S S (引数) L | ラベル | 現在の位置にラベルを設定。ラベルは2進数で記述。 |
L | S L | ラベル | 指定したラベルにジャンプ。 |
L | T S | ラベル | スタックから値を取り出し、その値が0であれば指定したラベルへジャンプ。 |
L | L L | なし | プログラムをその場で終了。 |
L SS S L //ラベル0を設定(ループ始点)
L SS T L //ラベル1を設定
L SL S //ラベル0へ戻る(ループ終点)
L TS T L //スタックから取り出し、値が0ならラベル1へジャンプ
L LL //プログラムを終了
入出力
IMP | コマンド | 引数 | 内容 |
---|---|---|---|
T L | S S | なし | スタックから値を取り出し、値とASCIIコードに対応する文字を出力 |
TL SS //スタックから値を取り出し、値とASCIIコードに対応する文字を出力
取り出した値が「73」であれば「I」のようにASCIIコードに変換して出力します。
コード表はこちらを参照してください。
終わりに
空白文字のインパクトが強いものの、構文自体は単純で理解がしやすい言語でした。
Whitespace 超入門を始めとして、丁寧な解説サイトがたくさんありますので、興味のある方はチャレンジしてみてください。
次回はPietに挑戦してみようと思います。