パズルをスライドさせることはできますか?


38

すべての細胞はどちらかであるテキストの矩形グリッドにかかるプログラムや機能書きますAB。すべてのAセルは単純に接続された形状を形成します。つまり、すべてのセルは穴なしで直交して接続されます(斜めに隣接する文字は接続されているとはみなされません)。同様に、すべてのBセルが別の単純に接続された形状を形成します。グリッドは、常に少なくとも一つ含まれていますAし、少なくとも一つをB

グリッドは、実際に表される薄いプラスチック二塊状状片であり、想像AB部分。テーブルの上に平らに置いた場合、テーブルの上で両方を完全に平らに保ちながら、2つの部品を引き離すことができますか?

2つの図形と図形を単純に引き離すことでこのように分離できる場合は、真理値を印刷または返します。そうでない場合は、偽の値を出力するか返します。AB

たとえば、入力

AAA
ABB
AAA

BBセクションは右にスライドして、から分離できるため、真実ですA

AAA
A    BB
AAA

ただし、入力

AAAA
ABBA
ABAA

スライドする方法はありませんのでfalsyあるAB、それらを重複せずに離れた部分は。

バイト単位の最短コードが優先されます。必要に応じて、およびの代わりに任意の2つの印刷可能なASCII文字を使用できます。AB

真実の例(空行で区切られている)

BBB
BAA
BBB

BA

A
B

AB
AB

AAA
BBB

AAAAB
ABBBB

ABBA
ABBA
AAAA

AAAAAABBBBBBBBB
AABBBBBBBBBBBBB
AAAAAAAAAABBBBB
AABBBBBBBBBBBBB
AAAAAAAAAAAAAAB

AAAAAAAAAAAA
ABABABABABAB
BBBBBBBBBBBB

BAAAAABB
BBAAABBB
BBBABBBB
BBBABBBB
BBBABBBB
BBBBBBBB
BBBBBBBB

AAA
BAA
AAA

偽の例

BBBB
BAAB
BABB

BBBB
BAAB
AABB

BBBBBBB
BBBBBAB
AAAAAAB
BBBBBBB

BAAA
BABA
BBBA
AABA
AAAA

AAAAAAA
ABBBBBA
AAAAABA
BBBBBBA

BAAAAABB
BBAAABBB
BBBABBBB
BBBABBBB
BBBAABBB
BBBBBBBB
BBBBBBBB

AAA
ABA
BBA
ABA
AAA

回答:


9

カタツムリ、14

o(t\B+~)+!(t\B

パズルを引き離すことができる場合、入力の領域を印刷します。それ以外の場合は、0を出力します。

大きな例では、グリッドの領域で時間がかかるため、少し遅いです。

         ,, the program will print the number of starting cells matching this pattern
o        ,, pick a cardinal direction
(
    t    ,, teleport to any cell on the grid
    \B+  ,, match "B" 1 or more times, moving in the direction set by 'o'.
         ,, when a cell is matched, it gets slimed and can't be matched again.
    ~    ,, match an out-of-bounds cell
)+       ,, do parenthesized instructions 1 or more times
!(       ,, the following must not match:
    t\B  ,, teleport to some cell and match 'B'

4
「それは少し遅いです..」。あなたはカタツムリと呼ばれる言語に何を期待したかわからない...
Bassdrop Cumberwubwubwub

4
@Bas今、傷に塩をこする理由はありません。
トラシバ

21

CJam、33 32 20 19 17バイト

@ Sp3000および@MartinBüttnerからの大規模なサポートを含む改訂版:

qN/_z]{:e`z,3<}/|

オンラインで試す

貢献

  • @ Sp3000は、私の元のアルゴリズムの重要な簡素化を提案しました。
  • @MartinBüttnerは、彼の気まぐれなゴルフスキルを改訂されたアプローチに適用しました。

アルゴリズムと証明

以下では、パズルが水平方向にスライドするための基準について説明します。縦の場合は、行ではなく列を見るか、文字行列を転置して行をもう一度見ることで決定できます。

同じ文字の最大シーケンスに「ストレッチ」という用語を使用します。たとえば、次の行にはそれぞれ1、2、および3ストレッチがあります。

AAAAAAAA
BBBAAAAA
AABBBAAA

また、スライドできない行/パズルを「インターロック」という用語を使用します。

重要なのは、すべての行に最大2つのストレッチがある場合にのみ、パズルが離れてスライドできることです。または逆に、2つ以上のストレッチを持つ行がある場合にのみ、インターロックされます。

以下は厳密な数学的証明とはみなされないかもしれませんが、なぜそうなるべきかを説得力のある説明にすると信じています。

2ストレッチ以上の行がある場合、パズルが連動していることが簡単にわかります。3つのストレッチがある行を見る:

BBBAAB

Aストレッチがストレッチ間でロックされているため、パズルが滑り落ちるのを防ぐことは明らかですB。これは、行が連動することを意味し、これによりパズル全体が連動します。

証明の反対方向はそれほど明白ではありません。すべての行が1つまたは2つのストレッチしか持たないインターロックパズルがないことを示す必要があります。いくつかの観察から始めます。

  • ストレッチが1つしかない行は、衝突することなくどちらの方向にもスライドできるため、パズルのインターロックに寄与しません。
  • 2ストレッチのすべての行の順序がAとであるB場合、パズルは明らかに連動していません。この場合、すべてのAセルがすべてのBセルから離れるか、またはその逆になり、2つのピースをスライドさせても衝突はありません。

唯一のトリッキーなケースは、異なる順序の2つのストレッチを持つ行があるパズルです。このようなパズル、指定された仕様では存在しないことを示します。これを示すために、この構成を持つ部分的なパズルを見てみましょう。.ワイルドカードは次のとおりです。

.......
AAABBBB
.......
BBAAAAA
.......

さて、仕様は、両方のことを言うAB、細胞は、単純にすべての有効なパズルに接続されています。ようにするにはA上記の部分的なパズルに接続されたセルを、我々は2つのオプションがあります。

  1. のストレッチの1つをループします。Bたとえば、

    ..AAAAAA
    AAABBBBA
    .......A
    BBAAAAAA
    ........
    

    これを行うために、行の1つを3つのストレッチを持つように避けられないため、すべての行が最大2つのストレッチを持つ有効なパズルを提供することはありません。

  2. それらを直接パスで接続します。

    .......
    AAABBBB
    ..A....
    BBAAAAA
    .......
    

    A細胞は現在、単純に接続されており、2つの以上のストレッチを持つ行はまだありません。ただし、Bセルも単純に接続する必要があります。直接パスは接続されたAセルによってブロックされ、セルを接続する唯一の方法Bは、セルのストレッチの1つをループAすることです。これはケース1に戻り、3つのストレッチの行を作成せずにそれを行うことはできません。

ストレッチをカウントするために、実装はCJam RLE演算子を使用します。

コードの説明

qN/     Get input and split at newlines.
_z      Make a transposed copy.
]       Wrap the original and transposed puzzle in an array so that we can
        loop over the two.
{       Start of loop over original and transposed puzzle.
  :e`     Apply RLE to all rows.
  z,      Transpose the matrix with the RLE rows, and take the element count of the
          result. Or in other words, take the column count. This will be the length
          of the longest row after RLE.
  3<      Check the length for less than 3.
}/      End of loop over original and transposed puzzle.
|       Or the results of the two.

9

JavaScriptの(ES6)、108の 107 98 91 82バイト

a=>!(T=[],R=/AB+A|BA+B/).test([...a].map((c,i)=>T[i%-~a.search`
`]+=c))|!R.test(a)

ライブデモ。Firefoxでテスト済み。入力を改行区切りの文字列として受け取ります。

編集:

  • \nリテラル改行に変更して1バイトを保存しました。
  • 配列に変換するのではなく、複数行の文字列に対してRegExpテストを直接実行することで9バイトを節約しました。
  • 配列内包表記を使用して文字列を分割し、移動してさらに9バイトを削除しました!g機能し、アレイ上に直接正規表現を呼び出す代わりに使用しましたfind
  • 別の9バイトを保存することにより、関節シーケンスを継続しました。転置を行う前に、改行で配列を分割する代わりに、インデックスでモジュラスを行いました。

使い方

前のバージョン:

a=>(T=[],a.split`
`.map(s=>s.split``.map((c,i)=>T[i]+=c)),!T.find(g=s=>/AB+A|BA+B/.test(s)))|!g(a)
  1. 入力を受け取りa、改行で文字列の配列に分割します。
  2. 転置aしてに保存しTます。のmap各要素を反復処理してa、文字列を文字配列に分割し、map再度使用してi、行のth文字をのith行 に追加しますT。の各要素Tは初期化されていないため、最終的にはのようなもの"undefinedAAABBA"になりますが、これは重要ではありません。
  3. gパターンに一致するRegExpベースのテスト関数を作成します/AB+A|BA+B/。一致する場合B、2つ以上Aのsの間にsのセットが挟まれているか、その逆であるため、ピースは指定された方向にロックされます。
  4. テスト関数gを使用して、ブロックのすべての要素をテストし、を使用して一致するかaどうかを調べます。両方が一致する場合、ピースは両方向にロックされるため、偽の値を出力します。そうでない場合は、真の値を出力します。Tfind

5

Javascript(ES6)、118

slidey=
// code
a=>!a.match(R=/AB+A|BA+B/)||!(a=a.split`
`.map(b=>b.split``))[0].map((_,c)=>a.map(d=>d[c])).some(e=>e.join``.match(R))

// IO
var S =document.getElementById('S');
S.onkeyup = _=> document.getElementById('P').innerText = slidey(S.value);

document.getElementById('P').innerText = slidey(S.value);
<textarea id='S'>BAAAAABB
BBAAABBB
BBBABBBB
BBBABBBB
BBBABBBB
BBBBBBBB
BBBBBBBB</textarea>
<p id='P'></p>

説明:

a=> !/* check string horizontally */ || !/* check string vertically by transposing it and
                                            running the same horizontal check */

a=> !a.match(R=/AB+A|BA+B/) || !/* ... */
// check for lines containing something like BAAAAAB or ABBBBBBBA
// this is the only way something can get blocked horizontally
// eg AAAAAAA
//    AAABAAA <<< note the B in the middle of As here
//    AAABBBB <<< blocked from being pulled out horizontally
//    AAAAAAA

a=> /* ... */ ||!( a = a.split('\n').map(b=> b.split('')) ) // split a into 2D array
    [0].map((_,c)=>a.map(d=>d[c])) // transpose it
    .some(e=>e.join``.match(R)) // run the check again using `some` to go line by line
                                // which is shorter than .join().match() outside

a=> !/* returns null if no horizontal obstacles and an array if there are */
    || !/* same thing */
// negate both to cast to a boolean (false if obstacles, true if not)
// an input can only be unslidable if both directions are blocked
// so (no obstacles vertically? || no obstacles horizontally?) gives the answer

ねずみ!それに私を打つ。
-intrepidcoder

5

JavaScript(ES6)72 74

@NotthatCharlesに保存された2バイトの編集

1つのピースがほんの少しのステップだけスライドできる場合、それは無料であるという直感的な理解があります。現在のテストケースはこれを確認します。

だから、私は各方向に1ステップだけチェックします。

使用する文字:
AおよびBなどの2つの印刷可能文字を使用するには、1および0 2バイト多く

EcmaScript 6準拠のブラウザーで以下のスニペットを実行してテストします(スプレッド演算子-IE Firefoxをサポート)

f=s=>[w=~s.search`
`,-w,-1,1].some(o=>![...s].some((x,p)=>x+s[p+o]==10))

// 4 bytes more- for any symbol, not just 1 and 0 (for instance A and B):
g=s=>[w=~s.search`
`,-w,-1,1].some(o=>![...s].some((x,p)=>x+s[p+o]=='AB'))

//TEST
console.log=x=>O.innerHTML+=x+'\n'

testOk = [
 '111\n100\n111',
 '10',
 '0\n1',
 '01\n01',
 '000\n111',
 '00001\n01111',
 '0110\n0110\n0000',
 '000000111111111\n001111111111111\n000000000011111\n001111111111111\n000000000000001',
 '000000000000\n010101010101\n111111111111',
 '10000011\n11000111\n11101111\n11101111\n11101111\n11111111\n11111111',
 '000\n100\n000'
]

testKo = [
 '1111\n1001\n1011',
 '1111\n1001\n0011',
 '1111111\n1111101\n0000001\n1111111',
 '1000\n1010\n1110\n0010\n0000',
 '0000000\n0111110\n0000010\n1111110',
 '10000011\n11000111\n11101111\n11101111\n11100111\n11111111\n11111111',
 '000\n010\n110\n010\n000'
]

console.log('Expecting true')
testOk.forEach(t=>console.log(t+'\n'+f(t)+'\n'))
console.log('Expecting false')
testKo.forEach(t=>console.log(t+'\n'+f(t)+'\n'))
<pre id=O></pre>


まあ、それはただの天才です。プロによって再びBeatられた。:-)
ETHproductions

s[p+o]=='0'少し長いようです。1-s[p+o]、または少なくとも置き換えられs[p+o]==0ますか?
ETHproductions

@ETHproductionsはい、それは長く、もう少し考える価値があります。これは、「\ n」は(垂直境界、0に変換)および未定義のための(上側及び下側境界は、NaNに変換する)ための偽を与えなければならない
edc65

=='A'に置き換えることができます<'B'。同じ=='B'
チャールズではない

また、あなただけではできませんx+s[p+o]=='AB'か?
チャールズではない

3

Mathematica 100 69バイト

@Martin Buttnerのおかげで、大量の31バイトが節約されました。

g=Max[Length/@Split/@#]<3&;g[c=Characters@StringSplit@#]||g@Thread@c&

入力を文字のマトリックスとしてフォーマットします。また、行列の転置を行います。マトリックスまたはその転置のいずれかが行ごとに2回以下の場合、パズルはスライドできます。

{a,a,b,b,b} 2通の手紙があります。

{a,a,b,a,a} 3通の手紙があります。

{a,a,b,a,a,a,b,b,b,b,b,b,b,b} 4通の手紙があります。


2

Dyalog APL、22バイト

(∨/{∧/2>+/2≠/⍵}¨)⊂∘⍉,⊂

ここで試してみてください。 これは、文字の2D配列を取り込んで、1スライドするインスタンスとスライドしないインスタンスに戻る関数です0。このアルゴリズムは、他のほとんどの回答と似ています。マトリックスとその転置をチェックして、行に異なる文字の隣接ペアが複数含まれていないことを確認します。4x3入力行列の場合

AAAA
ABBB
AAAB

関数は次のように呼び出すことができます

f ← (∨/{∧/2>+/2≠/⍵}¨)⊂∘⍉,⊂
f 4 3 ⍴ 'AAAAABBBAAAB'

結果はになり1ます。

説明

⊂∘⍉,⊂   The matrix and its transpose.
{...}¨   For each of them:
  2≠/⍵   On each row, replace each adjacent pair with 1 if they differ, with 0 otherwise
  2>+/    Take the sum on each row and check that it's less than 2
  ∧/     AND over all rows
∨/      OR over the resulting two values

1

JavaScript(ES6)、94バイト

x=>!(y=/AB+A|BA+B/).test(x)|(z=[],x.split`
`.map(b=>b.split``.map((c,i)=>z[i]+=c)),!y.test(z))

同じサイズの代替方法:

x=>(t=s=>!/AB+A|BA+B/.test(s),z=[],x.split`
`.map(b=>b.split``.map((c,i)=>z[i]+=c)),t(x)|t(z))

これは1、真実の入力と偽りを返します0。他の回答が投稿される前に、この作業を開始しました。私はもともとES7の配列内包表記を使ってみましたが、この方法よりも約10文字長くなりました。

やってみて:

a=x=>!(y=/AB+A|BA+B/).test(x)|(z=[],x.split`
`.map(b=>b.split``.map((c,i)=>z[i]+=c)),!y.test(z))

P.onclick=_=>Q.innerHTML='Result: '+a(O.value)
<textarea id=O cols="20" rows="8">AAAAAABBBBBBBBB
AABBBBBBBBBBBBB
AAAAAAAAAABBBBB
AABBBBBBBBBBBBB
AAAAAAAAAAAAAAB</textarea>
<button id=P>Test</button>
<p id=Q>Result: </p>

提案を歓迎します!


b.split``の代わりに[... b]を使用すると3バイト節約されますが、一部のブラウザーでのみ機能します。
イントレピダー
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.