Résoudre une carte 0h n0


19

0h n0 est un jeu très simple et agréable, un peu comme Sudoku ou dragueur de mines.

Regles du jeu

(Je recommande d'utiliser le tutoriel dans le jeu si vous le pouvez, c'est très simple et utile)

Le casse-tête commence par un n * ntableau contenant des pièces fixes et des cellules vides, et le solveur doit trouver un moyen de remplir les cellules vides de pièces et de satisfaire toutes les contraintes imposées par les pièces fixes. Voici les types de pièces que nous utiliserons avec l'abréviation:

  • # Pièce rouge (bloque la vue d'une pièce bleue)
  • O Pièce bleue
  • . Emplacement vide
  • numberPièce bleue numérotée ( numberest un nombre à un chiffre> 0)

Toutes les pièces numérotées doivent voir exactement la même quantité de pièces bleues que le nombre. Par exemple:

#1O#O
...O.

La 1pièce ne peut voir qu'une seule autre pièce bleue.

Comment les pièces se voient

Deux pièces bleues peuvent se voir si elles sont dans la même ligne ou colonne et qu'aucune pièce rouge ne se trouve entre elles. Exemple:

( Sest un endroit que la Opièce peut voir, Xne peut pas être vu)

   S
   S
X#SOSS
   #
   X

Chaque pièce bleue doit voir au moins une autre pièce bleue:

#O#

Ne fonctionnera pas, mais:

#OO

Ou:

###

Faire du travail.

Tableau de démonstration résoudre

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

Le coin inférieur droit 2 ne peut se voir qu'au-dessus de lui-même, ils doivent donc être bleus et le coin supérieur droit doit être rouge.

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

Puisque le 1est rempli, nous pouvons l'entourer de morceaux rouges.

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

Le coin supérieur gauche 1ne peut désormais voir que dans une seule direction, nous pouvons donc le remplir.

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

Maintenant sur ces derniers 2s. Nous pouvons mettre 2 pièces bleues dessus.

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

Le dernier sera rempli de #

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

Contribution

L'entrée est une chaîne de plusieurs lignes. La taille sera 9x9sans espace de fuite. Il a les types de pièces suivants:

  • . Vide
  • # Rouge prédéfini, ne peut pas être modifié
  • number Numéro prédéfini, ne peut pas être modifié

(Notez que le bleu ne sera jamais dans l'entrée)

Production

La sortie est la même que l'entrée, avec le changement que empty ( .) est remplacé par un rouge ou un bleu pour résoudre le tableau, et les nombres sont remplacés par des pièces bleues ( O).

Exemples

(Notez que plusieurs solutions peuvent être possibles pour chaque puzzle, mais il vous suffit d'en montrer une)

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

Merci à @PeterTaylor et @apsillers pour toute leur aide dans le bac à sable!


J'ai juste apporté une modification mineure au titre parce que "un" sonne mieux si le mot suivant commence par une voyelle - je ne m'attends pas à ce que des anglophones non natifs ou même des locuteurs natifs s'en soucient, mais c'est grammatical.
chat

Réponses:


2

Haskell, 224 octets

Pas entièrement testé, car il est si lent (au moins 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

Explication:

L'idée de base est de représenter un tableau de Red, Bluepièces sous la forme d'une liste de listes 0, 1, où la liste de listes est regroupée dans un seul entier pour une énumération plus facile. Tous ces entiers pour la taille de la carte sont générés et convertis en une forme avec des nombres de voisins. La première carte de ce type qui est une solution valide de l'entrée est renvoyée.

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

La partie qui pourrait probablement être plus golfed est: and.map and$zipWith(zipWith(%)). Sinon, j'ai attrapé quelques erreurs ponctuelles qui ont ajouté de la longueur et pourraient probablement être jouées davantage.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.