Home

Awesome

emojifunge

これは何

befunge + emoji

ありそうでなかったので作った

動かしたい

npm i
npm run dev:test

\code 以下の、code をコード、input を入力として動く

基本

emojiを二次元上に配置する言語。 コードは、emoji と 改行 のみ有効(それ以外の文字は未定義動作)。

(x, y) = (0, 0) を指すポインタがある。ポインタがコード上を動き、ポインタの箇所のemojiを実行する。 (x, y) と書いた時はポインタの座標を表すこととし、x列y行目を指している。

スタックベースの言語。 空のスタックは (top)[](bottom) のように表現され、topからpop、pushをする。 要素として「数値」「スタック」の2種類を取る。数値は整数値である。 2[1, 3]の順に空のスタックにpushした場合、[[1, 3], 2]となる。

空の stack から pop するとき、 -1 を返す。

最初、空のスタックが1つ用意されている。これを「操作中のスタック」という。 特に注意書きがない場合、操作中のスタックからのpop、pushを指す。操作中のスタックを指すスタックは、命令によって変更されることもある。

また、このスタックを「ルートスタック」という。操作中のスタックの親をたどり、親のないスタックがあればルートスタックである。ルートスタックを指すスタックは、命令によって変更されることもある。

初期状態では、「回転方向」は時計回りである。 ポインタが壁にぶつかった際、どちら向きに回転するかは、「回転方向」によって定まる。

ステップ

命令実行回数のスタック

「命令実行回数のスタック」がある。 最初、空のスタックである。 「命令実行回数のスタック」が空ではない時、「命令実行回数のスタック」から数値として pop して、その回数次の命令を行う。

移動に関する仕様

ポインタは、最初は (x, y) = (0, 0) に位置し、 移動方向は(dx, dy) = (1, 0) とする。

移動は、ふつう (x, y) = (x + dx, y + dy)とする操作を指す。 移動先に emoji がある場合、移動する。 emoji が壁の場合は、emoji がない場合とみなす。

emojiがなければ、回転方向に応じて、 時計回りでは (dx, dy) = (-dy, dx) として、 反時計回りでは (dx, dy) = (dy, -dx) とし試す。

4回試してemojiがなければ、正常終了する。 この正常終了は、正常終了無視状態であっても終了する。

popモード

「popモード」がある。 最初「通常モード」である。 「通常モード」と「スタックモード」がある。

モードが変わると、操作中のスタックから pop する仕様が変わる。

通常モードは、stack を開いてから pop する。 これを「数値として pop」と表現する。 (top)[[a, b, c], [], [d, e], f, [g, h]] のようなスタックがあったとき、 1度目の pop では、[a, b, c] が top にあるので、 開いて (top)[a, b, c, [], [d, e], f, [g, h]]となる。 改めて、a, b, c, ... と pop する。

スタックモードは、stack でも 数値 でも 構わず pop する。 これを「スタックとして pop」と表現する。 (top)[[a, b, c], [], [d, e], f, [g, h]] のようなスタックがあったとき、 [a, b, c], [], [d, e], [f], ... のように pop していく。

演算について

n個の要素の演算を行うとき、

すべての要素が 数値 である場合は、 指定された演算を行い、結果を返す、

それ以外の場合は、数値を要素数1のスタックとみなし、 すべてのスタックの 0番目、1番目、2番目、...、min(スタックの要素数) - 1 番目 に対してそれぞれ再帰的に処理をし、0番目の結果、 1番目の結果、... を保持した スタックを返す。 min(スタックの要素数) - 1 番目 より 後の要素は破棄される。

すなわち、 (top)[[7, 4, 6], 3, 6] の stack に対し、➕ を適用すると、[7, 4, 6][3] の演算となり、0番目の要素同士で計算したのち、1番目以降を破棄して [10] を得るので、(top)[[10], 6] という stack が得られる。

emoji と stack

emoji は codeUnit による スタック として表現される。

例えば、0️⃣ の codeUnit は [48, 65039, 8419] であり、 プログラム上では、 [8419, 65039, 48] という逆順のstackで表現される。

https://jsprimer.net/basic/string-unicode/

コマンド一覧

mode: o となっている場合、「pop」として表現される箇所は、popモードによって取り出し方が変更される。

入出力

emojinamemodeactionexample
ℹ️input-numberx入力を数値として受け取り、 pushする。空白などの直前まで受け取る。stack [53, 2] -> [32, 53, 2] input: 32 54 AA -> 54 AA
🔤input-asciix入力を ASCII CODE として受け取り、 pushする。stack [53, 2] -> [41, 53, 2] input: ABC -> BC
🔢output-numberoa を pop し、数値として出力する。stack [32, 53, 2] -> [53, 2] output: 32
🔡output-asciioa を pop し、ASCII CODEとして出力する。stack [41, 53, 2] -> [53, 2] output: A
🔣output-emojixa を スタックとして pop し、stackのtopを emoji として出力する。stack [[8419, 65039, 48], 53, 2] -> [53, 2] output: 0️⃣
🎦rewind-inputx入力を、最初の状態に戻す。
🐱catx最初の入力をそのままoutputする。input:ABC output:ABC
🐶dogx最初の入力を反転してoutputする。input:ABC output:CBA
📜quinexプログラムをそのままoutputする。
🤐silentx以降の出力命令を無視する。
🤮vomitx出力命令を無視をやめる。

盤面のemoji

emojinamemodeactionexample
👀pick-emojix(x + dx, y + dy) の emoji を push する。命令実行回数 stack に 0 を push する。
🤳pick-back-emojix(x - dx, y - dy) の emoji を push する。

制御

emojinamemodeactionexample
🏁entry-pointxこの地点をポインタの初期地点とする。複数ある場合、ランダムで選ばれる。通常時は何もしない。
⬜️emptyx何もしない。
⬛️wallx壁。emoji がない場合とみなす。
🔚endxプログラムを正常終了する。
🚥signalx正常終了するまでの時間 = 3 とする(すなわち、ふつう 3命令後に正常終了する)。
⏲️timerxa を 数値として pop し、正常終了するまでの時間 = a とする。
🏪change-ignore-endx正常終了無視状態を切り替える。正常終了無視状態のとき、正常終了する時、それを無視する。
🍚commentx次の comment まで、壁以外の命令を無視する。
💥crashxプログラムをクラッシュする。
🚲bicyclex自転車に乗っていないとき: 自転車に乗る。他の乗り物からは降りる。 乗ってるとき: 降りる。
🚳bicycle-stopx自転車に乗っているとき、壁とみなされる。それ以外の場合、何もしない。

定数

emojinamemodeactionexample
0️⃣0x0 を push する。stack [53, 2] -> [0, 53, 2]
1️⃣1x1 を push する。
2️⃣2x2 を push する。
3️⃣3x3 を push する。
4️⃣4x4 を push する。
5️⃣5x5 を push する。
6️⃣6x6 を push する。
7️⃣7x7 を push する。
8️⃣8x8 を push する。
9️⃣9x9 を push する。
🔟10x10 を push する。
🅰️Ax65 を push する。
🅱️Bx66 を push する。
©️Cx67 を push する。
🅾️Ox77 を push する。
Ⓜ️Mx79 を push する。
🅿️Px80 を push する。
®️Rx82 を push する。
💯100x100 を push する。
infinityxInfinity を push する。

備考: infinity に対応する emoji は、変更となる可能性がある。(codegolf中のみなさまへ: 期間中は変更しません)

乱数

x ~ y は、x 以上 y 以下を指す。

emojinamemodeactionexample
🎲dicex1 ~ 6 のランダムな値をpushする。
🤞judgementx0 ~ 1 のランダムな値をpushする。

計算

emojinamemodeactionexample
pluso(top)a, b を pop し、a+b を push する。stack [7, 4, 6] -> [11, 6]
minuso(top)a, b を pop し、a-b を push する。stack [7, 4, 6] -> [3, 6]
✖️mulo(top)a, b を pop し、a*b を push する。stack [7, 4, 6] -> [28, 6]
divo(top)a, b を pop し、a/b を push する。stack [7, 4, 6] -> [1, 6]
🈹modo(top)a, b を pop し、a%b を push する。stack [7, 4, 6] -> [3, 6]
🛸spaceship-operatoro(top)a, b を pop し、sign(a-b) を push する。stack [7, 4, 6] -> [1, 6]
❗️factoa を pop し、a の階乗 を push する。stack [7, 4, 6] -> [5040, 4, 6]
‼️semifactoa を pop し、a の半階乗 を push する。stack [7, 4, 6] -> [105, 4, 6]
👍incrementoa を pop し、a + 1 を push する。stack [7, 4, 6] -> [8, 4, 6]
👎decrementoa を pop し、a - 1 を push する。stack [7, 4, 6] -> [8, 4, 6]

スタック操作

emojinamemodeactionexample
🚮popoa を popする。値は ゴミ箱stack に pushする。stack [7, 4, 6] -> [4, 6]
🗑️pick-up-trashoゴミ箱stack から a を popし、操作中の stack に pushする。ゴミ箱stack を clear する。
💕dupoa を pop し、a, a を push する。stack [7, 4, 6] -> [7, 7, 4, 6]
💞swapo(top)a, b を pop し、(top)b, a を push する。stack [7, 4, 6] -> [4, 7, 6]
♻️swap3o(top)a, b, c を pop し、(top)c, a, b を push する。stack [7, 4, 6] -> [6, 7, 4]
🏗swapNox を 数値として pop する。 x - 1 回 pop し、 c を pop し、 x - 1 回 push し、 c, を push する。stack [3, 7, 4, 6] -> [6, 7, 4]
📐lengthxstackの長さを push する。stack [7, [4, 3], 6] -> [3, 7, [4, 3], 6]
🙃reversexstackを反転する。stack [7, 4, 6] -> [6, 4, 7]
🎆fireworksxstack を clear するstack [18, 4, 26] -> []
🔞R-18xstack から、 18未満の数を取り除くstack [18, 4, 26] -> [18, 26]
📧create-empty-stackx空の stack を作り、pushする。
💌create-new-stackoa を 数値として pop し、 a 回 pop する。空の stack を作り、空の stack に対し、a 回 pop したものを 逆順に push する(すなわち元通りの順番のstackができる)。 この stack を push する。
📨change-popmodexpopモード の 通常モード と スタックモード を切り替える。

ネストスタック操作

emojinamemodeactionexample
📬into-nested-stackx操作中の stack の top を、操作中の stack とする。 top が数値だった場合、1要素の stack に変換してから行う。
📫exit-nested-stackx現在操作中の stack の親を、現在操作中の stack とする。 親 stack がない場合は、この stack のみを要素とする 新たな stack を作成し、それを親 stack とする。 root stack は、この新たな stack に変更される。
📪goto-root-stackxroot stack を、操作中の stack とする。
📭open-stackxa を スタックとして pop し、 stack だった場合、開いて push する。数値の場合、そのままpushする。

記憶領域操作

emojinamemodeactionexample
📥mailbox-inoa を pop し、stackとは異なるstack(mailbox)にpushする。
📤mailbox-outomailbox から a を pop し、stackにpushする。

移動

emojinamemodeactionexample
➡️rightx(dx, dy) = (1, 0)
⬅️leftx(dx, dy) = (-1, 0)
⬆️upx(dx, dy) = (0, -1)
⬇️downx(dx, dy) = (0, 1)
↗️up-rightx(dx, dy) = (1, -1)
↘️down-rightx(dx, dy) = (1, 1)
↖️up-leftx(dx, dy) = (-1, -1)
↙️down-leftx(dx, dy) = (-1, 1)
fast-rightxdx++
fast-leftxdx--
fast-upxdy--
fast-downxdy++
🔃turn-clockwisex(dx, dy) = (-dy, dx)
🔄turn-counterclockwisex(dx, dy) = (dy, -dx)
🕸️spiderx(dx, dy) = (sign(dx), sign(dy))
🔀change-rotatex回転方向を(時計回り/反時計回り)に変更する。
✴️warpx(top)a, b を 数値として pop し、 (x, y) = (a, b)

条件分岐

emojinamemodeactionexample
↪️right-if-truexa を 数値として pop し、a > 0 なら right
↩️left-if-truexa を 数値として pop し、a > 0 なら left
⤴️up-if-truexa を 数値として pop し、a > 0 なら up
⤵️down-if-truexa を 数値として pop し、a > 0 なら down
📏equal-too(top)a, b を pop し、 a == b ? 1 : 0 を pushstack [7, 4, 6] -> [0, 6]
📈greater-thano(top)a, b を pop し、 a > b ? 1 : 0 を pushstack [7, 4, 6] -> [1, 6]
📉less-thano(top)a, b を pop し、 a < b ? 1 : 0 を pushstack [7, 4, 6] -> [0, 6]
notoa を pop し、a > 0 ? 0 : 1 を push する。stack [7, 4, 6] -> [3, 6]
🉑fairoa を pop し、 60 <= a < 80 ? 1 : 0 を pushstack [7, 4, 6] -> [0, 4, 6]
🈴passedoa を pop し、 60 <= a ? 1 : 0 を pushstack [7, 4, 6] -> [0, 4, 6]

回数操作

emojinamemodeactionexample
🏃‍♀️speedrunx命令実行回数stackに 2 をpushする(すなわち、次の命令を2回行う。)。
🎰slotx(top)a, b, c を 数値として pop し、a == b == cなら、命令実行回数stackに 7,7,7 をpushする。
💤sleepx命令実行回数stackに 0,0,0 をpushする。
🕰time-manipulationo操作中の stack から a を pop し、命令実行回数stackに a を push する。
infinity-loopx命令実行回数stackに Infinity をpushする。

録画

emojinamemodeactionexample
🎥recordx録画中でないとき: 録画中とする。(録画stack に実行したemojiをpushする。)録画中の時: 録画を停止する。録画stack を逆順にする。(録画した順番通りに再生するため。)
📽️play-recordx録画stack がemptyになるまで、録画stack から スタックして pop し、emoji を実行する。

misc

emojinamemodeactionexample
💻execxa を スタックとして pop し、対応する emoji を 実行する。
⏱️stopwatchxOFFのとき: ONにする。 ONのとき: ONにしてからのステップ数をpushしてOFFにする。
🥇goldxstackを開いた際の最大値を取得し、pushする。stack [7, 4, 6, 2] -> [7, 7, 4, 6, 2]
🥈silverxstackを開いた際の2番目に大きい値を取得し、pushする。stack [7, 4, 6, 2] -> [6, 7, 4, 6, 2]
🥉bronzexstackを開いた際の3番目に大きい値を取得し、pushする。stack [7, 4, 4, 2] -> [4, 7, 4, 4, 2]
🀄medianxstackを開いた際の中央値を取得し、pushする。stack [7, 4, 6, 2] -> [5, 7, 4, 6, 2]
📅calendarx日付をpushするstack [7, 4, 6] -> [2021, 2, 28, 11, 20, 43, 7, 4, 6]
🤖kazoeage-oneesanxa を 数値として pop し、 a * a のグリッド上の左上から右下に行く時、同じところを2度通らない道順の数を頑張って数える。stack [8, 4, 6] ->(4 hours later)->[3266598486981642, 4, 6]