解决0h n0板


19

0h n0是一个非常简单且有趣的游戏,有点像Sudoku或minesweeper。

游戏规则

(如果可以的话,我建议您在游戏中使用该教程,它非常简单实用)

难题始于n * n一块包含一些固定零件和一些空单元的木板,求解器必须找到一种方法来用零件填充空单元并满足固定零件所施加的所有约束。以下是我们将使用缩写的作品类型:

  • # 红色部分(阻止显示蓝色部分)
  • O 蓝片
  • . 空位置
  • number编号为蓝色的部分(number是一位数字> 0)

所有编号的块都必须看到与数字完全相同的蓝色块。例如:

#1O#O
...O.

1作品只能看到另一个蓝色作品。

作品如何彼此见面

如果两个蓝色块位于同一行或同一列中,并且它们之间没有红色块,则它们可以彼此看到。例:

SO一块可以看到,X无法看到的位置)

   S
   S
X#SOSS
   #
   X

每个蓝色部分必须至少看到另一个蓝色部分:

#O#

无法正常工作,但是:

#OO

要么:

###

做工作。

演示板解决

.1..
..1.
....
22#2

右下2只能在自身上方看到,因此它们必须为蓝色,右上角必须为红色。

.1.#
..1O
...O
22#2

既然1已填充,我们就可以用红色块包围它。

.1##
.#1O
..#O
22#2

左上角1现在只能看到一个方向,因此我们可以填写它。

O1##
.#1O
..#O
22#2

现在关于那些最后2的。我们可以在上面放2个蓝色的碎片。

O1##
.#1O
OO#O
22#2

最后一个将充满 #

O1##
##1O
OO#O
22#2

输入项

输入是多行字符串。大小将9x9没有尾随空格。它具有以下片段类型:

  • . 空的
  • # 预设红色,无法更改
  • number 预设号码,无法更改

(请注意,蓝色永远不会出现在输入中)

输出量

输出与输入相同,只是将空(.)替换为红色或蓝色以解决电路板,并将数字替换为蓝色的块(O)进行了更改。

例子

(请注意,每个难题可能有多种解决方案,但您只需要显示其中一个即可)

Input:
........4
...3.1...
45...2.3.
..9......
1..6#44..
....4..5.
....4.36.
2.......6
1....4...

Output:
OOO###OOO
OOOO#O#OO
OOO#OO#OO
#OOOO#O##
O#OO#OOOO
O#OOOO#OO
#OOOO#OOO
OO#O#OOOO
O#OOOO#O#

Input:
..7..#...
#...8..11
2....5...
..5...48.
...#...4.
.5...6...
...1.2...
2.....6.8
.7..#....

Output:
OOOOO####
##OOOO#OO
O#OOOO###
OOO#OOOOO
OO##O##O#
#O##OOOOO
#O#O#O#OO
OO#OOOOOO
OOO###O#O

Input:
5.3..33..
...4...23
.6.6.34..
...3#....
....5..4.
.5....3..
7.98.6#.3
.5.6..2..
..6...2..

Output:
OOOOO####
##OOOO#OO
O#OOOO###
OOO#OOOOO
OO##O##O#
#O##OOOOO
#O#O#O#OO
OO#OOOOOO
OOO###O#O

感谢@PeterTaylor@apsillers在沙盒中的所有帮助!


我对标题进行了很小的修改,因为如果以下单词以元音开头,则“ an”听起来会更好-我不希望非英语母语者甚至母语人士都为之烦恼,但这是语法上的。

Answers:


2

Haskell,224个字节

没有经过充分测试,因为它是如此缓慢(至少O(n*2^n^2))。

t=1<2
x!p|p<0=0|t=mod(div x$2^p)2
l#x=[[sum$map(p&)[-1,1,l+1,-l-1]|p<-[q..q+l]]|q<-[0,l..l*l],let i&v|x!i<1=0|t=x!(i+v)+(i+v)&v]
b%v|b<1=t|t=b==v
s b|l<-length b-1=[l#x|x<-[0..2^l^2],and.map and$zipWith(zipWith(%))b(l#x)]!!0

说明:

基本思想是将一块Red, Blue棋子表示为的列表列表0, 1,其中列表列表打包为单个整数,以便于枚举。生成所有这样的板尺寸整数,并将其转换为具有邻居计数的形式。返回第一个这样的板,它是输入的有效解决方案。

-- integer x at position p with out of bounds defined to be 0 (so no bounds checking)
(!) :: (Integral b, Integral r) => r -> b -> r
x ! p | p < 0     = 0 
      | otherwise = mod (div x (2^p)) 2


-- Sum of values from position p along vector v (x is implicit)
-- Note that a cartesian vector (x,y) in this representation is (l*x + y)
(&) :: (Integral a, Integral b) => b -> b -> a
p & v | x ! p == 0 = 0
      | otherwise  = x ! (p+v)  +  (p+v) & v


-- Value of board at position p (implicit x, l)
value :: Integral a => a -> a
value p = sum $ map (p&) [-1, 1, l+1, -l-1]


-- Integer to board, where l is length, x is input integer
(#) :: (Integral t, Integral a) => a -> t -> [[t]]
l # x = [[sum $ map (p&) [-1,1,l+1,-l-1] | p <- [q..q+l-1]] | q <- [0,l..l*l]]


-- Comparison operator, to see whether a solved board is a solution of the input
(%) :: (Num a, Ord a) => a -> a -> Bool
b % v | b == 0    = True
      | otherwise = b == v


-- Check one possible solution
check :: Integral a => [[a]] -> Int -> [[a]] -> Bool
check b l x = (and . (map and)) zipWith(zipWith (%)) b (l # x)

-- Solver
solve :: Integral t => [[t]] -> [[t]]
solve b = [l # x | x <- [0..2^l^2], check b l x]
  where
    l = length b

最可能打高尔夫球的部分是:and.map and$zipWith(zipWith(%))。否则,我会遇到一些错误,这些错误会增加长度,并且可能会打得更多。

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.