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する。
-
命令実行回数だけ、
- ポインタの座標にある emoji を実行。emoji がない場合、異常終了する。
- 正常終了状態なら正常終了する。
-
正常終了するまでの時間 <= 0 なら、正常終了する。
-
正常終了するまでの時間をデクリメントする。
-
移動ルールにそってポインタを移動する。
「命令実行回数のスタック」がある。 最初、空のスタックである。 「命令実行回数のスタック」が空ではない時、「命令実行回数のスタック」から数値として 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 する仕様が変わる。
通常モードは、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 は codeUnit による スタック として表現される。
例えば、0️⃣ の codeUnit は [48, 65039, 8419] であり、
プログラム上では、 [8419, 65039, 48] という逆順のstackで表現される。
https://jsprimer.net/basic/string-unicode/
mode: o となっている場合、「pop」として表現される箇所は、popモードによって取り出し方が変更される。
| emoji | name | mode | action | example |
|---|---|---|---|---|
| ℹ️ | input-number | x | 入力を数値として受け取り、 pushする。空白などの直前まで受け取る。 | stack [53, 2] -> [32, 53, 2] input: 32 54 AA -> 54 AA |
| 🔤 | input-ascii | x | 入力を ASCII CODE として受け取り、 pushする。 | stack [53, 2] -> [41, 53, 2] input: ABC -> BC |
| 🔢 | output-number | o | a を pop し、数値として出力する。 |
stack [32, 53, 2] -> [53, 2] output: 32 |
| 🔡 | output-ascii | o | a を pop し、ASCII CODEとして出力する。 |
stack [41, 53, 2] -> [53, 2] output: A |
| 🔣 | output-emoji | x | a を スタックとして pop し、stackのtopを emoji として出力する。 |
stack [[8419, 65039, 48], 53, 2] -> [53, 2] output: 0️⃣ |
| 🎦 | rewind-input | x | 入力を、最初の状態に戻す。 | |
| 🐱 | cat | x | 最初の入力をそのままoutputする。 | input:ABC output:ABC |
| 🐶 | dog | x | 最初の入力を反転してoutputする。 | input:ABC output:CBA |
| 📜 | quine | x | プログラムをそのままoutputする。 | |
| 🤐 | silent | x | 以降の出力命令を無視する。 | |
| 🤮 | vomit | x | 出力命令を無視をやめる。 |
| emoji | name | mode | action | example |
|---|---|---|---|---|
| 👀 | pick-emoji | x | (x + dx, y + dy) の emoji を push する。命令実行回数 stack に 0 を push する。 |
|
| 🤳 | pick-back-emoji | x | (x - dx, y - dy) の emoji を push する。 |
| emoji | name | mode | action | example |
|---|---|---|---|---|
| 🏁 | entry-point | x | この地点をポインタの初期地点とする。複数ある場合、ランダムで選ばれる。通常時は何もしない。 | |
| ⬜️ | empty | x | 何もしない。 | |
| ⬛️ | wall | x | 壁。emoji がない場合とみなす。 | |
| 🔚 | end | x | プログラムを正常終了する。 | |
| 🚥 | signal | x | 正常終了するまでの時間 = 3 とする(すなわち、ふつう 3命令後に正常終了する)。 | |
| ⏲️ | timer | x | a を 数値として pop し、正常終了するまでの時間 = a とする。 |
|
| 🏪 | change-ignore-end | x | 正常終了無視状態を切り替える。正常終了無視状態のとき、正常終了する時、それを無視する。 | |
| 🍚 | comment | x | 次の comment まで、壁以外の命令を無視する。 | |
| 💥 | crash | x | プログラムをクラッシュする。 | |
| 🚲 | bicycle | x | 自転車に乗っていないとき: 自転車に乗る。他の乗り物からは降りる。 乗ってるとき: 降りる。 | |
| 🚳 | bicycle-stop | x | 自転車に乗っているとき、壁とみなされる。それ以外の場合、何もしない。 |
| emoji | name | mode | action | example |
|---|---|---|---|---|
| 0️⃣ | 0 | x | 0 を push する。 | stack [53, 2] -> [0, 53, 2] |
| 1️⃣ | 1 | x | 1 を push する。 | |
| 2️⃣ | 2 | x | 2 を push する。 | |
| 3️⃣ | 3 | x | 3 を push する。 | |
| 4️⃣ | 4 | x | 4 を push する。 | |
| 5️⃣ | 5 | x | 5 を push する。 | |
| 6️⃣ | 6 | x | 6 を push する。 | |
| 7️⃣ | 7 | x | 7 を push する。 | |
| 8️⃣ | 8 | x | 8 を push する。 | |
| 9️⃣ | 9 | x | 9 を push する。 | |
| 🔟 | 10 | x | 10 を push する。 | |
| A | x | 65 を push する。 | ||
| B | x | 66 を push する。 | ||
| ©️ | C | x | 67 を push する。 | |
| O | x | 77 を push する。 | ||
| M | x | 79 を push する。 | ||
| P | x | 80 を push する。 | ||
| ®️ | R | x | 82 を push する。 | |
| 💯 | 100 | x | 100 を push する。 | |
| ➰ | infinity | x | Infinity を push する。 |
備考: infinity に対応する emoji は、変更となる可能性がある。(codegolf中のみなさまへ: 期間中は変更しません)
x ~ y は、x 以上 y 以下を指す。
| emoji | name | mode | action | example |
|---|---|---|---|---|
| 🎲 | dice | x | 1 ~ 6 のランダムな値をpushする。 | |
| 🤞 | judgement | x | 0 ~ 1 のランダムな値をpushする。 |
| emoji | name | mode | action | example |
|---|---|---|---|---|
| ➕ | plus | o | (top)a, b を pop し、a+b を push する。 |
stack [7, 4, 6] -> [11, 6] |
| ➖ | minus | o | (top)a, b を pop し、a-b を push する。 |
stack [7, 4, 6] -> [3, 6] |
| ✖️ | mul | o | (top)a, b を pop し、a*b を push する。 |
stack [7, 4, 6] -> [28, 6] |
| ➗ | div | o | (top)a, b を pop し、a/b を push する。 |
stack [7, 4, 6] -> [1, 6] |
| 🈹 | mod | o | (top)a, b を pop し、a%b を push する。 |
stack [7, 4, 6] -> [3, 6] |
| 🛸 | spaceship-operator | o | (top)a, b を pop し、sign(a-b) を push する。 |
stack [7, 4, 6] -> [1, 6] |
| ❗️ | fact | o | a を pop し、a の階乗 を push する。 |
stack [7, 4, 6] -> [5040, 4, 6] |
| semifact | o | a を pop し、a の半階乗 を push する。 |
stack [7, 4, 6] -> [105, 4, 6] |
|
| 👍 | increment | o | a を pop し、a + 1 を push する。 |
stack [7, 4, 6] -> [8, 4, 6] |
| 👎 | decrement | o | a を pop し、a - 1 を push する。 |
stack [7, 4, 6] -> [8, 4, 6] |
| emoji | name | mode | action | example |
|---|---|---|---|---|
| 🚮 | pop | o | a を popする。値は ゴミ箱stack に pushする。 |
stack [7, 4, 6] -> [4, 6] |
| 🗑️ | pick-up-trash | o | ゴミ箱stack から a を popし、操作中の stack に pushする。ゴミ箱stack を clear する。 |
|
| 💕 | dup | o | a を pop し、a, a を push する。 |
stack [7, 4, 6] -> [7, 7, 4, 6] |
| 💞 | swap | o | (top)a, b を pop し、(top)b, a を push する。 |
stack [7, 4, 6] -> [4, 7, 6] |
| ♻️ | swap3 | o | (top)a, b, c を pop し、(top)c, a, b を push する。 |
stack [7, 4, 6] -> [6, 7, 4] |
| 🏗 | swapN | o | x を 数値として pop する。 x - 1 回 pop し、 c を pop し、 x - 1 回 push し、 c, を push する。 |
stack [3, 7, 4, 6] -> [6, 7, 4] |
| 📐 | length | x | stackの長さを push する。 | stack [7, [4, 3], 6] -> [3, 7, [4, 3], 6] |
| 🙃 | reverse | x | stackを反転する。 | stack [7, 4, 6] -> [6, 4, 7] |
| 🎆 | fireworks | x | stack を clear する | stack [18, 4, 26] -> [] |
| 🔞 | R-18 | x | stack から、 18未満の数を取り除く | stack [18, 4, 26] -> [18, 26] |
| 📧 | create-empty-stack | x | 空の stack を作り、pushする。 | |
| 💌 | create-new-stack | o | a を 数値として pop し、 a 回 pop する。空の stack を作り、空の stack に対し、a 回 pop したものを 逆順に push する(すなわち元通りの順番のstackができる)。 この stack を push する。 |
|
| 📨 | change-popmode | x | popモード の 通常モード と スタックモード を切り替える。 |
| emoji | name | mode | action | example |
|---|---|---|---|---|
| 📬 | into-nested-stack | x | 操作中の stack の top を、操作中の stack とする。 top が数値だった場合、1要素の stack に変換してから行う。 | |
| 📫 | exit-nested-stack | x | 現在操作中の stack の親を、現在操作中の stack とする。 親 stack がない場合は、この stack のみを要素とする 新たな stack を作成し、それを親 stack とする。 root stack は、この新たな stack に変更される。 | |
| 📪 | goto-root-stack | x | root stack を、操作中の stack とする。 | |
| 📭 | open-stack | x | a を スタックとして pop し、 stack だった場合、開いて push する。数値の場合、そのままpushする。 |
| emoji | name | mode | action | example |
|---|---|---|---|---|
| 📥 | mailbox-in | o | a を pop し、stackとは異なるstack(mailbox)にpushする。 |
|
| 📤 | mailbox-out | o | mailbox から a を pop し、stackにpushする。 |
| emoji | name | mode | action | example |
|---|---|---|---|---|
| ➡️ | right | x | (dx, dy) = (1, 0) |
|
| ⬅️ | left | x | (dx, dy) = (-1, 0) |
|
| ⬆️ | up | x | (dx, dy) = (0, -1) |
|
| ⬇️ | down | x | (dx, dy) = (0, 1) |
|
| up-right | x | (dx, dy) = (1, -1) |
||
| down-right | x | (dx, dy) = (1, 1) |
||
| up-left | x | (dx, dy) = (-1, -1) |
||
| down-left | x | (dx, dy) = (-1, 1) |
||
| ⏩ | fast-right | x | dx++ |
|
| ⏪ | fast-left | x | dx-- |
|
| ⏫ | fast-up | x | dy-- |
|
| ⏬ | fast-down | x | dy++ |
|
| 🔃 | turn-clockwise | x | (dx, dy) = (-dy, dx) |
|
| 🔄 | turn-counterclockwise | x | (dx, dy) = (dy, -dx) |
|
| 🕸️ | spider | x | (dx, dy) = (sign(dx), sign(dy)) |
|
| 🔀 | change-rotate | x | 回転方向を(時計回り/反時計回り)に変更する。 | |
| ✴️ | warp | x | (top)a, b を 数値として pop し、 (x, y) = (a, b) |
| emoji | name | mode | action | example |
|---|---|---|---|---|
| ↪️ | right-if-true | x | a を 数値として pop し、a > 0 なら right |
|
| ↩️ | left-if-true | x | a を 数値として pop し、a > 0 なら left |
|
| up-if-true | x | a を 数値として pop し、a > 0 なら up |
||
| down-if-true | x | a を 数値として pop し、a > 0 なら down |
||
| 📏 | equal-to | o | (top)a, b を pop し、 a == b ? 1 : 0 を push |
stack [7, 4, 6] -> [0, 6] |
| 📈 | greater-than | o | (top)a, b を pop し、 a > b ? 1 : 0 を push |
stack [7, 4, 6] -> [1, 6] |
| 📉 | less-than | o | (top)a, b を pop し、 a < b ? 1 : 0 を push |
stack [7, 4, 6] -> [0, 6] |
| ❕ | not | o | a を pop し、a > 0 ? 0 : 1 を push する。 |
stack [7, 4, 6] -> [3, 6] |
| 🉑 | fair | o | a を pop し、 60 <= a < 80 ? 1 : 0 を push |
stack [7, 4, 6] -> [0, 4, 6] |
| 🈴 | passed | o | a を pop し、 60 <= a ? 1 : 0 を push |
stack [7, 4, 6] -> [0, 4, 6] |
| emoji | name | mode | action | example |
|---|---|---|---|---|
| 🏃♀️ | speedrun | x | 命令実行回数stackに 2 をpushする(すなわち、次の命令を2回行う。)。 |
|
| 🎰 | slot | x | (top)a, b, c を 数値として pop し、a == b == cなら、命令実行回数stackに 7,7,7 をpushする。 |
|
| 💤 | sleep | x | 命令実行回数stackに 0,0,0 をpushする。 |
|
| 🕰 | time-manipulation | o | 操作中の stack から a を pop し、命令実行回数stackに a を push する。 |
|
| ➿ | infinity-loop | x | 命令実行回数stackに Infinity をpushする。 |
| emoji | name | mode | action | example |
|---|---|---|---|---|
| 🎥 | record | x | 録画中でないとき: 録画中とする。(録画stack に実行したemojiをpushする。)録画中の時: 録画を停止する。録画stack を逆順にする。(録画した順番通りに再生するため。) | |
| 📽️ | play-record | x | 録画stack がemptyになるまで、録画stack から スタックして pop し、emoji を実行する。 |
| emoji | name | mode | action | example |
|---|---|---|---|---|
| 💻 | exec | x | a を スタックとして pop し、対応する emoji を 実行する。 |
|
| ⏱️ | stopwatch | x | OFFのとき: ONにする。 ONのとき: ONにしてからのステップ数をpushしてOFFにする。 | |
| 🥇 | gold | x | stackを開いた際の最大値を取得し、pushする。 | stack [7, 4, 6, 2] -> [7, 7, 4, 6, 2] |
| 🥈 | silver | x | stackを開いた際の2番目に大きい値を取得し、pushする。 | stack [7, 4, 6, 2] -> [6, 7, 4, 6, 2] |
| 🥉 | bronze | x | stackを開いた際の3番目に大きい値を取得し、pushする。 | stack [7, 4, 4, 2] -> [4, 7, 4, 4, 2] |
| 🀄 | median | x | stackを開いた際の中央値を取得し、pushする。 | stack [7, 4, 6, 2] -> [5, 7, 4, 6, 2] |
| 📅 | calendar | x | 日付をpushする | stack [7, 4, 6] -> [2021, 2, 28, 11, 20, 43, 7, 4, 6] |
| 🤖 | kazoeage-oneesan | x | a を 数値として pop し、 a * a のグリッド上の左上から右下に行く時、同じところを2度通らない道順の数を頑張って数える。 |
stack [8, 4, 6] ->(4 hours later)->[3266598486981642, 4, 6] |