論理ドット形状


12

ゲーム

最近、私の時間の大部分は、ロジックドットと呼ばれる、携帯電話で中毒を起こすゲームに費やされました。ゲームのディスプレイを表示するとルールを説明するのが簡単になるため、ここでは未解決の解決済みパズルのスクリーンショットを示します。

ここで、注目すべき3つの主な点があります。

  1. ゲームボード(中央にある4x4の正方形のグリッド)
  2. 必要な形状(上から2番目のバー、スコアおよびメニューの下など)のすべての線、またはa1つの長方形によるリンクされたドット
  3. 解決策のために、列に必要なドットの数を示す行と列の数値

ゲームの目的は、必要な形状をグリッドに収めることです。図形を回転させることはできますが、斜めに入れることはできません。

ソリューションでは、すべてのシェイプが一度だけ作成されることに注意してください(必要なシェイプに一度だけあるため)。この場合、それらはすべて水平ですが、垂直にすることもできます。正方形に塗りつぶされたピンク色は、使用されていない正方形を示します。

これは、より大きく、わずかに複雑なグリッドです。

未解決のパズルには、すでにいくつかの正方形が塗りつぶされていることに注意してください。灰色の正方形は、ドットを配置できないブロックされた正方形を示します。テールのあるドットは、そのスポットにドットがあることを示し、テールの方向で少なくとも 1つ以上のドットにリンクしいますが他の方向(反対方向を含む)ではリンクしいません。

表記法

この投稿の残りの部分では、次の記号を使用してボードを参照します。

  • <、>、^、v-事前に配置されたドットがポイントの方向に伸びるテールを持つことを示します
  • *-ドットを示します。未解決のグリッド(入力)で指定された場合、それは個々の形状です。出力の場合は、周囲のドットに接続されます。
  • #-ブロックされたグリッドスクエアを示します(ドットを配置できない場所)
  • -、| (ハイフンとバー)-左右の尾を持つドットと、上下の尾を持つドットをそれぞれ示します
  • **(スペース文字)-**空のスペースを示します

これらのシンボルを使用すると、後者の例のケース(未解決)は次のように表すことができます。

 <    



    # 
 ^ #

ソリューションは次のように表すことができます。

*< * *
   *  
     *
 *   *
 * *#*
 ^ # *

2つの図形が水平、垂直、または斜めに接触することはできないため、次のケースは無効です。

 *** 
**   
  ** 

チャレンジ

あなたの課題は、4x4から9x9までのロジックドットパズルを解決することです。4行の入力を受け取り、次にゲームボードを受け取ります。行は次のようになります。

  • 1行目、図形-検索する図形。それぞれフォームsizexquantity3x2長さ3の2つの図形など)で指定され、スペースで区切られます。例の行:3x1 2x1 1x1
  • 2行目、列-各列に必要なドット数のスペース区切りリスト。例の行:1 1 2 2
  • 3行目、行-各行に必要なドット数のスペース区切りリスト。例の行:3 0 3 0
  • 4行目、ボードサイズ-単一の整数、ボードサイズ、 B

次にボードが与えられ、B上記の表記法を使用してボードを表す入力行になります。たとえば、後者の例の完全な入力は次のとおりです。

4x1 3x1 2x2 1x2
1 4 0 3 0 5
4 1 1 2 3 2
6
 <    



    # 
 ^ #  

その後、プログラムは解決されたボードを同じ表記で出力します。上記の入力に一致する出力は次のとおりです。

** * *
   *  
     *
 *   *
 * *#*
 * # *

ゲームボードには複数のソリューションがある場合があることに注意してください。この場合、有効なソリューションを1つだけ出力してください。また、プログラムは、複雑な10x10グリッドの合理的なデスクトップコンピューターで10秒以内に正しいソリューションを出力する必要があります。

これはコードゴルフであるため、最小バイトが勝ちます。


テストケース

入力1

3x2 1x4
2 2 3 1 2
4 0 3 0 3
5


    #
  #  
    *

出力1

*** *

 ***#
  #  
* * *

入力2

3x1 1x6
2 0 4 0 3
3 1 2 1 2
5
*    


   # 

出力2

* * *
  *  
  * *
*  # 
  * *

入力3

5x1 4x1 2x1 1x2
1 2 3 3 2 2
0 5 0 4 0 4
6
#     
  -   


 #    
   <  

出力3

#     
 *****

 **** 
 #    
* ** *

はい、それは正しいです@flawr
globby

@flawr t no two shapes can touch horizontally, vertically or diagonally(これは最初にある必要があり、ほぼ終わり近くではなく、とにかく...)
edc65

@globbyすべての空のスペースが#に置き換えられるわけではありません。ゲーム内の空のスペースをシングルタップしたときは#であると思います。レベルを完了すると、すべての空のセルがいっぱいになります。
テウンプロンク

@TeunPronk No.#は、2番目の例の灰色の四角のように、レベルにドットを配置できないように事前に決定されたスペースです。
globby

2
報奨金を提供するよりも、より興味深いテストケースを追加し、質問のエラーを修正する必要があります。たとえば、現在のテストケースの前の最後の出力には、<と^が含まれています
-edc65

回答:


3

Python 2:766 739 696 663 633バイト

def f(B,S,o=0):
 if[]==S:print'\n'.join(B);exit()
 s=S[0]
 for i in r:
  for j in R(Z-s+1):
   if(B[i][j]in' '+'>v'[o])*(B[i][j+s-1]in' '+'<^'[o])*({' ','-|'[o]}>=set(B[i][j+1:j+s-1]))*all(B[x][y]in'# 'for x,y in [(x,y)for y in R(j-1,j+s+1)for x in i-1,i+1]+[(i,j-1),(i,j+s)]if 0<=x<Z>y>=0):q=B[:];q[i]=q[i][:j]+'*'*s+q[i][j+s:];q=(q,t(q))[o];any((t(q)+q)[k].count('*')>m[k]for k in R(Z+Z))or f(q,S[1:])
 o or f(t(B),S,1)
y=raw_input;S=[];s=str.split
for i in s(y()):u,v=map(int,s(i,'x'));S+=[u]*v
m=map(int,s(y())+s(y()));Z=input();R=range;r=R(Z);B=[y()for _ in r];J=''.join;t=lambda x:map(J,zip(*x))
f(B,S[:len(S)-J(B).count('*')])

オンラインで動作することを確認してください:Ideone.com(オンラインバージョンは大きくて難しいグリッドには遅すぎる場合がありますが、オフラインでは問題ありません)

入力はstdinを介して行われ、OPから行をコピーして貼り付けます(ただし、stackexchangeはスペースまたは行を削除することがあるので注意してください)。

このコードの基本的な考え方:再帰関数を使用しますffボードに1つの形状を配置しようとします。可能な場所ごとに、変更されたボードで自身を呼び出します。3つのループがあります。o方向を決定します(2-水平方向、3-垂直方向)。図形は常に水平に配置されるため、の最後にo=2関数でボードを転置しますti行でありj、すべての可能な開始列です。シェイプの両端に有効な文字がある場合、シェイプの中央に有効な文字がある場合、および周囲が空の場合、多くのチェックが行われます。


私はあなたの最後の編集(-30)を見て、あきらめたときに私は、最後の6つのバイトを切るのに苦労した...あなたは私のために票を持っているもの、それの価値
edc65

3

JavaScript(ES6)661 667 695 702 745 755 786 790 784 784 798

進行中の作業、短縮することができます。 おそらく複雑なグリッドでは遅すぎます。そうでないかもしれない。

編集少し長く、ずっと速く。
編集2バグ修正、列/行チェック。ちなみに、今では高速です

M関数がメインです。wパラメータは、すべての入力を含む複数行の文字列です。この関数は入力を解析し、開始ボードを準備します。<>^v|-*開始ボードの文字はに置き換えられ,、それぞれ,*正しいソリューションで置き換えられる必要があります。

R関数は、ボード内のすべての形状を再帰的に配置しようとします。シェイプが配置されると、シェイプの短いリストと変更されたボードを渡して自身を呼び出します。すべてのシェイプが配置されたときに、に,置き換えられない場合、ソリューションは依然として無効になる可能性があります*

P関数は、指定された位置と方向に形状を配置できるかどうかをテストします。すべてのコストラインをチェックします(ボード内、オーバーラップ、タッチなし、有効な行と列のカウント)

M=w=>(
  [x,c,r,z]=w=w[S='split'](n='\n'),
  (b=[...w.slice(4).join(n)])
  .map((c,p)=>~(k='*<>-*^v|'.indexOf(c))&&[(q=k>3?z:1,0),k&1&&-q,k&2&&q].map(o=>b[p+o]=0),
    c=c[S](e=' '),r=r[S](e),w=z++,f='*',s='',x[S](e).map(v=>s+=v[0].repeat(v[2]))),
  R=(s,b,x=0,y=0,n=s[0],V=i=>b[i]>'#',
    P=(p,o,q,t,g,l,d=[...b])=>{
        if(l<z-n&!V(p+o*l-o)&!V(p+o*l+o*n))
        {
          for(i=-1;v=d[p],++i<w;p+=o,t-=v==f)
            if(i>=l&i-n<l)
              for(v!=e&v!=0|[q,w,~z].some(w=>V(p+w)|V(p-w))?t=0:d[p]=f,j=o*i,u=k=0;
                  ++k<z;(u+=d[j]==f)>g[i]?t=0:j+=q);
          return t>=n&&d.join('')
        }
    })=>{
    if(b){
      if(!n)return~b.search(0)?0:b;
      for(s=s.slice(1);y<w||(y=0,++x<w);++y)
        if(h=R(s,P(y*z,1,z,r[y],c,x))||n>1&&R(s,P(x,z,1,c[x],r,y)))return h
    }
  })(s,b)

FireFox / FireBugコンソールでテストする

;['3x2 1x4\n2 2 3 1 2\n4 0 3 0 3\n5\n     \n     \n    #\n  #  \n    *\n'
,'3x1 1x6\n2 0 4 0 3\n3 1 2 1 2\n5\n*    \n     \n     \n   # \n     \n'
,'5x1 4x1 2x1 1x2\n1 2 3 3 2 2\n0 5 0 4 0 4\n6\n#     \n  -   \n      \n      \n #    \n   <  \n'
,'4x1 3x1 2x2 1x2\n1 4 0 3 0 5\n4 1 1 2 3 2\n6\n <    \n      \n      \n      \n    # \n ^ #  \n']
.forEach(x=>console.log(x,M(x).replace(/ /g,'`'))) // space replaced with ` for clarity

出力(合計実行時間<1秒)

3x2 1x4
2 2 3 1 2
4 0 3 0 3
5


    #
  #  
    *

***`*
`````
`***#
``#``
*`*`*

3x1 1x6
2 0 4 0 3
3 1 2 1 2
5
*    


   # 


*`*`*
``*``
``*`*
*``#`
``*`*

5x1 4x1 2x1 1x2
1 2 3 3 2 2
0 5 0 4 0 4
6
#     
  -   


 #    
   <  

#`````
`*****
``````
`****`
`#````
*`**`*

4x1 3x1 2x2 1x2
1 4 0 3 0 5
4 1 1 2 3 2
6
 <    



    # 
 ^ #  

**`*`*
```*``
`````*
`*```*
`*`*#*
`*`#`*

@globbyはその報奨金を忘れたようです。とにかく、このレースはとても楽しかったです。
ジャクベ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.