0h n0ボードを解く


19

0h n0は非常にシンプルで楽しいゲームで、数独や掃海艇に少し似ています。

ゲームのルール

(可能であれば、ゲームでチュートリアルを使用することをお勧めします。非常にシンプルで便利です)

パズルは、n * nいくつかの固定ピースといくつかの空のセルを含むボードから始まります。ソルバーは、空のセルをピースで満たし、固定ピースによって課せられるすべての制約を満たす方法を見つけなければなりません。略語で使用するピースのタイプは次のとおりです。

  • # 赤い部分(青い部分のブロックビュー)
  • O ブルーピース
  • . 空の場所
  • number番号付きの青い部分(number1桁以上の数字です)

番号付きのすべてのピースには、番号とまったく同じ量の青いピースが表示される必要があります。例えば:

#1O#O
...O.

1作品は一つだけ、他の青の部分を見ることができます。

ピース同士の見方

2つの青い部分が同じ行または列にあり、それらの間に赤い部分がない場合、互いに見えます。例:

(作品が見ることができる、見ることができないS場所です)OX

   S
   S
X#SOSS
   #
   X

各青いピースには、少なくとも1つの他の青いピースが表示される必要があります。

#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)に置き換えられます。

(各パズルに対して複数の解決策が可能ですが、そのうちの1つを表示するだけでよいことに注意してください)

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」の方が音が良くなるため、タイトルを非常にマイナーに編集しました。英語を母国語としない人、さらには母国語の話者がそれを気にすることはないでしょうが、文法的にはそうです。

回答:


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(%))です。そうでなければ、長さを追加し、おそらくより多くのゴ​​ルフをすることができるいくつかのオフバイワンのエラーを見つけました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.