Pouvez-vous relier les points?

18

Ce défi est basé sur Flow Free. Une version en ligne peut être trouvée ici: http://www.moh97.us/

Un puzzle vous sera remis et vous devrez revenir 1si le puzzle est résolu, ou0 non.

Pour résoudre un casse-tête, le joueur doit créer un chemin pour connecter chaque paire de nombres en utilisant chaque case vide exactement une fois.

Vous passez les dimensions du carré, puis les x, y, c (où c est un nombre représentant la couleur) de chaque point. Par exemple:

Si elle vous 5,5 0,0,0 3,0,1 1,1,2 1,2,2 4,2,1 4,4,0était transmise, elle représenterait:

0..1.
.2...
.2..1
....0

Et devrait retourner 1.


Voici quelques problèmes de test supplémentaires:

5,2 2,0,1 0,1,2 4,1,2 représente:

..1..
2...2

et n'est pas résoluble car il n'y en a qu'un 1.

4,2 0,0,0 3,0,0 0,1,0 3,1,0 représente:

0..0
0..0

et n'est pas résoluble car il comprend plus de 2 0s.

8,6 0,0,1 7,5,1 représente:

1.......
........
........
........
........
.......1

et n'est pas résoluble (car vous ne pouvez pas utiliser tous les carrés).

2,5 0,0,1 2,0,6 4,0,6 0,1,4 3,1,4 4,1,1 représente:

1.6.6
4..41

et n'est pas résoluble car vous ne pouvez pas connecter les 1.

6,3 1,0,4 5,0,1 0,1,4 1,1,3 5,1,3 0,2,2 3,2,2 5,2,1 représente:

.4...1
43...3
2..2.1

et n'est pas résoluble car vous ne pouvez pas connecter les 1 (ou les 3), car les deux chemins doivent nécessairement se croiser.

5,2 0,0,1 3,0,1 0,1,3 4,1,1 représente:

1..1.
3...3

et n'est pas résoluble car vous ne pouvez pas utiliser tous les carrés pour créer un chemin.

2,2 0,0,0 1,1,0 représente:

1.
.1

et n'est pas résoluble car vous ne pouvez pas utiliser tous les carrés ici non plus

Voici quelques tests supplémentaires:

5,5 0,3,0 0,4,1 1,2,2 1,3,1 2,0,0 3,0,4 3,1,2 3,3,5 3,4,4 4,4,5 devrait retourner 1

13,13 1,1,0 9,1,1 10,1,2 11,1,3 1,2,4 2,2,5 5,2,6 7,2,7 3,3,0 5,4,6 6,4,1 9,6,3 4,7,8 5,8,9 12,8,8 11,9,10 2,10,4 4,10,2 9,10,5 11,10,7 1,11,9 12,12,10 devrait retourner 1

7,7 0,0,0 0,1,1 1,1,2 2,1,3 4,2,4 0,3,1 5,3,3 0,4,4 2,4,5 5,4,2 0,5,0 1,5,5 3,5,6 3,7,6 devrait retourner 0


C'est un golf de code, et les règles standard s'appliquent.

Nathan Merrill
la source
2
Une solution doit-elle être "réaliste" correcte ou juste théoriquement correcte? Par exemple, l'espace d'état peut être décomposé en affectant l'une des 6 configurations d'entrée à entrée possibles à chaque cellule vide. La solvabilité est facilement déterminée en essayant toutes les combinaisons 6 ^ N et en retournant 1si l'une d'entre elles visite toutes les cellules et connecte tous les terminaux. De toute évidence, cette approche ne serait pas terminée dans un délai raisonnable pour autre chose que la plus petite N(nombre de cellules vides), mais nous avons toujours une garantie mathématique que l'algorithme retournerait finalement la valeur correcte.
COTO
1
Peut-être que si vous proposiez deux énormes ensembles de grilles de jeu (un public pour les tests, un privé pour la validation) en utilisant un algorithme commun et que le gagnant était la soumission qui avait correctement identifié la solvabilité de la plupart des grilles de l'ensemble privé dans certains durée raisonnable par grille, avec une taille de programme comme bris d'égalité si deux soumissions avaient une utilité égale. J'essaierais certainement de faire ça.
COTO
1
@NathanMerrill: Le problème est réductible à SAT et donc à NP difficile.
COTO
3
@NathanMerrill réduire un problème à SAT signifie que le problème est en NP, pas qu'il soit NP-difficile - il réduit SAT à un problème qui montre la dureté NP du problème. La page à laquelle vous avez lié a un lien vers une preuve d'exhaustivité de NP.
cardboard_box
1
@VisualMelon Digit color n'est pas le bon mot. Chaque couleur est représentée par un nombre différent, pas un chiffre.
Nathan Merrill

Réponses:

3

Haskell

import Data.List.Split
import qualified Data.Sequence as Q
import Data.List
import Control.Monad

data A a = S a | E a | P a | X deriving Eq

sc = foldr1 (Q.><)
sp b x y p = Q.update y (Q.update x p $ b `Q.index` y) b
dt b c | S c `elem` sc b = E c
       | otherwise = S c
ad b [x, y, c] = sp b x y (dt b c)

ep b [x, y, c] = do
  let nps = filter ob [(x+1, y), (x-1, y), (x, y+1), (x, y-1)]
      ns = map gp nps
  [b | E c `elem` ns] ++ do
    (x', y') <- filter ((== X) . gp) nps
    ep (sp b x' y' (P c)) [x', y', c]
  where ob (u, v) = 0 <= u && u < length (b `Q.index` 0) && 0 <= v && v < length b
        gp (u, v) = b `Q.index` v `Q.index` u

rd i = let [c, r] : ps = (map read . splitOn ",") <$> words i :: [[Int]]
           e = Q.replicate r $ Q.replicate c X
           cs = map last ps
           ss = nubBy (\[_,_,c1] [_,_,c2] -> c1 == c2) ps
           b = foldl ad e ps
           bs = foldM ep b ss
       in if even (length cs) && length ss == length cs `div` 2 &&
             (all (\[j,k] -> j==k) . chunksOf 2 . sort $ cs) &&
             any (null . Q.elemIndicesL X . sc) bs
           then 1
           else 0

main = rd <$> getContents >>= print

Clé

  • sc: Seq concat
  • sp: position définie
  • dt: type de point (c'est-à-dire début ou fin de ligne)
  • annonce: ajouter un point
  • ep: étendre le chemin
  • rd: exécuter des points (algorithme pur primaire)
Mat
la source
2
Merci pour la soumission et bienvenue à l'échange de pile PPCG. Il s'agit d'un défi de golf de code, ce qui signifie que le but est d'écrire le programme le plus court qui résout le défi. Vous êtes en tête, car vous avez la seule réponse, mais vous devriez essayer de raccourcir votre programme autant que possible.
isaacg
Je suis honnêtement impressionné que vous ayez répondu à cette question après tout ce temps. De plus, ce problème était plus un défi de code, mais j'ai utilisé le code-golf, car il était difficile de trouver une base de notation différente.
Nathan Merrill
Oui, je ne me suis pas trop inquiété de l'aspect "golf"; J'essaie d'apprendre Haskell et cela m'a semblé être un problème amusant :-)
Matt