Розв’яжіть дошку 0h n0


19

0h n0 - дуже проста і приємна гра, трохи схожа на судоку або тральщик.

Правила гри

(Я рекомендую використовувати підручник у грі, якщо можете, це дуже просто і корисно)

Головоломка починається з n * nдошки, яка містить деякі нерухомі шматки та кілька порожніх комірок, і розв’язувач повинен знайти спосіб заповнити порожні клітинки шматочками та задовольнити всі обмеження, накладені фіксованими шматочками. Ось типи штук, які ми будемо використовувати із абревіатурою:

  • # Червоний шматок (блокує вигляд синього шматка)
  • O Синій шматок
  • . Порожнє місце
  • numberПронумерований синій шматок ( numberце одноцифрове число> 0)

Усі пронумеровані шматки повинні бачити рівно стільки ж синіх шматочків, скільки і номер. Наприклад:

#1O#O
...O.

На 1творі видно лише один синій шматок.

Як шматки бачать один одного

Два сині шматки можуть бачити один одного, якщо вони знаходяться в одному рядку або стовпці, і жоден червоний шматок не знаходиться між ними. Приклад:

( Sце місце, яке Oможе бачити твір, 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

Тепер про останні останні 2s. Ми можемо покласти над ними 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 за всю їхню допомогу в пісочниці!


Я вніс лише незначну редакцію заголовка, тому що "а" звучить краще, якщо наступне слово починається з голосної - я не очікую, що немовці, які володіють англійською мовою, або навіть носіїв мови не турбуватимуться, але це граматично.
кіт

Відповіді:


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

Та частина , яка, ймовірно , може бути найбільш golfed є: and.map and$zipWith(zipWith(%)). В іншому випадку я виявив кілька помилок один за одним, що додало довжини, і, ймовірно, можна було б пограти більше.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.