プレリュード構文チェッカー


10

Preludeは難解なプログラミング言語であり、有効なプログラムを構成するものに対する制限はほとんどありませんが、珍しいものです。印刷可能なASCIIテキストの任意のブロック(「ブロック」は、印刷可能なASCIIの行が改行で区切られることを意味します-0x0A)は、次の条件が満たされている場合に有効です:

  • テキストのすべての(垂直)列には、(およびのいずれかが含まれます)
  • 垂直位置を無視して、()はバランスがとれています。つまり、それぞれ()その右側の1つだけがペアになり、その逆も同様です。

印刷可能なASCIIと改行を含む文字列を指定して、それが有効なPreludeプログラムを構成するかどうかを決定するプログラムまたは関数を記述します。STDIN(または最も近い代替)、コマンドライン引数または関数引数を介して入力を受け取ることができます。選択した2つの固定された 真偽値を使用して、結果をSTDOUTに返したり、出力したりできます。

入力が長方形であると想定してはいけませ

これはコードゴルフなので、最短の提出(バイト単位)が勝ちます。

以下は有効な Preludeプログラムです(実際、これらは実際の Preludeプログラムです):

?1-(v  #1)-             
1   0v ^(#    0)(1+0)#)!
    (#)  ^#1-(0 #       
1(#  1) v #  - 1+)
    vv (##^v^+
? v-(0 # ^   #)
?
  1+              1-!

そして、ここにいくつかの入力がありますが、すべて無効です:

#(#(##)##)##(
)##(##(##)#)#
#(#)
)###
#(##
(##)
(##)
(#)#
(##)
(###
#(#)
(##)
#(#)
###)
#()#
()##
#(#)##
###
###(#)

Preludeには、近い括弧をブロックする可能性があるコメントがありますか?
Alex A.

@アレックスいいえ。上記のルールは、プログラムが有効であるかどうかを決定するためのすべてです。
マーティンエンダー2015年

分かりました。ありがとうございます。確認したかっただけです。
Alex A.

ルール1-「テキストのすべての列に含まれる(および)の最大1つ」; 例1、2行目:「1 0v ^(#0)(1 + 0)#)!」-> 3 )と2が表示され(ます。1行に1つだけではいけませんか?
Ismael Miguel

1
@IsmaelMiguelの「列」は通常、垂直線を指すと理解されています(特にグリッドのコンテキストでは)。とにかく私はそれを明確にしました。
Martin Ender 2015年

回答:


3

CJam、57 56バイト

qN/z_{_"()"--W<},,\s:Q,{)Q/({_')/,\'(/,-}:T~\sT0e>+z+}/!

長すぎると、たくさんゴルフすることができます。ゴルフしたら追加される説明。

簡単な説明

コードには2つのチェックがあります。

  • 最初のフィルターは、各列が最大で1つのブラケットであることを確認します。フィルターの最終的な出力は、複数の角かっこを持つ列の数です。
  • 次に、入力を列メジャー形式に変換し、各インデックスで2つの部分に分割します。
    • これら2つの部分のそれぞれで、(Number of "(" - Number of ")")は互いに補完し合う必要があります。したがって、それらを合計すると、結果は0になるはずです。このプロパティに失敗した部分は、入力全体の括弧が一致しなくなります。
    • 「(」が「)」の左側にあることも確認する必要があります。つまりNumber of "(" - Number of ")"、右側のブロックではの値を負にすることはできません。

ここでオンラインでお試しください


6

Python 2、128 119 105バイト

def F(p):
 v=n=1
 for r in map(None,*p.split("\n")):A,B=map(r.count,"()");n+=B-A;v*=n<2>A+B
 return n*v>0

Python 2でNoneマッピングできることをご存知ですか?

説明

まず、列が行になるようにプレリュードを転置することから始めます。通常、これはを使用して行いますがzipzip行の最短の長さに切り捨てられ、itertools.zip_longestコードゴルフには長すぎるため、必要なことを行うための短い方法はないようです...

マッピングを除くNone

>>> print map(None,*[[1,2,3],[4],[5,6]])
[(1, 4, 5), (2, None, 6), (3, None, None)]

残念ながら(または、幸いにもすべての非ゴルフ目的で)、これはPython 2でのみ機能します。

nv

  • nスタックのように機能し、を数え1 - <number of unmatched '(' remaining>ます。いずれの場合も(1を減算し、すべての)場合n >= 2は1を加算します。したがって、いずれかの時点で、)sが多すぎてプログラムが無効であることがわかります。nが1で終了しない場合、少なくとも1つの不一致が(残っています。
  • v有効性をチェックし、1から開始します。プログラムが無効である(n >= 2またはA+B >= 2)場合、v0になり無効であることを示します。

したがって、プログラムが有効であれば、最終的にはが必要になりますn = 1, v = 1。プログラムが無効な場合、最終的にはv = 0、またはのいずれかが必要になりますv = 1, n <= 0。したがって、有効性は簡潔にとして表すことができますn*v>0

(@feersumのおかげで、14バイトの多くの良い提案がありました!)

以前の、より読みやすい提出:

def F(p):
 p=map(None,*p.split("\n"));v=n=0
 for r in p:R=r.count;A=R("(");B=R(")");n+=A-B;v|=A+B>1or n<0
 return n<1>v

それはmap...のめちゃくちゃな使い方です
xnor

1
def F(p): v=n=3 for r in map(None,*p.split("\n")):A,B=map(R.count,"()");n+=A-B;v*=n>2>A+B return n*v==9
119-

@feersumありがとう!私は変更しようとしてきのだor比較の連鎖の中に、私は変更することを考えていなかった|=*=。しかし、物事をさらに後退させることにより、別のバイトを
取りました

2

J、64バイト

入力は、末尾に改行がある文字列です。出力は0または1です。

(0=(1<|s)s+[:(|@{:+(0>])s)[:+/\]s=.+/@:)@(1 _1 0{~[:'()'&i.];.2)

使用例

   ]in=.'#(#)##',LF,'###',LF,'###(#)',LF
#(#)##
###
###(#)

   ((0=(1<|s)s+[:(|@{:+(0>])s)[:+/\]s=.+/@:)@(1 _1 0{~[:'()'&i.];.2)) in
0

方法は次のとおりです

  • 改行で入力を切り取り、行列に入れる ];.2
  • マップ(/ )/ anything else1/ -1/0 1 _1 0{~[:'()'&i.]
  • s=.+/@:動詞に追加された副詞を定義して、動詞配列の出力を合計します
  • 列に値を追加する ]s

    • ()すべての接頭辞の正のバランスをチェックします [:(0>])s)[:+/\]
    • ()リスト全体(つまり、最後の接頭辞)で等しいバランスをチェックします |@{:@]
  • 列にabs(values)を追加し、すべての要素の最大値1を確認します (1<|s)s

  • 以前のすべてのチェックで失敗時に正の値が得られたので、それらを合計して0と比較し、入力の有効性を取得します。 0=]


2

J、56バイト

3 :'*/0<: ::0:(+/\*:b),-.|b=.+/+.^:_1]0|:''()''=/];.2 y'

これは、末尾に改行のある文字列を受け入れ、0または1を返す無名関数です。右から左に読み取ります。

  • ];.2 y、他のJの送信と同様yに、最後の文字が出現するたびに文字列をカットし(入力に後続の改行が必要な理由です)、行が断片である長方形のマトリックスを作成し、必要に応じてスペースを埋め込みます。

  • '()'=/最初にその行列のすべての文字を比較し(、次に)2つの0-1行列のリストを返します。

  • +.^:_1]0|:2つの行列のリストを複素数の単一の行列に変換します。これまでのところ、プログラム(は入力のすべて)を1に、すべてをiに、その他すべての文字を0に変換します。

  • b=.+/その複素行列の行の合計をに割り当てbます。

  • -.|b1- | z |のリストを作成します のすべてのzに対してb。すべての列に最大で1つの括弧が含まれるという条件は、これらすべての数値1- | z |に変換されます。負ではありません。

  • +/\*:bは、の数値の2乗の合計を実行するベクトルですb。すべての列に最大で1つの括弧が含まれている場合、の数値の2乗bはすべて0、1、または-1です。,さん| Z | 1-ベクトルで、このベクトルを連結します。

  • 今、すべて私たちが行う必要があるが、当社の連結ベクトルのエントリがあることテストされv、これはほとんど非負実数の番号である*/0<:vのいくつかのエントリがあれば、エラーが発生していることを除いて、v本物ではない、我々は交換するよう<:<: ::0:、単にエラーの場合に0を返します。


複素数を使った素晴らしいアイデアですが0={:+/\*:b、たとえば(、それが有効でないためかどうかを確認する必要もあります。
randomra 2015年

ああ、あなたは正しい、@ randomra、忘れた!
オマール

1
0=(-|)v非負の実数をチェックするために2バイト短くなります。(CJamを倒そう!:P)
randomra

1
ああ、inv代わりに^:_1 別のバイトを保存します。
randomra

1
(バランスチェックで)56へ戻ります3 :'*/0=({:,]-|)(-.@|,+/\@:*:)+/+.inv]0|:''()''=/];.2 y'
randomra 2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.