Czy potrafisz połączyć kropki?

18

To wyzwanie jest oparte na Flow Free. Wersja online znajduje się tutaj: http://www.moh97.us/

Dostaniesz układankę i musisz wrócić, 1jeśli układanka jest rozwiązana lub 0nie.

Aby rozwiązać zagadkę, gracz musi utworzyć ścieżkę, aby połączyć każdą parę liczb za pomocą każdego pustego kwadratu dokładnie raz.

Przechodzisz do wymiarów kwadratu, a następnie x, y, c (gdzie c jest liczbą reprezentującą kolor) każdej kropki. Na przykład:

Gdyby 5,5 0,0,0 3,0,1 1,1,2 1,2,2 4,2,1 4,4,0został ci przekazany, reprezentowałby:

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

I powinien zwrócić 1.


Oto kilka innych problemów testowych:

5,2 2,0,1 0,1,2 4,1,2 reprezentuje:

..1..
2...2

i nie można go rozwiązać, ponieważ jest tylko 1 1.

4,2 0,0,0 3,0,0 0,1,0 3,1,0 reprezentuje:

0..0
0..0

i nie można go rozwiązać, ponieważ obejmuje więcej niż 2 0sekundy.

8,6 0,0,1 7,5,1 reprezentuje:

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

i nie jest do rozwiązania (ponieważ nie można użyć każdego kwadratu).

2,5 0,0,1 2,0,6 4,0,6 0,1,4 3,1,4 4,1,1 reprezentuje:

1.6.6
4..41

i nie można go rozwiązać, ponieważ nie można połączyć 1s.

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

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

i nie można go rozwiązać, ponieważ nie można połączyć 1 (lub 3), ponieważ dwie ścieżki muszą koniecznie się przeciąć.

5,2 0,0,1 3,0,1 0,1,3 4,1,1 reprezentuje:

1..1.
3...3

i nie można go rozwiązać, ponieważ nie można użyć wszystkich kwadratów do zbudowania ścieżki.

2,2 0,0,0 1,1,0 reprezentuje:

1.
.1

i nie można go rozwiązać, ponieważ nie można tutaj użyć wszystkich kwadratów

Oto kilka innych testów:

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 powinien zwrócić 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 powinien zwrócić 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 powinien zwrócić 0


To jest golf golfowy i obowiązują standardowe zasady.

Nathan Merrill
źródło
2
Czy rozwiązanie musi być „realistycznie” poprawne, czy tylko teoretycznie poprawne? Na przykład przestrzeń stanu można podzielić na przypisanie jednej z 6 możliwych konfiguracji wprowadzania danych wejściowych do każdej pustej komórki. Rozpuszczalność można łatwo ustalić, próbując wszystkich kombinacji 6 ^ N i zwracając, 1jeśli którakolwiek z nich odwiedzi wszystkie komórki i połączy wszystkie terminale. Oczywiście to podejście nie zakończy się w rozsądnym czasie dla niczego oprócz najmniejszej N(liczby pustych komórek), ale nadal mamy matematyczną gwarancję, że algorytm ostatecznie zwróci prawidłową wartość.
COTO,
1
Być może, jeśli opracowałeś dwa ogromne zestawy plansz do gry (jeden publiczny do testowania, drugi prywatny do weryfikacji) przy użyciu wspólnego algorytmu i uznałeś, że zwycięzcą jest zgłoszenie, które poprawnie określiło możliwość rozwiązania większości siatek w prywatnym zestawie w niektórych rozsądna ilość czasu na siatkę, z rozmiarem programu jako rozstrzygającym, jeśli dwa zgłoszenia miały taką samą użyteczność. Zdecydowanie spróbowałbym w tym swoich sił.
COTO
1
@NathanMerrill: Problem można zredukować do SAT, a zatem NP trudny.
COTO
3
@NathanMerrill redukując problem do SAT oznacza, że ​​problem dotyczy NP, a nie że jest trudny do NP - redukuje SAT do problemu, który pokazuje twardość NP do problemu. Strona, do której prowadzisz link, zawiera jednak link do dowodu kompletności NP.
cardboard_box
1
@VisualMelon Kolor cyfry to niewłaściwe słowo. Każdy kolor jest reprezentowany przez inną liczbę, a nie cyfrę.
Nathan Merrill

Odpowiedzi:

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

Klucz

  • sc: Seq concat
  • sp: ustaw pozycję
  • dt: typ kropki (tj. początek lub koniec linii)
  • ad: dodaj kropkę
  • ep: przedłużyć ścieżkę
  • rd: uruchom kropki (podstawowy czysty algorytm)
Matt
źródło
2
Dziękujemy za przesłanie i witamy na wymianie stosu PPCG. Jest to wyzwanie dla golfa kodowego, co oznacza, że ​​celem jest napisanie najkrótszego programu, który rozwiąże wyzwanie. Jesteś na prowadzeniu, ponieważ masz jedyną odpowiedź, ale powinieneś spróbować skrócić swój program tak bardzo, jak to możliwe.
isaacg
Jestem pod wrażeniem, że odpowiedziałeś na to pytanie po tak długim czasie. Ponadto ten problem był raczej wyzwaniem dla kodu, ale użyłem golfa, ponieważ trudno było wymyślić inną podstawę punktacji.
Nathan Merrill,
Tak, nie martwiłem się zbytnio aspektem „golfa”; Próbuję nauczyć się Haskell i wydaje mi się, że to zabawny problem :-)
Matt