逻辑点形状


12

游戏

最近,我的大部分时间都花在了手机上的一个令人上瘾的游戏中,名为Logic Dots,这激发了我编写这一挑战的灵感。如果我向您展示游戏画面,则更容易解释这些规则,因此以下是未解决且已解决的难题的屏幕截图:

现在,这里要注意三件事。

  1. 游戏板(中心的4x4正方形网格)
  2. 所需的形状(从顶部开始,在第二个栏中的链接点,在乐谱和菜单下等)均为全线,或者a由1个矩形组成
  3. 行和列上的数字,表示解决方案中列中需要多少个点

游戏的目的是使所需的形状适合网格。您可以旋转形状,但不能斜入。

在解决方案中,请注意,所有形状仅创建一次(因为它们仅在所需的形状中创建一次),在这种情况下,它们都是水平的,但也可以是垂直的。正方形中的粉红色表示未使用的正方形。

这是一个更大,稍微更复杂的网格:

请注意,在未解决的难题中,已经有一些正方形填满。灰色的正方形表示您不能在其上放置点的被遮盖的正方形。带有尾巴的点告诉您该点处有一个点,并且它在尾巴的方向上链接了至少一个点,但在任何其他方向(包括相反的方向)上都没有链接。

符号

对于本文的其余部分,我将使用以下符号来指代董事会:

  • <,>,^,v-表示一个预先放置的点,其尾部沿点的方向延伸
  • *-表示一个点。如果在未解决的网格(输入)上给出,则它是单个形状。如果是输出,则将其连接到其周围的点。
  • #-表示被遮挡的网格正方形(您不能在其中放置点)
  • -,| (连字符和横线)-分别表示一个带有左右尾巴的点和一个带有上下尾巴的点
  • **(空格字符)-**表示空白

使用这些符号,后一种示例情况(未解决)可以表示为:

 <    



    # 
 ^ #

解决方案可以表示为:

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

请注意,没有两个形状可以水平,垂直或对角线接触,因此以下情况无效:

 *** 
**   
  ** 

挑战

您面临的挑战是解决从4x4到9x9的所有逻辑点难题。您将收到四行输入,然后是游戏板。这些行将如下所示:

  • 第一行,形状-要查找的形状,每个形状均以表格形式给出sizexquantity(例如,3x2对于长度为三的两个形状),并以空格分隔。示例行:3x1 2x1 1x1
  • 第二行,列-每列所需的点数的空格分隔列表。示例行:1 1 2 2
  • 第三行,行-每行所需的点数的空格分隔列表。示例行:3 0 3 0
  • 第4行,电路板尺寸-一个整数,电路板尺寸, B

然后给出该板,并且是B使用上述符号表示板的输入线。例如,后一种示例情况的完整输入如下:

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



    # 
 ^ #  

然后,您的程序将以相同的符号输出已求解的板。上述输入的匹配输出如下:

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

请注意,游戏板可以具有多种解决方案。在这种情况下,只需输出一个有效的解决方案。此外,对于复杂的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 2015年

@flawr t no two shapes can touch horizontally, vertically or diagonally(这应该是开头,几乎不会在结尾处丢失,但是无论如何……)
edc65

@globby不会用#代替每个空白处,我想#是当您在游戏中单点一个空白处时。完成关卡后,它将填充所有空白单元格。
Teun Pronk

@TeunPronk No.#是预先确定的空间,您不能在级中放置点,如第二个示例中的灰色方块。
globby 2015年

2
比提供赏金更好的是,您应该添加更多有趣的测试用例并修复问题中的错误。例如,当前测试用例之前的最后一个输出仍然包含<和^
edc65

Answers:


3

蟒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尝试在板上放置一种形状。对于每个可能的位置,它使用修改后的板进行调用。其中有3个循环。o确定方向(2-水平,3-垂直)。它将始终放置水平的形状,因此,在最后o=2,它将使用功能转置板ti是行,并且j都是可能的起始列。然后,如果形状的末端具有有效的字符,形状的中间具有有效的字符以及周围是否为空,则会进行大量检查。


当我看到您的上一次编辑(-30)并放弃时,我正努力削减最后6个字节...您对它的价值拥有投票
edc65

3

的JavaScript(ES6)661 667 695 702 745 755 786 790 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忘了那个赏金。无论如何,在这场比赛中玩得很开心。
2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.