Giải quyết một bảng 0h n0


19

0h n0 là một trò chơi rất đơn giản và thú vị, hơi giống Sudoku hoặc quét mìn.

Luật chơi

(Tôi khuyên bạn nên sử dụng hướng dẫn trong trò chơi nếu bạn có thể, nó rất đơn giản và hữu ích)

Câu đố bắt đầu với một n * nbảng chứa một số mảnh cố định và một số ô trống, và người giải phải tìm cách lấp đầy các ô trống bằng các mảnh và thỏa mãn tất cả các ràng buộc được áp đặt bởi các mảnh cố định. Dưới đây là các loại mảnh chúng tôi sẽ sử dụng với chữ viết tắt:

  • # Mảnh màu đỏ (khối xem của một mảnh màu xanh)
  • O Mảnh màu xanh
  • . Vị trí trống
  • numberSố màu xanh được đánh số ( numberlà số có một chữ số> 0)

Tất cả các mảnh được đánh số phải nhìn thấy chính xác cùng số lượng các mảnh màu xanh như số. Ví dụ:

#1O#O
...O.

Các 1mảnh chỉ có thể nhìn thấy một mảnh màu xanh khác.

Làm thế nào các mảnh nhìn thấy nhau

Hai mảnh màu xanh có thể nhìn thấy nhau nếu chúng ở cùng một hàng hoặc cột và không có mảnh màu đỏ nào nằm giữa chúng. Thí dụ:

( Slà một vị trí mà Omảnh có thể nhìn thấy, Xkhông thể nhìn thấy)

   S
   S
X#SOSS
   #
   X

Mỗi mảnh màu xanh phải nhìn thấy ít nhất một mảnh màu xanh khác:

#O#

Không làm việc, nhưng:

#OO

Hoặc là:

###

Làm việc.

Bảng demo giải quyết

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

Phía dưới bên phải 2 chỉ có thể nhìn thấy phía trên, vì vậy chúng phải có màu xanh và phía trên bên phải phải có màu đỏ.

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

Kể từ khi 1được lấp đầy, chúng ta có thể bao quanh nó với các mảnh màu đỏ.

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

Phía trên bên trái 1chỉ có thể nhìn theo một hướng bây giờ, vì vậy chúng tôi có thể điền vào.

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

Bây giờ về những 2s cuối cùng . Chúng ta có thể đặt 2 mảnh màu xanh lên trên chúng.

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

Cái cuối cùng sẽ được lấp đầy #

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

Đầu vào

Đầu vào là một chuỗi nhiều dòng. Kích thước sẽ 9x9không có dấu cách. Nó có các loại mảnh sau:

  • . Trống
  • # Đặt trước màu đỏ, không thể thay đổi
  • number Số cài đặt trước, không thể thay đổi

(Lưu ý rằng màu xanh sẽ không bao giờ có trong đầu vào)

Đầu ra

Đầu ra giống như đầu vào, với sự thay đổi mà trống ( .) được thay thế bằng màu đỏ hoặc màu xanh để giải bảng và các số được thay thế bằng các mảnh màu xanh ( O).

Ví dụ

(Lưu ý rằng có thể có nhiều giải pháp cho mỗi câu đố, nhưng bạn chỉ cần hiển thị một trong số chúng)

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

Cảm ơn @PeterTaylor@apsillers vì tất cả sự giúp đỡ của họ trong hộp cát!


Tôi chỉ thực hiện một chỉnh sửa rất nhỏ cho tiêu đề vì "an" nghe có vẻ tốt hơn nếu từ sau bắt đầu bằng nguyên âm - Tôi không mong người nói tiếng Anh không phải là người bản xứ hoặc thậm chí người bản ngữ bận tâm với nó, nhưng đó là ngữ pháp.
mèo

Câu trả lời:


2

Haskell, 224 byte

Chưa được kiểm tra đầy đủ, vì nó rất chậm (ít nhất 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

Giải trình:

Ý tưởng cơ bản là biểu diễn một bảng các Red, Bluemảnh như một danh sách các danh sách 0, 1, trong đó danh sách các danh sách được đóng gói thành một số nguyên duy nhất để liệt kê dễ dàng hơn. Tất cả các số nguyên như vậy cho kích thước bảng được tạo và chuyển đổi thành một hình thức với số lượng lân cận. Bảng đầu tiên như vậy là một giải pháp hợp lệ của đầu vào được trả lại.

-- 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

Phần có thể được đánh gôn nhất là : and.map and$zipWith(zipWith(%)). Mặt khác, tôi đã bắt gặp một vài lỗi do lỗi thêm chiều dài và có thể bị đánh gôn nhiều hơn.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.