你能把点连接起来吗?


18

这项挑战基于Flow Free。可以在这里找到在线版本:http : //www.moh97.us/

您将得到一个谜题,1如果该谜题可以解决,0则必须返回。

为了解决难题,玩家必须创建一条路径,以使用每个空正方形恰好一次连接每对数字。

传递正方形的尺寸,然后传递每个点的x,y,c(其中c是代表颜色的数字)。例如:

如果5,5 0,0,0 3,0,1 1,1,2 1,2,2 4,2,1 4,4,0传递给您,则表示:

0..1.
.2...
.2..1
....0

并应返回1。


这里还有一些测试问题:

5,2 2,0,1 0,1,2 4,1,2 代表:

..1..
2...2

并且是不可解的,因为只有1 1

4,2 0,0,0 3,0,0 0,1,0 3,1,0 代表:

0..0
0..0

并且不可解决,因为它包含超过2 0s的时间。

8,6 0,0,1 7,5,1 代表:

1.......
........
........
........
........
.......1

并且无法解决(因为您不能使用每个正方形)。

2,5 0,0,1 2,0,6 4,0,6 0,1,4 3,1,4 4,1,1 代表:

1.6.6
4..41

由于无法连接1,因此无法解决。

6,3 1,0,4 5,0,1 0,1,4 1,1,3 5,1,3 0,2,2 3,2,2 5,2,1 代表:

.4...1
43...3
2..2.1

并且无法解决,因为您无法连接1(或3),因为两条路径必须交叉。

5,2 0,0,1 3,0,1 0,1,3 4,1,1 代表:

1..1.
3...3

并且无法解决,因为您无法在构建路径时使用所有正方形。

2,2 0,0,0 1,1,0 代表:

1.
.1

并且无法解决,因为您也无法在此处使用所有正方形

这是更多测试:

5,5 0,3,0 0,4,1 1,2,2 1,3,1 2,0,0 3,0,4 3,1,2 3,3,5 3,4,4 4,4,5 应该返回1

13,13 1,1,0 9,1,1 10,1,2 11,1,3 1,2,4 2,2,5 5,2,6 7,2,7 3,3,0 5,4,6 6,4,1 9,6,3 4,7,8 5,8,9 12,8,8 11,9,10 2,10,4 4,10,2 9,10,5 11,10,7 1,11,9 12,12,10 应该返回1

7,7 0,0,0 0,1,1 1,1,2 2,1,3 4,2,4 0,3,1 5,3,3 0,4,4 2,4,5 5,4,2 0,5,0 1,5,5 3,5,6 3,7,6 应该返回0


这是代码高尔夫球,适用标准规则。


2
解决方案必须是“现实”正确的还是理论上正确的?例如,状态空间可以分解为将6种可能的输入到输入配置之一分配给每个空单元格。通过尝试所有6 ^ N组合并返回1它们中的任何一个是否访问所有单元并连接所有终端的方法,可以轻松确定可解性。显然,除了最小的N(空单元数)以外,这种方法无法在合理的时间内完成,但是我们仍然在数学上保证算法最终将返回正确的值。
COTO 2014年

1
也许,如果您使用一种通用算法想出了两套巨大的游戏网格(一个用于测试,一个用于验证),并且认为获胜者是提交者,则可以正确地识别出某些游戏中专用网格中大多数网格的可解性。每个网格合理的时间量,如果两个提交的效用相同,则程序大小将成为决胜局。我一定会尽力的。
COTO 2014年

1
@NathanMerrill:这个问题可以通过SAT来解决,因此可以解决NP问题。
COTO 2014年

3
@NathanMerrill将问题简化为SAT意味着问题出在NP上,而不是NP难的问题–它将SAT简化为显示问题的NP难点的问题。您链接到的页面确实具有指向NP完整性证明的链接。
cardboard_box

1
@VisualMelon数字颜色是错误的单词。每种颜色用不同的数字表示,而不是数字。
内森·美林

Answers:


3

哈斯克尔

import Data.List.Split
import qualified Data.Sequence as Q
import Data.List
import Control.Monad

data A a = S a | E a | P a | X deriving Eq

sc = foldr1 (Q.><)
sp b x y p = Q.update y (Q.update x p $ b `Q.index` y) b
dt b c | S c `elem` sc b = E c
       | otherwise = S c
ad b [x, y, c] = sp b x y (dt b c)

ep b [x, y, c] = do
  let nps = filter ob [(x+1, y), (x-1, y), (x, y+1), (x, y-1)]
      ns = map gp nps
  [b | E c `elem` ns] ++ do
    (x', y') <- filter ((== X) . gp) nps
    ep (sp b x' y' (P c)) [x', y', c]
  where ob (u, v) = 0 <= u && u < length (b `Q.index` 0) && 0 <= v && v < length b
        gp (u, v) = b `Q.index` v `Q.index` u

rd i = let [c, r] : ps = (map read . splitOn ",") <$> words i :: [[Int]]
           e = Q.replicate r $ Q.replicate c X
           cs = map last ps
           ss = nubBy (\[_,_,c1] [_,_,c2] -> c1 == c2) ps
           b = foldl ad e ps
           bs = foldM ep b ss
       in if even (length cs) && length ss == length cs `div` 2 &&
             (all (\[j,k] -> j==k) . chunksOf 2 . sort $ cs) &&
             any (null . Q.elemIndicesL X . sc) bs
           then 1
           else 0

main = rd <$> getContents >>= print

  • SC:Seq Concat
  • sp:设置位置
  • dt:点类型(即行首或行尾)
  • 广告:加点
  • ep:延伸路径
  • rd:运行点(主要纯算法)

2
感谢您的提交,欢迎加入PPCG堆栈交换。这是一个代码挑战赛,这意味着目的是编写最短的程序来解决挑战。您处于领先地位,因为您有唯一的答案,但是您应该尝试尽可能缩短程序。
isaacg 2015年

老实说,您一直都回答了这个问题,这给我留下了深刻的印象。另外,这个问题更多是代码挑战,但我使用了代码高尔夫,因为很难得出不同的评分依据。
弥敦道·美林

是的,我不必太担心“高尔夫”方面。我正在尝试学习Haskell,这似乎是一个有趣的问题:-)
Matt
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.