言語設計:2次元パターンマッチング


49

これは、Fortnightly Challenge#6です。テーマ:言語設計

このチャレンジにはチャットルームがあります。アイデアについて議論したい場合は、ぜひご参加ください!

そして今、完全に異なるもののために...

この2週間、新しいタイプのチャレンジを試してみたいと思います。この課題では、言語を設計します!パターンマッチングはプログラミングでは非常に一般的な問題であり、コードゴルフでは非常に役立ちます。たとえば、正規表現を使用して、テキスト行のパターンを検出できます。ただし、2次元パターンを記述および検出する確立された方法はありません。

挑戦

パターンマッチング言語を設計します。これにより、テキストのブロックで2次元のパターンを記述できます。動作モード(あなたの言語がそうでなければ、正規表現と共通の何かを持っている必要はありませんが)あなたの言語のは、正規表現のようになります。

  • 入力として、テキストの長方形ブロックを受け取ります。テキストは、印刷可能なASCII文字(0x20〜0x7E)と、グリッドの行を区切る改行(0x0A)のみで構成されていると想定できます。
  • パターンの説明によると、このテキストブロックのサブセットとして一致が見つかった場合、この一致を返すか印刷する必要があります。一致するものが長方形でない可能性がある場合、いくつかの予約文字を使用して長方形領域にパディングする必要があります。複数の有効な一致がある場合、返される一致の選択方法(最大、最小、最初など)を決定できます。

一部のアプリケーションでは、実装が一致自体ではなく一致の位置を返すことができれば便利かもしれませんが、これは要件ではありません。

少なくとも、言語は、入力の連続した長方形のサブ領域としてパターンに一致できる必要があります。

あなたの答えは以下を含むべきです:

  • 記述言語の。
  • 作業実施。これは、プログラム、または選択した言語の関数/クラスのセットです。
  • 以下に示す例解決するためにどのように使用できるかを示すことにより、言語を実証する必要があります。あなたの言語はそれらのすべてに一致する必要はありませんが、これらのうち少なくとも8つに一致できる必要があります。あなたの言語が私たちが思いもしなかった素晴らしいことをすることができるなら、それも同様に自由に含めてください。

答えが既存のアイデアに基づいている場合、それは問題ありませんが、それが当然である場合はクレジットを与えてください。

拡張機能

上記は、有効な提出が満たす必要のある最小値を説明しています。ただし、いくつかの一般化により、次のようなパターンマッチング言語がさらに便利になります。

  • パターンを1つ以上のエッジに固定できるため、入力領域全体に特定のパターンがあるかどうかを確認できます。
  • 1つだけではなく、すべての一致を生成します。重複する一致のセマンティクスを選択できます。
  • 入力として四角形以外のテキストを使用します。
  • パターンで非矩形の一致を指定できるようにします。このような場合、出力は予約文字を含む長方形に埋め込まれる必要があります。
  • パターンが穴との一致を指定できるようにします。
  • 特定のオフセットで表示される2つの文字のように、不連続な一致を許可します。
  • 回転と反射の簡単な指定。
  • 必要に応じて、入力を周期的に円柱またはトーラスとして扱い、反対側のエッジが隣接していると見なします。

得点

この課題の主な目標は、将来使用される可能性のある効果的な2Dパターンマッチング言語を作成することです。そのため、「例を解決するための最短結合長」などのスコアリングシステムは、一般的な使いやすさを犠牲にして特定の機能をハードコーディングすることになります。したがって、このチャレンジは人気コンテストとして実施するのが最適であると判断しました。純投票数が最も多い提出が勝ちです。人々がどのように投票するかを強制することはできませんが、投票者が理想的に探すべきものについてのいくつかのガイドラインを以下に示します。

  • 表現力。この質問で提示された例以外にも、言語はさまざまな問題を解決できますか?推奨される拡張機能のいずれかをサポートしていますか?
  • 読みやすさ。表記法はどの程度直感的ですか(少なくとも基本的な構文を知っている人にとって)?
  • Golfitude。これはまだCodeGolf.SEです。このサイトの目的のために、パターンを記述するためのコードをほとんど必要としないマッチング言語があることはもちろん素晴らしいことです。

問題の例

次のスタックスニペットは、2次元パターンマッチング言語で対処できる16の問題例を示しています。各例には短い問題の説明が含まれており、通常、一致を検出できる1つの入力例と、一致が検出できない1つの例(該当する場合)が後に続きます。

上記のように、あなたの言語はこれらの問題のうち8つを解決できる必要があるだけです。その上にあるものはすべてオプションですが、得られる票の数を増やす必要があります。

(いいえ、そのHTMLコードを読む必要はありません。「コードスニペットを実行する」ボタンを押してブラウザで適切にレンダリングし、フルスクリーンで表示することもできます。)


これらの問題に一般的な時間制限はありますか?私はこれを解決することに非常に興味がありますが、私は非常に忙しいので、簡単に2週間かかることがあります。
デボンパーソンズ

7
@DevonParsons応募期限はありません。
PhiNotPi

特に、このために新しいタグを作成したため、面白そうです。2D言語を作成するためのボーナスポイントがあるはずだと思います。
mbomb007

1
@ mbomb007 2D言語を作成するためのボーナスポイントがあります。かなりの賛成票が得られると確信しています。;)
マーティン・エンダー

@MartinBüttner本当に言語を作成する方法さえ知りません。新しい言語のコードのファイルを取得するPythonプログラムを作成し(定義された構文に基づいて解釈/実行する)、出力を生成するような(単純な)ものでしょうか?
mbomb007

回答:


32

SnakeEx

これまでに15/16の問題を解決しました!

オンライン通訳者-完全な言語仕様 - Javascriptのソース

通訳のスクリーンショット

この言語の背後にある考え方は、正規表現のような構文を使用して文字をチェックするテキスト内を移動する「蛇」を定義することです。

SnakeExのプログラムは、さまざまなコマンドシーケンスを使用したヘビの定義のリストで構成されています。ヘビは、これらの定義を使用して他のヘビを生成できます。これは、SnakeExが最も力を発揮する場所です。分岐構造を一致させたり、再帰を実行したりすることもできます(Paren一致の例を参照)。

すべてのプログラムは基本的に正規表現のセットのように見えますが、ヘビの方向を変更する形式の方向コマンドを追加し、より多くのヘビを生成する形式のコマンドを呼び出します。<dir>{label<dir>params}

エントリポイントの場合、インタプリタは最初の定義を使用して1つのヘビを生成し、右に移動します。

それはひどく簡潔ではありませんが、非常に強力で、(私は)かなり読みやすいです。

更新情報

  • かわった !論理否定および〜一致をマークしない
  • <!>共線を解決するために追加されました
  • マッチングクロスの解決
  • チェス盤をそれほどひどくない方法で解決した
  • 有界閉包構文を追加 %{min,max}
  • 再帰の例を追加しました

解決策

15解決、1進行中

上記リンクのオンラインインタープリターを使用して、これらのプログラムを簡単に試すことができます!

問題1-チェス盤を見つける

m:{v<R>2}{h<>1}
v:{c<L>A1}+
h:{c<R>A2}+
c:_?(#_)+#?

詳細な紹介については、問題3から始めてください。

問題2-チェス盤の検証

m:{v<R>2}{h<>1}
v:${c<L>A1}+$
h:${c<R>A2}+$
c:$_?(#_)+#?$

範囲外の記号で適切なヘビをブックエンド$することは、プログラムを入力全体のみに一致させる1つの方法です。

問題3-数字の四角形を検出する

m:{c<R>A1}%{2,}
c:[0-9]%{2,}

mヘビ移動右、最小2匹のヘビ(AT産卵%{2,}定義cを(使用した「無限に2」を意味するクロージャである)c)と右移動(<R>すべての方向が現在のスネークに対して相対的であるので、)、またはむしろダウンこの場合です。Aparamがちょうど指定産卵蛇が呼び出し後に移動する必要があることをことを砂糖です。1「グループ」にヘビを入れて数パラメータ-私たちは長方形にマッチを制限する方法パラメータがあります。同じグループ内のすべてのヘビがまったく同じ距離を移動しない限り、試合はカウントされません。

問題4-単語検索で単語を見つける

m:<*>GOLF

方向コマンド<*>は、蛇が斜めまたは直交方向に回転することを指定します。次に、単純な正規表現を探します。

問題5-スクエア入力の検出

m:{v<R>1}{h<>1}
v:${c<L>A1}+$
h:${c<R>A1}+$
c:$.+$

ここで重要なのは、$蛇が範囲外の場合にのみ一致する特殊文字です。水平スネークと垂直スネークを生成します。それらのそれぞれは、エッジに沿って走るにつれてより多くのヘビを生み出し、それらはすべて同じグループに属し、同じ長さでなければなりません。

問題6-人生のゲームでグライダーを見つける

m:<+>[({l1<R>A}{l2<R>A}{l3<R>})({l1<L>A}{l2<L>A}{l3<L>})]
l1:##\.
l2:[(#\.)(\.#)]#
l3:#\.\.

m4つの直交方向(<+>)のいずれかで開始し、回転を実現します。次に、3行を順番に左または右に見て、反射を実現します。

(スペースにピリオドを入れたのは、インタープリターで使用されているHTMLテキストエリアに複数のスペースが連続している場合に愚かなことをするためだけです)

問題7-ネザーポータルの一致

m:{e<R>A1}{d<R>A1}%{2,22}{e<R>1}
e:~.X%{3,22}~.
d:X\.+X

m真ん中の列をチェックするために、2-22ヘビを左エッジをチェックするために、そして最終的に蛇が右端をチェックするためにヘビを産卵ヘビの移動右、。~オペレータは、以下のものは何でもチェックする必要がありますが、ソリューションの一部としてマークされるべきでないことを示しています。

有界閉包により、この問題を完全かつ適切に解決できるようになりました!

問題8-Minecraftの胸の配置

m:~{s<>}~!{d<+>}\.
s:<+>.<BR>([$\.]<R>)%{3}
d:.<+>CC

ここでは!、次のトークンが何とも一致しない場合にのみ一致する論理否定()を使用します。宣言dは特定の方向の二重チェストを検出するため!{d<+>}、直交する方向に二重チェストがないことを確認します。s現在の正方形の周りを小さなひし形で移動し、これらのスペースのうち少なくとも3つが空かボード外にあることを確認します。後続の\.条件は、前の条件がすべて成功したと仮定して、最終的に正方形に一致します。

問題9-水平および垂直方向の配置

m:<R>?#~.*#

mオプションで、ヘビ<R>?はシーケンスに一致する前に右に曲がります()。 .正規表現のように、ワイルドカードです。

問題10-共線点

m:<!>#~.*#~.*#

<!>方向を追加することで、今これを解決できます! <!>は似て<+>いますが、4方向に分岐するのではなく、可能なあらゆる方向に分岐します。

問題12-文字Qを避ける

m:{h<R>A}%{4}
h:[^Qq]%{4}

Q以外の4つのキャラクターをそれぞれ探す4つのヘビを生成します。

問題13-ダイヤモンドマイニング

m:{tl<RB>1}{tr<RF>1}
tl:X/*{bl<L>1}X
tr:X\\*{br<R>1}X
bl:X\\*X
br:X/*X

これはかなりきちんとしている。m2匹のヘビを産みます。1匹は右後方に、もう1匹は前方右に移動します。それらのそれぞれは、Xに向かってスラッシュをたどり、現在の方向に直角に別の蛇をスポーンします。

問題14-クロスのマッチング

m:{a<R>A}+{b<R>A}+{a<R>A}+
a:{e<>P1}{c<>P2}{e<>P3}
b:{c<>P1}{c<>P2}{c<>P3}
e:\.+
c:#+

Piggybackパラメーターを使用したのは初めてです。通常、ヘビは独立していますが、このパラメーターで呼び出しを行うと、呼び出し元のヘビは呼び出し先とともに移動します。したがってe2、「。」のシーケンス、次に「#」のシーケンス、次に「。」のシーケンスを確認し、それらをすべて個別の呼び出しにして、「1」、「2」、「3」でグループ化することができます、長さが一致するように強制します。

問題15-Boggleボードで単語を一致させる

m{I}:<*>p<*>a<*>n<*>a<*>m<*>a

言葉遣いならシンプル。Iparameterは、大文字と小文字を区別しないことを指定します(定義と呼び出しでパラメーターを指定できます)。ヘビは任意の方向に向きを変え、キャラクターと一致し、再び向きを変えます。

m{EI}:<*>p<*>a<*>n<*>a<*>m<*>a

これは、文字を再利用しないバージョンです。Eエクスクルーシブパラメータは、すでに多くのfeersumのスライムトレイルのように、マークされている任意の文字にマッチするから蛇を禁止します。

問題16-エッジを囲む

m{W}:{c<R>WA}%{3}
c:###

このWパラメーターにより、スネークが範囲外になったときにラップすることができます。またHV水平方向または垂直方向の折り返しのみが許可されます。

エキストラ-迷路ソルバー

m{E}:$(<P>\.)+$

歩行可能な床がピリオドであるASCII迷路を解決します。<P>方向手段は、前方、左、または右(砂糖[<F><L><R>])。

追加-パレンマッチング

m:\(~{r<>P}\)
r:[^\(\)]*(\({r<>P}\))?[^\(\)]*

プレリュードの作り方はまだわかりませんが、最初の一歩です!ここでは、r蛇を再帰的に使用して、対応する括弧の間に一致する括弧がないことを確認することで、一致する括弧を一致させます。

追加-ASCIIトポロジ:カウントループ


この言語が単なるマッチングではなく置換を行えるように、構文を追加することを検討しますか?codegolf.stackexchange.com/questions/51231/のエントリを作成するために、この課題に対するいくつかのソリューションを使用したいのですが、ここでは単一のソリューションが検索と置換を行いません。(言語仕様のタイミングルールにより、私の回答が有効ではないことを知っています)
スパー

@スパー。悪い考えではありませんが、それは確かにコードゴルフにもっと役立つでしょう。いつ自分でそれをする時間があるかはわかりませんが、心に留めておきます。
BMac

3
個別:方向変更の構文はわかりにくいです。キャラクターを一致させた後にヘビが進行するため、自分にとって意味のある場所よりも先にキャラクターの方向を変更する必要があります。例:文字列「ABC \ nDEF」で、ABCFで定義されたL字型のテトリスに一致させたい場合、蛇を「m:ABC <R> F」と書きたいが、「m:AB <R>」と書かなければならない代わりにCF」。これは仕様と一致することを理解していますが、非常に直感に反していると思います。
スパー

プレリュード構文の部分的な解決策があります。唯一の問題は、入力全体と一致しない場合、一致しないようにできないことです m:{a<>} a:[({n<R>A})({n<R>A}*{l<R>A}{a<>P}{r<R>A})]*{n<R>A}* l:$[^\(\)]*\([^\(\)]*$ r:$[^\(\)]*\)[^\(\)]*$ n:$[^\(\)]+$
。– TheNumberOne

21

スリップ、Python 3.4(Github wikiオンラインインタープリター

feersumの提出のように、これもグリッドのトラバースに基づいていますが、CarpetPythonの提出のように、これは正規表現に基づいています。どういうわけか、私はなんとか中間点に立つことができたように見えます。

追加したい未実装の機能が非常に多いので、関連する場合は、時間があるときに何をするつもりかを書き留めました。


更新情報

(詳細なニュースについてはGithubページをご覧ください)

  • 2015年4月5日:Slipにオンライン通訳が追加されました!まだ初期段階なので、いくつかのバグがあるかもしれません。

  • 2015年4月5日:効率の更新!ネザーポータルの大きな入力がはるかに高速(2秒)になりました。また、いくつかの構文の変更がありましたので、Wikiを確認してください。グループ番号も修正されました。


スリップには、特定の正方形から始まり、最初は右向きのマッチポインターがあります。文字が一致すると、ポインターは現在の方向に進みます(ただし、実装はその順序どおりに処理を行いません)。

マッチポインタの方向を有する特定の方向に設定することができ^<digit>^0^1^2、...、^7N、NE、E、...、NWは、それぞれ(時計回りに行く)へのポインタを設定します。

次のショートカットも利用できます。

  • ^* 8つの直交方向または斜め方向すべてをチェックし、
  • ^+ 4つの直交方向すべてをチェックします。

(今後の計画:(1, 2)騎士の移動など、任意の方向の設定を許可)

たとえば(問題4-単語検索で単語を見つける)、

^*GOLF

「GOLF」という単語を探して、8つの直交方向または斜め方向すべてを試行します。デフォルトでは、スリップは可能なすべての開始正方形を試行し、それぞれから1つの結果を返し、重複を除外するため、次のようなグリッド

GOLF
O
L
FLOG

一番上の行と一番下の行のみを一致として返します(一番上の行と左の列の「GOLF」は同じ正方形から始まるため)。すべての一致を取得するには、o重複一致モードを使用できます。

同様に(問題15-Boggleボードの単語と一致する)、

p^*a^*n^*a^*m^*a

panama毎回異なる方向を試して一致します。i大文字と小文字を区別しない場合は、フラグを使用します。スリップはデフォルトで文字を再利用しますが、これはrno-repeatフラグで切り替えることができます。

(今後の計画:繰り返し^*が不要になるように、各移動後に方向のセットを自動的にチェックする検索モード修飾子)

マッチポインタの方向は、<またはで>それぞれ90度左または右に回転させることもできます。例えば、

 `#`#< `#<  <`#<`#

パターンを探す

  #
## 
 ##

次の順序で確認します。

765
894
123

これにより、問題6-でグライダー見つける

^+(`#`# >`# > `#>`#> |`#`# <`# < `#<`#< | `#`#> `#>  >`#>`#| `#`#< `#<  <`#<`#)

ここで、パート1と2はグライダーのシェイプをエンコードし、パート3と4は反射した対応するものをエンコードします。

スリップは`エスケープにバックティックを使用することに注意してください。これは、Slipには、言語にスリップコマンドという名前を与える別の形式の動きがあるためです。/マッチポインターを左に直交して\スリップし、マッチポインターを右に直交してスリップします。

例えば、

abc   ghi
   def

で一致させることができますabc\def/ghi

単独では特に有用ではありません(?| <regex> )が、一致する先読みのように機能する静止グループと組み合わせると、スリップがより重要になります。内部の正規表現が照合され、その最後で、マッチポインタの位置と方向が静止グループの前の状態にリセットされます。

例えば、

abc
def
ghi

と一致させることができます(?|abc)\(?|def)\(?|ghi)

同様に、問題の12 -文字Qを避けてくださいすることで解決することができます

%(\(?|[^qQ]{4})){4}

where %は、最初の\アクティベーションを停止するためのノースリップコマンドです。

スリップには長さassertもあり、(?_(<group num>) <regex> )一致する長さが指定されたグループnumの長さと同じ場合にのみ、内部の正規表現に一致します。

たとえば、問題13-ダイヤモンドマイニングは次の方法で簡単に解決できます。

^1X(`/*)X>(?_(1)`\*)X>(?_(1)`/*)X>(?_(1)`\*)

これは、最初にダイヤモンドの左上を一致させようとし、他の3つの辺が同じ長さであると断言します。

v詳細出力のフラグを指定して実行)

Match found in rectangle: (8, 0), (12, 4)
  X
 / \
X   X
 \ /
  X

Match found in rectangle: (0, 0), (6, 6)
   X
  / \
 /   \
X     X
 \   /
  \ /
   X

Match found in rectangle: (2, 2), (4, 4)
 X
X X
 X

Match found in rectangle: (10, 2), (14, 6)
  X
 / \
X   X
 \ /
  X

Match found in rectangle: (5, 3), (9, 7)
  X
 / \
X   X
 \ /
  X

Match found in rectangle: (0, 6), (2, 8)
 X
X X
 X

ゴルファーの代替手段は

^1X(`/*)(X>(?_(1)`\*)X>(?_(1)`/*)){2}

これは、最初の側を2回一致させます。

他の問題の多くは、スリップ、固定グループ、長さアサートを使用して解決できます。

問題14-マッチングクロス:

(?|(`.+)(`#+)(`.+))(\(?|(?_(2)`.+)(?_(3)`#+)(?_(4)`.+)))*(\(?|(?_(2)`#+)(?_(3)`#+)(?_(4)`#+)))+(\(?|(?_(2)`.+)(?_(3)`#+)(?_(4)`.+)))+

最初の行の.sと#sの幅をキャプチャすると、それはずっと下に滑り落ちています。

出力:

Match found in rectangle: (0, 1), (5, 5)
.###..
######
######
.###..
.###..

Match found in rectangle: (4, 6), (6, 8)
.#.
###
.#.

いくつかのバグを整理した後、これはおそらく少しの再帰でゴルフすることができます。

問題3-数字の長方形を検出する:

(?|`d`d+)(\(?|(?_(1)`d+)))+

2桁以上の一番上の行と一致し、次にすべての行が同じ長さであることを確認します。`dは、に相当する定義済みの文字クラスです[0-9]

これにより、すべての一致が検出されることに注意してください。

問題7-ネザーポータルに一致:

(?|.X{2,22}.)\((?|(?_(1)X`.+X))\){3,22}(?_(1).X+.)

出力は、元のスレッドの一番上の例の場合:

Match found in rectangle: (2, 1), (5, 5)
XXXX
X..X
X..X
X..X
XXXX

Match found in rectangle: (9, 1), (14, 5)
.XXXX.
X....X
X....X
X....X
.XXXX.

Match found in rectangle: (13, 4), (17, 8)
.XXXX
X...X
X...X
X...X
.XXX.

最後に、スリップの他の機能には次のものがあります。

  • $0, $1, $2, ..., $7北端、北東隅、東端などを$+固定します。任意の端を$*固定し、任意の角を固定します。
  • $小文字の文字が続くことは、後により一致させることができ、現在の位置でアンカーを設定します$例えば、対応する大文字が続く$a$A
  • # no-moveフラグを切り替えます。これにより、次のマッチ後にマッチポインタが前方に移動するのが停止します。
  • ,はのような文字に一致し.ますが、出力に追加せず、によって認識できる一方で、連続しない一致を許可し(?_())ます。

... もっと。本当に多すぎてこのページにリストできません。

その他の問題

問題1-チェス盤を見つける:

(?|`#?(`_`#)+`_?)(?_(1)(?|...+))(\(?_(1)(?|`#?(`_`#)+`_?$a)))+<(?|`#?(`_`#)+`_?)(?_(9)(?|...+))(\(?_(9)(?|`#?(`_`#)+`_?)))+$A

2つのチェス盤の問題は確かにSlipの得意ではありません。一番上の行を一致させてから、長さが少なくとも3で、との間#で交互になることを確認してから_、後続の行をスリップして一致させます。最後までに、$aアンカーはチェス盤の右下になければなりません。

次に、左に曲がって列を繰り返し$A、最後に一致することを確認します。

問題2-チェス盤の検証:

$7%(\(?|`_?(`#`_)*`#?$2))+$5<%(\(?|`_?(`#`_)*`#?$0))+$3

前の問題と同様に、各行が正しいことを確認し、左に回転して列に対して同じことを行います。アンカーは、ボード全体のみが一致することを確認するために使用されます。

問題9-水平および垂直方向の配置:

>?`#,*`#

オプションの?を適用します >右または下に一致するように、rotateコマンドの量指定子。当社での例では、すべての5を見つけoモードを重ねるが、唯一の4それなし以来#.,###.,#同じ位置からスタート。

問題10-共線点

^+`#(?|(,*)<(,*))(((?_(2),*)<(?_(3),*),>)+#`#){2}

#次に、いくつかの水平方向の文字といくつかの垂直方向の文字を一致させ、2番目#まで繰り返し、3番目まで繰り返し#ます。

問題5-正方形入力の検出:

$7.(.*)>(?_(1).*)$3>((?|.*)\)*

右下隅を固定する前に、左上隅を固定し、上端が右端と同じ長さであることを確認します。入力がこれをパスする場合、入力全体に一致するように逆方向に上がります。

問題8-Minecraftのチェストの配置:

`.^+(($^|(?|`.))>){3}($^|`.|C<(($^|(?|`.))>){3})

pフラグを指定して実行し、各マッチの位置を取得します。$^次の動きがマッチポインターを範囲外に置く場合にマッチするアンカーです。

最初にaを照合し.、次に3つ.のs / boundariesに囲まれていることを確認してから、4番目の周囲の正方形も./ boundaryまたは単一のチェストであることを確認ます(周囲の正方形をチェックして)。

問題11-プレリュードの構文を確認します

$7>%(/(?|[^()]+$4)(?1)?|/(?|[^()]*`([^()]*$4)(?1)?/(?|[^()]*`)[^()]*$4)(?1)?)$1

数回試してみましたが、これは正しいと思います。ここでは、PCREと同じ構文を持つ再帰を使用します。

このアプローチでは、入力が長方形である必要がありますが、一度非長方形のマッチングが行われると、その仮定は不要になります。

これは同じアプローチで、より多くの再帰でゴルフをしました:

$7>%((/(?|([^()]*)$4)|/(?|(?4)`((?3))(?1)?/(?|(?4)`)(?3)))*)$1

問題16-エッジの周りを囲む:

%(\(?|`#{3})){3}

(注:ラッピングはまだオンライン通訳にプッシュされていません)

これには、ラッピングフラグが必要wです。技術的には%、ノースリップのイニシャルは必要ありませんが、マッチは1つ上の正方形から始まるものとしてカウントされます。

問題EX 1-迷路ソルバー:

S(^+`.)*^+E

チャットでのBMacのコメントの問題。rマッチポインターが行き来しないように、フラグを繰り返しなしモードに使用します。

問題EX 2 - 顔認識

(?|O(,*),(?_(2),*)O)(?_(2)(\(?|,))*)\(?|,(?_(2),*)O)(?_(2)(\(?|,))*)\`\(?_(2)`_*)`_(?_(2)`_*)`/

私は顔を照合するだけで、クリアは行わないことに注意してください。質問にはユーロ記号が含まれていることに注意してください。ユーロ記号を使用するには、印刷可能なASCIIに置き換える必要があります。


そのハッシュパターンはコンウェイグライダーです
-Heimdall

17

PMA /スネイル(C ++)

私は、言語をグリッド上を動き回り、コマンドを実行するカタツムリと考えています。カタツムリは、移動する各正方形にスライムの痕跡を残します。これにより、デフォルトでは、正方形はその後、一致しなくなります。コマンドのリストの最後に到達した場合、一致は成功です。

十分な演算子があるので、それらを追跡するために優先順位リストが必要になります。操作は次の順序で解決されます。

  1. グループ内 ( ) [ ]
  2. 代替文字に沿って分割 |
  3. `グループの左側のすべてを評価する
  4. 数量詞[m],[n]n
  5. アサーション = !
  6. 連結

インタープリターはC ++で作成されています。ひどいソースコードはここにあります

問題4:単語検索

プログラム

z\G\O\L\F

単語が見つかったかどうかの真実または偽の値を取得するには十分です。z(15の絶対または相対方向コマンドの1つ)は、任意の八重線方向に一致します。複数の連続する方向コマンドはORで結合されます。たとえば、右、上、左、下、および任意の対角線方向のコマンドであるため、ruldyとほぼ同等にzなります。ただし、方向は別の順序でテストされます。一致する最初の文字は、方向に関係なく、常にカタツムリが開始する文字です。\<character>は、単一のリテラル文字に一致します。

デフォルトの戦略は、左寄せ入力の境界ボックス内のすべての正方形でパターンを試行し、一致数を出力することです。ブール値1または0が必要な場合は、次のプログラムを使用できます。

?
z\G\O\L\F

ソースファイルに少なくとも1つの改行がある場合、最初の行は、入力を長方形の形式に初期変換するためのオプションとして扱われます。この?オプションは、どこにも一致するかどうかに応じて0または1を出力します。

問題15:切り替え

代替を実装した後、Boggleを解決できるようになりました。これには大文字と小文字を区別しないマッチングを使用する方が良いでしょうが、それを実装することは私の最優先事項ではありません。

\p|\P)z(\a|\A)z{\n|\N)z{\a|\A}z(\m|\M)z(\a|\A

|1次元正規表現とまったく同じように機能します。グループ化のための2つの一致する区切り文字ペア、つまり()とがあり{}ます。閉じ括弧は、同じタイプの最も近いものの間にある反対のタイプの開いているグループを閉じます。たとえば、次のよう{({{)に、左端のグループのみが開いたままになります。ご覧のとおり、エッジの一致しないグループ化シンボルは暗黙的に閉じられています。別のグループ化コマンドがありますが、ここでは説明し`ません。

問題8:Minecraftのチェスト

プログラムは、有効な胸部配置の数を印刷します。これは私が実際にゴルフをしなければならなかった最初のものであり、バイト数(17)を数回減らしました。

\.!(o\C)2o(!\Cw)3
  • \. 一致の開始点で、文字通りドットに一致します。
  • !(o\C)2!((o\C)2)定量化はアサーションよりも優先順位が高いためと同等です。正確に時間<atom> <number>を繰り返すことを意味します。カタツムリを任意の直交方向に回転させます。否定的な主張です。したがって、この部分は、隣接する二重チェストがないことを確認します。<atom><number>o!
  • o 直交する方向に回転します。
    • (!\Cw)3Cカタツムリの前に何もないと断言し、反時計回りに3回回転します。

問題2:チェス盤の検証

&
\#!(o^_)|\_!(o^#

この&オプションは、1すべての位置で一致が成功するようにプログラムの出力を設定し0ます。正規表現と同等^cではない文字に一致します。全体として、プログラムは次のことを意味します。入力の境界矩形のすべての位置に、でない文字に直交して隣接していない、またはである文字に直交して隣接していないない; それ以外の場合は0。c[^c]#__#


スライムトレイルのアイデアは、
ボグル

これは、Boggle問題の素晴らしい解決策です。私のアプローチではそれを解決できません。
ロジックナイト

14

Re2dクラス、Python 2

更新:「9.アライメント」問題を追加。

私のアプローチは、Python reモジュールを使用して検索とマッチングを行うことです。Re2dクラスは、処理のためにテキストを準備し、re関数を実行し、結果を出力用にフォーマットします。

これはまったく新しい言語ではないことに注意してください-これは、追加の2Dモード用のフラグが追加された2次元に投影される標準の正規表現言語です。

クラスには次の使用法があります。

re2dobject = Re2d(<horizontal pattern>, [<vertical pattern>], [<flags>])

両方のパターンは、標準の線形テキストREパターンです。垂直パターンが指定されていない場合、クラスは垂直方向のマッチングにも水平パターンを使用します。フラグは、いくつかの2D拡張機能を備えた標準のREフラグです。

テスト中

1. Finding chessboards
Chessboard pattern at (2, 1, 4, 3)

print '\n1. Finding chessboards'
reob1 = Re2d('#(_#)+_?|_(#_)+#?')
found = reob1.search('~______~\n~##_#_#~\n~#_#_##~\n~##_#_#~\n~______~')
print 'Chessboard pattern at', found
assert not reob1.search('#_##\n_#_#\n__#_\n#_#_\n#_#_')

検索メソッドはチェス盤パターンを見つけ、4タプルの位置を返します。タプルには、x,y一致の最初の文字の位置と、 width, height一致した領域の位置があります。1つのパターンのみが指定されているため、水平および垂直のマッチングに使用されます。

2. Verifying chessboards
Is chess? True

print '\n2. Verifying chessboards'
reob2 = Re2d('^#(_#)*_?|_(#_)*#?$')
print 'Is chess?', reob2.match('_#_#_#_#\n#_#_#_#_\n_#_#_#_#')
assert not reob2.match('_#_#_#__\n__#_#_#_\n_#_#_#__')

チェス盤は、ブール値を返すmatchメソッドで検証されました。 テキスト全体と一致するには^$開始文字と開始文字が必要であることに注意してください。

3. Rectangle of digits
Found: [(0, 1, 5, 3), (1, 1, 4, 3), (2, 1, 3, 3), (3, 1, 2, 3), (0, 2, 5, 2), (1, 2, 4, 2), (2, 2, 3, 2), (3, 2, 2, 2), (6, 3, 2, 2)]
Not found: None

print '\n3. Rectangle of digits'
reob3 = Re2d(r'\d\d+', flags=MULTIFIND)
print 'Found:', reob3.search('hbrewvgr\n18774gwe\n84502vgv\n19844f22\ncrfegc77')
print 'Not found:', reob3.search('uv88wn000\nvgr88vg0w\nv888wrvg7\nvvg88wv77')

ここで、MULTIFINDフラグを使用して、2 +桁ブロックに一致する可能性のあるものすべてを返します。このメソッドは、9つの可能な一致を見つけます。それらは重複する可能性があることに注意してください。

4. Word search (orthogonal only)
Words: [(0, 0, 4, 1), (0, 3, 4, 1), (3, 3, -4, -1), (3, 2, -4, -1), (3, 0, -4, -1)] [(0, 0, 1, 4), (3, 0, 1, 4), (3, 3, -1, -4), (0, 3, -1, -4)]
Words: ['SNUG', 'WOLF', 'FLOW', 'LORE', 'GUNS'] ['S\nT\nE\nW', 'G\nO\nL\nF', 'F\nL\nO\nG', 'W\nE\nT\nS']
No words: [] []

print '\n4. Word search (orthogonal only)'
words = 'GOLF|GUNS|WOLF|FLOW|LORE|WETS|STEW|FLOG|SNUG'
flags = HORFLIP | VERFLIP | MULTIFIND
reob4a, reob4b = Re2d(words, '.', flags), Re2d('.', words, flags)
matching = 'SNUG\nTEQO\nEROL\nWOLF'
nomatch = 'ABCD\nEFGH\nIJKL\nMNOP'
print 'Words:', reob4a.search(matching), reob4b.search(matching)
print 'Words:', reob4a.findall(matching), reob4b.findall(matching)
print 'No words:', reob4a.findall(nomatch), reob4b.findall(nomatch)

このテストは、垂直および水平の反転の使用を示しています。これにより、一致する単語が逆になります。斜めの単語はサポートされていません。この MULTIFINDフラグは、4つの方向すべてで複数の重複する一致を許可します。findallメソッドは、検索を使用して一致するボックスを検索し、一致するテキストブロックを抽出します。逆方向の一致に負の幅や高さを検索で使用する方法に注意してください。垂直方向の単語には改行文字があります-これは、2D文字ブロックの概念と一致しています。

7. Calvins portals
Portals found: [(3, 1, 5, 6)]
Portal not found None

print '\n7. Calvins portals'
reob7 = Re2d(r'X\.{2,22}X|.X{2,22}.', r'X\.{3,22}X|.X{3,22}.', MULTIFIND)
yes = '....X......\n.XXXXXX.XX.\n...X...X...\n.X.X...XXX.\n...X...X.X.\n.XXX...X.X.\nX..XXXXX.X.'
no = 'XX..XXXX\nXX..X..X\nXX..X..X\n..X.X..X\n.X..X.XX'
print 'Portals found:', reob7.search(yes)
print 'Portal not found', reob7.search(no)

最小サイズはそれぞれ異なるため、この検索で​​は各ディメンションに個別のパターンが必要でした。

9. Alignment
Found: ['#.,##', '##'] ['#\n.\n,\n.\n#', '#\n,\n.\n#']
Found: [(3, 4, 5, 1), (6, 4, 2, 1)] [(7, 0, 1, 5), (3, 1, 1, 4)]
Not found: None None

print '\n9. Alignment'
reob9a = Re2d(r'#.*#', r'.', MULTIFIND)
reob9b = Re2d(r'.', r'#.*#', MULTIFIND)
matching = '.,.,.,.#.,\n,.,#,.,.,.\n.,.,.,.,.,\n,.,.,.,.,.\n.,.#.,##.,\n,.,.,.,.,.'
nomatch = '.,.#.,.,\n,.,.,.#.\n.,#,.,.,\n,.,.,.,#\n.#.,.,.,\n,.,.#.,.\n#,.,.,.,\n,.,.,#,.'
print 'Found:', reob9a.findall(matching), reob9b.findall(matching)
print 'Found:', reob9a.search(matching), reob9b.search(matching)
print 'Not found:', reob9a.search(nomatch), reob9b.search(nomatch)

この2つの検索のセットは、2つの垂直一致と2つの水平一致を検出しますが、埋め込まれた#.,#文字列を検出できません。

10. Collinear Points (orthogonal only)
Found: [(0, 1, 7, 1)] [(3, 1, 1, 4)]
Not found: None None

print '\n10. Collinear Points (orthogonal only)'
matching = '........\n#..#..#.\n...#....\n#.......\n...#....'
nomatch = '.#..#\n#..#.\n#....\n..#.#'
reob10h = Re2d(r'#.*#.*#', '.')
reob10v = Re2d('.', r'#.*#.*#')
flags = MULTIFIND
print 'Found:', reob10h.search(matching, flags), reob10v.search(matching, flags)
print 'Not found:', reob10h.search(nomatch, flags), reob10v.search(nomatch, flags)

ここでは、2つの検索を使用して、両方向の一致を見つけます。複数の直交一致を見つけることができますが、このアプローチは対角一致をサポートしていません。

12. Avoid qQ
Found: (2, 2, 4, 4)
Not found: None

print '\n12. Avoid qQ'
reob12 = Re2d('[^qQ]{4,4}')
print 'Found:', reob12.search('bhtklkwt\nqlwQklqw\nvtvlwktv\nkQtwkvkl\nvtwlkvQk\nvnvevwvx')
print 'Not found:', reob12.search('zxvcmn\nxcvncn\nmnQxcv\nxcvmnx\nazvmne')

この検索により、最初の一致が検出されます。

13. Diamond Mining
.X.
X.X
.X.

.X.
X.X
.X.

..X..
./.\.
X...X
.\./.
\.X..

..X..
./.\.
X...X
.\./.
..X..

.XX.\
//.\.
X...X
.\./.
..X..

...X...
../.\..
./.X.\.
X.X.X.X
.\.X.//
..\./X.
.X.X..\

Diamonds: [(2, 2, 3, 3), (0, 6, 3, 3)] [(8, 0, 5, 5), (10, 2, 5, 5), (5, 3, 5, 5)] [(0, 0, 7, 7)]
Not found: None None None

print '\n13. Diamond Mining'
reob13a = Re2d(r'.X.|X.X', flags=MULTIFIND)
reob13b = Re2d(r'..X..|./.\\.|X...X|.\\./.', flags=MULTIFIND)
reob13c = Re2d(r'...X...|../.\\..|./...\\.|X.....X|.\\.../.|..\\./..', flags=MULTIFIND)
match = '''
...X......X....
../.\..../.\...
./.X.\..X...X..
X.X.X.XX.\./.\.
.\.X.//.\.X...X
..\./X...X.\./.
.X.X..\./...X..
X.X....X.......
.X.............
'''.strip().replace(' ', '')
nomatch = '''
.X......./....
.\....X.......
...X.\.\...X..
..X.\...\.X.\.
...X.X...X.\.X
../X\...\...X.
.X...\.\..X...
..\./.X....X..
...X..../.....
'''.strip().replace(' ', '')
for diamond in reob13a.findall(match)+reob13b.findall(match)+reob13c.findall(match):
    print diamond+'\n'
print 'Diamonds:', reob13a.search(match), reob13b.search(match), reob13c.search(match)
print 'Not found:', reob13a.search(nomatch), reob13b.search(nomatch), reob13c.search(nomatch)

ダイヤモンドの問題はより困難です。3つのサイズには3つの検索オブジェクトが必要です。テストセットで6個のダイヤモンドを見つけることができますが、可変サイズのダイヤモンドにスケールしません。これは、ダイヤモンドの問題の部分的な解決策にすぎません。

Python 2コード

import sys
import re

DEBUG = re.DEBUG
IGNORECASE = re.IGNORECASE
LOCALE = re.LOCALE
UNICODE = re.UNICODE
VERBOSE = re.VERBOSE
MULTIFIND = 1<<11
ROTATED = 1<<12     # not implemented
HORFLIP = 1<<13
VERFLIP = 1<<14
WRAPAROUND = 1<<15  # not implemented

class Re2d(object):
    def __init__(self, horpattern, verpattern=None, flags=0):
        self.horpattern = horpattern
        self.verpattern = verpattern if verpattern != None else horpattern
        self.flags = flags

    def checkblock(self, block, flags):
        'Return a position if block matches H and V patterns'
        length = []
        for y in range(len(block)):
            match = re.match(self.horpattern, block[y], flags)
            if match:
                length.append(len(match.group(0)))
            else:
                break
        if not length:
            return None
        width = min(length)
        height = len(length)
        length = []
        for x in range(width):
            column = ''.join(row[x] for row in block[:height])
            match = re.match(self.verpattern, column, flags)
            if match:
                matchlen = len(match.group(0))
                length.append(matchlen)
            else:
                break
        if not length:
            return None
        height = min(length)
        width = len(length)
        # if smaller, verify with RECURSIVE checkblock call:
        if height != len(block) or width != len(block[0]):
            newblock = [row[:width] for row in block[:height]]
            newsize = self.checkblock(newblock, flags)
            return newsize
        return width, height

    def mkviews(self, text, flags):
        'Return views of text block from flip/rotate flags, inc inverse f()'
        # TODO add ROTATED to generate more views
        width = len(text[0])
        height = len(text)
        views = [(text, lambda x,y,w,h: (x,y,w,h))]
        if flags & HORFLIP and flags & VERFLIP:
            flip2text = [row[::-1] for row in text[::-1]]
            flip2func = lambda x,y,w,h: (width-1-x, height-1-y, -w, -h)
            views.append( (flip2text, flip2func) )
        elif flags & HORFLIP:
            hortext = [row[::-1] for row in text]
            horfunc = lambda x,y,w,h: (width-1-x, y, -w, h)
            views.append( (hortext, horfunc) )
        elif flags & VERFLIP:
            vertext = text[::-1]
            verfunc = lambda x,y,w,h: (x, height-1-y, w, -h)
            views.append( (vertext, verfunc) )
        return views

    def searchview(self, textview, flags=0):
        'Return matching textview positions or None'
        result = []
        for y in range(len(textview)):
            testtext = textview[y:]
            for x in range(len(testtext[0])):
                size = self.checkblock([row[x:] for row in testtext], flags)
                if size:
                    found = (x, y, size[0], size[1])
                    if flags & MULTIFIND:
                        result.append(found)
                    else:
                        return found
        return result if result else None

    def search(self, text, flags=0):
        'Return matching text positions or None'
        flags = self.flags | flags
        text = text.split('\n') if type(text) == str else text
        result = []
        for textview, invview in self.mkviews(text, flags):
            found = self.searchview(textview, flags)
            if found:
                if flags & MULTIFIND:
                    result.extend(invview(*f) for f in found)
                else:
                    return invview(*found)
        return result if result else None

    def findall(self, text, flags=0):
        'Return matching text blocks or None'
        flags = self.flags | flags
        strmode = (type(text) == str)
        text = text.split('\n') if type(text) == str else text
        result = []
        positions = self.search(text, flags)
        if not positions:
            return [] if flags & MULTIFIND else None
        if not flags & MULTIFIND:
            positions = [positions]
        for x0,y0,w,h in positions:
            if y0+h >= 0:
                lines = text[y0 : y0+h : cmp(h,0)]
            else:
                lines = text[y0 : : cmp(h,0)]
            if x0+w >= 0:
                block = [row[x0 : x0+w : cmp(w,0)] for row in lines]
            else:
                block = [row[x0 : : cmp(w,0)] for row in lines]
            result.append(block)
        if strmode:
            result = ['\n'.join(rows) for rows in result]
        if flags & MULTIFIND:
            return result
        else:
            return result[0]

    def match(self, text, flags=0):
        'Return True if whole text matches the patterns'
        flags = self.flags | flags
        text = text.split('\n') if type(text) == str else text
        for textview, invview in self.mkviews(text, flags):
            size = self.checkblock(textview, flags)
            if size:
                return True
        return False

ダイヤモンドの問題が明確でない場合、ダイヤモンドは0、1、または2だけでなく、任意のサイズにすることができます。編集:仕様を編集して、これをより明確にしました。
PhiNotPi

とった。Re2dにはこの問題に対する部分的な解決策しかないことを答えに書き留めておきます。可変サイズに拡大縮小することはできません。それは大丈夫ですか?
ロジックナイト

はい、大丈夫です。
-PhiNotPi

14

グライム、ハスケル

前書き

グライムはブール文法に基づいています。基本的な考え方は、小さなコンポーネントから長方形のパターンを構築し、それらが入力行列にあるかどうかを確認することです。これまでのところ、Grimeは長方形の一致のみをサポートし、少なくとも11の問題を多少ともエレガントに解決します。

編集:クロスを修正し(バグを発見したDLoscに感謝)、ダイヤモンドマイニングを追加しました。

EDIT2:スリップのそれらに触発されたキャラクタークラスを追加しました。また、オプションフラグの構文を変更し、式パーサーを改善し、no-Q問題を追加しました。

EDIT3:サイズの制約を実装し、ネザーポータルの問題を追加しました。

使用法

Grimeプログラムはグラマーと呼ばれ、グラマーの正しいファイル拡張子はですが.gr、これは強制されません。文法は次のように評価されます

runhaskell grime.hs [options] grammarfile matrixfile

どこmatrixfile文字行列を含むファイルです。たとえば、数字の文法は次のように評価されます。

runhaskell grime.hs digits.gr digit-matrix

速度を上げるために、最適化を行ってファイルをコンパイルすることをお勧めします。

ghc -O2 grime.hs
./grime digits.gr digit-matrix

デフォルトでは、インタープリターは最初に見つかった一致を出力しますが、これはオプションフラグを使用して制御できます。

  • -e:マトリックス全体のみ1に一致し、一致する場合と一致0しない場合に出力します。
  • -n:一致の数、または-e指定されている場合はマトリックス全体を出力します。
  • -a:すべての一致を出力します。
  • -p:一致の位置も形式で出力します(x,y,w,h)
  • -s:マッチ自体を出力しません。
  • -d:デバッグ情報を出力します。

オプションは、任意の行の前に挿入してカンマを追加することにより、文法内で指定することもできます,(例については以下を参照)。

構文とセマンティクス

グライムの文法は、それぞれが別々の行にある1つ以上の定義で構成されます。それらのそれぞれは非端末の値を定義します、そして、それらの1つは匿名のトップレベル非端末を定義しなければなりません。定義の構文はN=EorでE、where Nは大文字Eで、です。

式は次のように構築されます。

  • でエスケープされた文字は、その文字を含む\すべての1x1長方形と一致します。
  • . 任意の1文字に一致します。
  • $1x1文字行列の外側の長方形に一致します。
  • _ 幅または高さがゼロの長方形に一致します。
  • 定義済みの文字グループは、digit、uppercase、lowercase、alphabetic、alpha numeric、symbolです。
  • 新しい文字クラスは、構文によって定義できます[a-prt-w,d-gu]。左側の文字が含まれ、右側の文字が除外されているため、これは完全に一致しabchijklmnoprtvwます。左側が空の場合、すべての文字が含まれていると見なされます。右側が空の場合、コンマは省略できます。文字[],-\はでエスケープする必要があります\
  • エスケープされていない大文字は非終端記号であり、割り当てられた式と一致します。
  • Pand Qが式である場合、それPQはちょうど水平方向の連結でありP/Q、上にある垂直方向の連結Pです。
  • P+は1つ以上Pのsが水平にP/+配置され、同じが垂直に配置されます。
  • ブール演算はP|QP&Qおよびで示されP!ます。
  • P?短縮形であるP|_P*のためにP+|_、とP/*のためにP/+|_
  • P#の一致を含む任意の長方形に一致しますP
  • P{a-b,c-d}ここで、abcd非負の整数で、あるサイズの制約P。場合はP、文字クラスがあり、その式は、任意のマッチしmxnて文字のみを含む長方形、m間にあるab包括的に、そしてn間にあるcd包括的。それ以外の場合、式は、正しいサイズを持ち、かつ一致するすべての長方形にP一致します。場合aまたはc省略され、それらがあると解釈され0、そして場合bまたはd省略されている、彼らは無限にあります。間にハイフン場合aとがb省略され、その後、我々は区間の両端で同じ番号を使用します。全体がc-d一部が省略され、両方の軸が制約されます。明確にするために、はと{-b}同等であり{0-b,0-b}、と{a-,c}同等{a-infinity,c-c}です。

ノート

グライムはA=A!、未定義の動作のような逆説的な定義を許可します。ただし、クラッシュや無限ループは発生しません。

Grimeは非矩形入力をサポートしています。行は単に左に揃えられ、ギャップはを使用して一致させることができます$

将来的には、次を実装したいと思います。

  • より高速なマッチング。現在、インタープリターは、たとえば、長方形に.しか一致できないという事実を考慮していません1x1。一致するものが見つかるまで、すべてのサイズのすべての長方形が順番に試行され、それぞれの長方形が即座に失敗します。
  • 単語の検索とグライダーの課題のための回転操作と反射操作。
  • コンテキストを使用した四角形以外の一致は、Boggleボードチャレンジで役立ちます。たとえば、下のコンテキスト(右のコンテキスト)をPv(Q>R)意味PQますR。L字型のパターンと一致します

    PPP
    PPP
    QQQRRRR
    QQQRRRR
    QQQRRRR
    

タスク

おおまかに複雑さの順に与えられます。

数字の長方形

d{2-}

これは単純です2x2。少なくともサイズの数字の長方形。

qまたはQなし

[,qQ]{4}

これは最初のものとほとんど同じくらい簡単です。現在、より制限されたサイズとカスタム文字クラスがあります。

水平および垂直方向の配置

\#.*\#|\#/./*/\#

エスケープされた文字がいくつかあります。基本的に、これは1つ#、次に任意の数の文字、次に#、水平または垂直のいずれかに一致します。

正方形入力を検出する

S=.|S./+/.+
e,S

この文法は非常に単純です。基本的に、正方形は1x1長方形、または右端に1列、その下に1行が固定された小さな正方形のいずれかであることを定義します。また、e入力全体の検証を切り替えるトップレベルの非終端記号の前のオプションにも注意してください。

単語検索で単語を見つける

G=\G
O=\O
L=\L
F=\F
GOLF|FLOG|G/O/L/F|F/L/O/G|G.../.O../..L./...F|...G/..O./.L../F...|F.../.L../..O./...G|...F/..L./.O../G...

グライムには回転や反射の操作がないため、これは恐ろしいことです。また、Grimeは一致のサイズが4x11x4またはのみであることを認識していないため、非常に低速4x4です。

グライダーの問題も同様に解決できますが、私はそれを書くのが面倒です。

ネザーポータル

.\X+./\X/+\.{2-22,3-22}\X/+/.\X+.

サイズ制限演算子を使用すると、これはそれほど難しくありません。中央部分は正しいサイズの\.{2-22,3-22}任意の長方形と一致します。.次にX、両側にsの列を追加しX、その上下に無視された端を持つsの行をタックします。

マッチングクロス

E=\.+/+
F=\#+/+
EFE/F/EFE&(E/F/E)F(E/F/E)

ここにあるのは、2つの式の論理積(論理AND)です。非終端E試合の空でない長方形.の、およびFの空でない長方形#の。コンジャンクションの左側は、タイプの長方形と一致します

...####..
...####..
...####..
#########
#########
.....##..
.....##..

私たちがEFE一番上にあり、そしてF、そしてEFE再び。右側はこれらの転置に一致するため、正確に十字を取得します。

ダイヤモンドマイニング

C=./+
T=\X|CTC/\/.+\\
B=\X|\\.+\//CBC
CTC/\X.+\X/CBC

非終端記号Cは、1xn列の省略形です。ダイヤモンドの上半分は、T単一のX、またはT両側の列とその/[something]\下の行に囲まれた別のいずれかに一致します。 B同様にダイヤモンドの底に一致し、トップレベルの非終端記号はX[something]X、上半分と下半分の間のフォームの単なる行です。

チェス盤を見つける

(\#\#|\#/\#|\_\_|\_/\_)#!&[#_]{3-}

右側はsとsの[#_]{3-}任意の3x3またはより大きな長方形と一致しますが、左側は2つの隣接するsまたはs が含まれないことを保証します。#_#_

チェス盤の検証

e,(\#\#|\#/\#|\_\_|\_/\_)#!&[#_]+/+

これは基本的に上記と同じですが、空ではない任意の長方形と一致させることができますが、e入力検証全体にフラグを使用する必要があります。

プレリュードの構文を検証する

A=[,()]/*
P=A*|P(A/\(/A)P(A/\)/A)P
e,P

これはおそらくこれまでで最も興味深い文法です。非終端A一致する列が含まれていない(、または)、とP一致するいくつかの数のいずれかAの、またはそれ以上の存在であると外部と2つの整合括弧、Psは。


@DLosc修正、バグを見つけてくれてありがとう!
ズガルブ

だろう\#(.*|./*)\#動作しますか?
Seequ

@Siegアライメント用?残念ながら、それは「#左側に1つ、次に何かの行または列、次に#右側に1つ」として解析されるためです。#スラッシュを使用してsが列に垂直に連結されるように指定する必要があります/
ズガルブ

10

TMARL

テンプレート照合および認識言語

説明

私の通訳は24K文字を(占めるコードスニペットは、文字を取る?)ので、完全な説明を見つけることができるここに

最良の部分:インタープリターはJavascriptであるため、ここで試すことができます!

そして問題について:

#1-チェス盤を見つける

$#_#
a
$_#_
bvacvbS5&(avcS5)G0G2P

&検索を追加します。最後のG2は、一致要素の3番目の要素である実際の一致を取得します。最初の2つの要素は、x座標とy座標(1ではなく、0である)です。

#3-数字の長方形を検出する

$DD
$DD
S1G2P

これは非常に簡単だと思います。

#4-単語検索で単語を見つける

$GO\LF
a
$G
$*O
$**\L
$***F
S6&(aS6)G0G2P

S引数がそうであっても、それはすべての回転を検索することです。次の検索に追加できるため、4より大きい(個々の一致は追加できない)。

#5-スクエア入力の検出

IL-(IG0L)!P

これが完全に合法かどうかはわかりません。入力が長方形の場合にのみ直角度を正しく決定するからです。入力ILの長さと最初の行の長さを比較し、それIG0Lを反転します。

#6-人生のゲームでグライダーを見つける

$## 
$# #
$# 
a
$ ##
$## 
$  #
bS6&(bMS6)&(aS6)&(aMS6)G0G2P

最後に、ミラーの使用!

#12-手紙Qを避ける

$[^Qq]
~4*4S1G2P

S1。必要なのは1つの一致だけです。

難しいもののいくつかは後で行います。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.