Rozwiązuj zagadki Hitori

21

Wprowadzenie

Napisz solver dla zagadek Hitori, używając najmniej bajtów.

Wyzwanie

Twoim zadaniem jest napisanie solvera dla logicznych łamigłówek Hitori (ひ と り, po japońsku słowo „sam”; znaczenie gry to „Zostaw mnie w spokoju”). Reguły są następujące:

  • Wyświetlana jest siatka komórek n-na-n, każda komórka zawiera liczbę całkowitą od 1 do n (włącznie).
  • Twoim celem jest upewnienie się, że żadna liczba nie pojawi się więcej niż raz w każdym rzędzie i każdej kolumnie siatki, poprzez usunięcie liczb z danej siatki, z zastrzeżeniem ograniczeń wskazanych w dwóch następnych regułach,
  • Nie można usunąć dwóch liczb z dwóch sąsiadujących (poziomo lub pionowo) komórek.
  • Pozostałe ponumerowane komórki muszą być ze sobą połączone. Oznacza to, że dowolne dwa pozostałe ponumerowane komórki można połączyć za pomocą krzywej złożonej wyłącznie z segmentów łączących sąsiednie pozostałe liczby (poziomo lub pionowo). (Podziękowania dla @ user202729 za wskazanie, że tego brakuje)

Mam nadzieję, że zasady są już jasne. Jeśli jest coś niejasnego w zasadach, sprawdź stronę na Wikipedii .

Przypadki testowe

Komórki, z których usuwane są liczby, są reprezentowane przez 0.

Input  ->  Output

4
2 2 2 4      0 2 0 4
1 4 2 3  ->  1 4 2 3
2 3 2 1      2 3 0 1
3 4 1 2      3 0 1 2

4
4 2 4 3      0 2 4 3
4 1 1 2  ->  4 1 0 2
3 1 2 1      3 0 2 1
4 3 1 3      0 3 1 0

5
1 5 3 1 2      1 5 3 0 2
5 4 1 3 4      5 0 1 3 4
3 4 3 1 5  ->  3 4 0 1 5
4 4 2 3 3      4 0 2 0 3
2 1 5 4 4      2 1 5 4 0

8
4 8 1 6 3 2 5 7      0 8 0 6 3 2 0 7
3 6 7 2 1 6 5 4      3 6 7 2 1 0 5 4
2 3 4 8 2 8 6 1      0 3 4 0 2 8 6 1
4 1 6 5 7 7 3 5  ->  4 1 0 5 7 0 3 0
7 2 3 1 8 5 1 2      7 0 3 0 8 5 1 2
3 5 6 7 3 1 8 4      0 5 6 7 0 1 8 0
6 4 2 3 5 4 7 8      6 0 2 3 5 4 7 8
8 7 1 4 2 3 5 6      8 7 1 4 0 3 0 6

9
8 6 5 6 8 1 2 2 9      8 0 5 6 0 1 2 0 9
5 6 2 4 1 7 9 8 3      5 6 2 4 1 7 9 8 3
5 8 2 5 9 9 8 2 6      0 8 0 5 0 9 0 2 0
9 5 6 6 4 3 8 4 1      9 5 6 0 4 3 8 0 1
1 1 6 3 9 9 5 6 2  ->  0 1 0 3 9 0 5 6 2
1 1 4 7 3 8 3 8 6      1 0 4 7 0 8 3 0 6
3 7 4 1 2 6 4 5 5      3 7 0 1 2 6 4 5 0
3 3 1 9 8 7 7 4 5      0 3 1 9 8 0 7 4 5
2 9 7 5 3 5 9 1 3      2 9 7 0 3 5 0 1 0 

Te przypadki testowe pochodzą odpowiednio z Concept Is Puzzles , PuzzleBooks , Concept Is Puzzles , Wikipedia i Youtube .

Okular

  • Nie musisz martwić się obsługą wyjątków.

  • Państwo może zakładać, że wejście jest zawsze ważna logiczna z unikalnego rozwiązania można skorzystać z tego w pisanie kodu.

  • To jest , najniższa liczba bajtów wygrywa.

  • 4 <= n <= 9 (16 pierwotnie zmieniono na 9 zgodnie z sugestią Stewie Griffin, również zaoszczędzić trochę problemów w IO)

  • Możesz pobierać dane wejściowe i dostarczać dane wyjściowe za pomocą dowolnego standardowego formularza i możesz wybrać format.

  • Niektóre sugestie dotyczące formatu wyjściowego są (ale nie jesteś do nich ograniczony)

    • Wyprowadzanie ostatecznej siatki
    • Wyprowadzanie siatki zawierającej wszystkie usunięte liczby
    • Wyprowadzić listę współrzędnych jednego z powyższych
  • Jak zwykle obowiązują tutaj domyślne luki .


Powiązane (zainspirowane tym wyzwaniem): Sprawdź, czy wszystkie elementy w macierzy są połączone

Moje ostatnie wyzwanie: rozszerzenie gry w siódemkę

Weijun Zhou
źródło
2
Sugeruję, że potrzebujesz deterministycznego środowiska uruchomieniowego lub wymagasz, aby największy przypadek testowy mógł zostać rozwiązany w nie więcej niż 1 minutę (a może więcej / mniej). Mówisz też 4 <= n <= 16, ale dla największego przypadku testowego n=9. Sugeruję, abyś albo opublikował n=16przypadek testowy, albo powiedz 4 <= n <= 9. Nawiasem mówiąc,
fajne
1
@StewieGriffin, co powiesz na oddzielne najszybsze wyzwanie algorytmowe?
Jonathan Allan
@StewieGriffin Próbowałem dodać 16 x 16, ale nie jest jeszcze całkiem gotowy. Teraz zmieniono na 9.
Weijun Zhou
@JathanathanAllan Jak sobie życzysz.
Weijun Zhou
Odp .: „Postanawiam dokonać zmiany, aby zobaczyć, czy byłoby lepiej”: Zdecydowanie byłoby gorzej. Nie powinieneś również zmieniać już opublikowanego wyzwania.
user202729

Odpowiedzi:

3

Haskell , 374 bajty

import Data.Array;import Data.List;r=range;p=partition
c(e,f)=p(\(b,p)->any(==1)[(b-d)^2+(p-q)^2|(d,q)<-e])f
n#g=[s|(o,(e:f))<-[p((==0).(g!))$indices g],
 null.fst$c(o,o),null.snd$until(null.fst)c([e],f),
 s<-case[((l,c),d)|((l,c),h)<-assocs g,h>0,
 d<-[filter((==h).(g!))$r((l,c+1),(l,n))++r((l+1,c),(n,c))],d/=[]]
 of[]->[g];((c,d):_)->n#(g//[(c,0)])++n#(g//[(c,0)|c<-d])]

Wypróbuj online!

Roman Czyborra
źródło
Dziękuję Ci. Bardzo imponujące. Osobiście jestem początkującym, ale także wielkim fanem Haskell.
Weijun Zhou
tio.run/…
H.PWiz
1
Powyżej było zbyt wiele znaków, więc zostaw komentarz. Po prostu usuwa trochę białych znaków
H.PWiz
2

APL (Dyalog Unicode) , 133 bajty SBCS

{q←{⊢/4 2⍴⍵}⌺3 3g←⍵=⊂∪,⍵⋄⍵×~1⊃{((⌈/q b)⌈b<{2<≢∪0,,(⍵×⊢⌈⌈/∘q)⍣≡⍵×(⍴⍵)⍴1+⍳≢,⍵}¨~b∘⌈¨⊂⍤2∘.≡⍨⍳⍴b)(+/↑w<g×⌈.⌈⍨w×g)⌈w b←⍵}⍣≡×\(⌈/=∘⌽⍨q⍵)0}

Wypróbuj online!

Moja implementacja reguły nr 4 (komórki muszą tworzyć pojedynczy podłączony komponent) jest raczej marnotrawstwem, ale nadal przechodzi wszystkie testy w około 10 sekund na TIO.


Ogólny algorytm: przechowuj dwie macierze boolowskie bi wkomórki, które z pewnością będą odpowiednio czarne i białe. Zainicjuj bjako zero. Zainicjuj wjako 1 tylko dla komórek, które mają sąsiadujących sąsiadujących ze sobą przeciwnie.

Powtarzaj do bi wustabilizuj:

  • dodaj do bkomórek, które znajdują się w tej samej linii (poziomej lub pionowej) i mają tę samą wartość, co komórkaw

  • dodać do wbezpośrednich sąsiadów wszystkich komórek wb

  • dodaj do wwszystkich punktów odcięcia - komórki, których usunięcie podzieliłoby wykres komórek innych niż czarne na wiele połączonych komponentów

Na koniec wynik not(b)pomnożony przez pierwotną macierz.

ngn
źródło
Dziękuję bardzo za zainteresowanie i wyjaśnienia. Myślę, że to, co opisałeś, jest również typowym algorytmem stosowanym do rozwiązywania zagadki ręcznie.
Weijun Zhou
1
Szczerze mówiąc, nigdy nawet nie próbowałem rozwiązać Hitori ręcznie. Mam te sztuczki z Wikipedii i nie mam dowodu na to, że algorytm zawsze będzie zbieżny aż do (unikalnego) rozwiązania.
ngn
2

Galaretka , 62 bajty

Korzysta z linku monadycznego isConnected użytkownika user202729 z innego pytania.


FJṁa@µ«Ḋoµ€ZUµ4¡ÐLFQL<3
ḟ0ĠḊ€
¬T€œ&2\;Ç€FȦ
ZÇȯÇ_1Ŀ
2ḶṗLṗLa⁸ÇÞḢ

Pełny program drukujący reprezentację listy list.
Działa brutalną siłą i jest głupio nieefektywna.

Wypróbuj online! - 3 na 3, ponieważ jest zbyt mało wydajny, aby uruchomić nawet rozmiar 4 w granicach 60 sekund TIO!

W jaki sposób?

FJṁa@µ«Ḋoµ€ZUµ4¡ÐLFQL<3 - Link 1 isConnected? List of lists
...                     - 1 if connected 0 if not -- see linked answer in the header

ḟ0ĠḊ€ - Link 2, helperFor-AnyRepeatedValues: list
ḟ0    - filter out zeros
  Ġ   - group indices by value (i.e. [[indices of min],...,[indices of max]]
   Ḋ€ - dequeue €ach -- leaving a list of empty lists iff no repeated values
      -                 any remaining values are non-zero (1-based indexing in Jelly)

¬T€œ&2\;Ç€FȦ - Link 3, columnwiseAnyAdjacentZerosOrRowwiseAnyRepeatedValues: list of lists
¬            - logical not (convert all zeros to ones and all others to zeros)
 T€          - for €ach row get a list of truthy indexes (i.e. indexes of original zeros)
     2\      - pairwise reduction (i.e. for neighbouring rows) with:
   œ&        -   intersection (empty if no columnwise adjacent original zeros
             -                 any remaining values are non-zero due to 1-based indexing)
        Ç€   - call last link (1) as a monad for €ach row
       ;     - concatenate
          F  - flatten into a single list (empty iff no columnwise adjacent original zeros
             -                                   AND no rowwise repeated values)
           Ȧ - any and all (0 if empty [or contains any zero -- never] else 1)

ZÇȯÇ_1Ŀ - Link 4, validity check? list of lists
Z       - transpose
 Ç      - call last link (2) as a monad rowwiseAnyAdjacentZerosOrColumnwiseAnyRepeatedValues?
   Ç    - call last link (2) as a monad columnwiseAnyAdjacentZerosOrRowwiseAnyRepeatedValues?
  ȯ     - logical OR
     1Ŀ - call link 1 as a monad (isConnected?)
    _   - subtract
        - this yields -1 for valid, while it yields 0 or 1 if not.

2ḶṗLṗLa⁸ÇÞḢ - Main link: list of lists
2Ḷ          - lowered range of 2 -> [0,1]
   L        - length (number of rows in the input)
  ṗ         - Cartesian power (all lists of zeros and ones of length L)
     L      - length (number of rows in the input again)
    ṗ       - Cartesian power (all grids of zeros and ones of same shape as the input)
       ⁸    - the input
      a     - logical AND -- effectively uses each of the formed grids as a mask
         Þ  - sort by:
        Ç   -   last link (3) as a monad
          Ḣ - head
            - implicit print
Jonathan Allan
źródło
NIce na początek. Dziękuję Ci. Spojrzę.
Weijun Zhou
Zapomniałeś czwartej zasady. (podłączony)
202729
(powodzenia w implementacji BFS / DFS / DSU w Jelly)
user202729 30.01.2018
Och ... usunie się, gdy będziesz na komputerze. Dzięki.
Jonathan Allan
tak, nie sądzę, że jest to możliwe, powiedzmy, <60 bajtów galaretki, nie mówiąc o <100 ...
Erik Outgolfer