Bisakah Anda menghubungkan titik-titik?

18

Tantangan ini didasarkan pada Flow Free. Versi online dapat ditemukan di sini: http://www.moh97.us/

Anda akan diberikan puzzle, dan Anda harus kembali 1jika puzzle itu dapat dipecahkan, atau 0jika tidak.

Untuk memecahkan teka-teki, pemain harus membuat jalur untuk menghubungkan setiap pasangan angka menggunakan setiap kotak kosong tepat satu kali.

Anda dimasukkan dalam dimensi kotak, dan kemudian x, y, c (di mana c adalah angka yang mewakili warna) dari setiap titik. Sebagai contoh:

Jika 5,5 0,0,0 3,0,1 1,1,2 1,2,2 4,2,1 4,4,0diteruskan kepada Anda, itu akan mewakili:

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

Dan harus mengembalikan 1.


Berikut adalah beberapa masalah tes lagi:

5,2 2,0,1 0,1,2 4,1,2 mewakili:

..1..
2...2

dan tidak bisa dipecahkan karena hanya ada 1 1.

4,2 0,0,0 3,0,0 0,1,0 3,1,0 mewakili:

0..0
0..0

dan tidak dapat dipecahkan karena mencakup lebih dari 2 0detik.

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

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

dan tidak dapat dipecahkan (karena Anda tidak dapat menggunakan setiap kotak).

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

1.6.6
4..41

dan tidak dapat dipecahkan karena Anda tidak dapat menghubungkan 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 mewakili:

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

dan tidak dapat dipecahkan karena Anda tidak dapat menghubungkan 1s (atau 3s), karena kedua jalur harus saling bersilangan.

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

1..1.
3...3

dan tidak dapat dipecahkan karena Anda tidak dapat menggunakan semua kotak dalam membangun jalur.

2,2 0,0,0 1,1,0 mewakili:

1.
.1

dan tidak dapat dipecahkan karena Anda tidak dapat menggunakan semua kotak di sini juga

Berikut ini beberapa tes lagi:

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 harus mengembalikan 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 harus mengembalikan 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 harus mengembalikan 0


Ini adalah kode golf, dan aturan standar berlaku.

Nathan Merrill
sumber
2
Apakah solusi harus "secara realistis" benar atau hanya secara teoritis benar? Sebagai contoh, ruang keadaan dapat dipecah menjadi menetapkan satu dari 6 konfigurasi input-ke-input yang mungkin untuk setiap sel kosong. Solvabilitas mudah ditentukan dengan mencoba semua kombinasi 6 ^ N dan kembali 1jika salah satu dari mereka mengunjungi semua sel dan menghubungkan semua terminal. Jelas pendekatan ini tidak akan menyelesaikan dalam jumlah waktu yang wajar untuk apa pun kecuali yang terkecil N(jumlah sel kosong), tetapi kami masih memiliki jaminan matematis bahwa algoritma pada akhirnya akan mengembalikan nilai yang benar.
COTO
1
Mungkin jika Anda datang dengan dua set grid permainan besar (satu publik untuk pengujian, satu pribadi untuk validasi) menggunakan algoritma umum dan menganggap pemenangnya adalah kiriman yang mengidentifikasi dengan benar solvabilitas grid paling banyak dalam set privat di beberapa jumlah waktu yang wajar per kisi, dengan ukuran program sebagai tiebreak jika dua kiriman memiliki utilitas yang sama. Saya pasti akan mencoba tangan saya pada saat itu.
COTO
1
@NathanMerrill: Masalahnya dapat direduksi menjadi SAT dan karenanya NP sulit.
COTO
3
@NathanMerrill mengurangi masalah menjadi SAT berarti masalahnya ada di NP, bukan NP-hard - itu mengurangi SAT menjadi masalah yang menunjukkan NP-hardness masalah. Namun, halaman yang Anda tautkan memiliki tautan ke bukti kelengkapan NP.
cardboard_box
1
@VisualMelon Digit warna adalah kata yang salah. Setiap warna diwakili oleh angka yang berbeda, bukan digit.
Nathan Merrill

Jawaban:

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

Kunci

  • sc: Seq concat
  • sp: atur posisi
  • dt: jenis titik (yaitu, mulai atau akhir baris)
  • iklan: tambahkan dot
  • ep: perpanjang jalur
  • rd: run dots (algoritma murni primer)
Mat
sumber
2
Terima kasih atas kirimannya, dan selamat datang di pertukaran tumpukan PPCG. Ini adalah tantangan kode golf, artinya tujuannya adalah untuk menulis program terpendek yang menyelesaikan tantangan. Anda yang memimpin, karena Anda memiliki satu-satunya jawaban, tetapi Anda harus berusaha mempersingkat program Anda sebanyak mungkin.
isaacg
Saya benar-benar terkesan bahwa Anda menjawab pertanyaan ini setelah sekian lama. Juga, masalah ini lebih merupakan tantangan kode, tetapi saya menggunakan golf kode, karena sulit untuk menghasilkan basis penilaian yang berbeda.
Nathan Merrill
Ya, saya tidak terlalu khawatir tentang aspek "golf"; Saya mencoba mempelajari Haskell dan sepertinya ini masalah yang menyenangkan :-)
Matt