Résoudre des puzzles Hitori

21

introduction

Écrivez un solveur pour les puzzles Hitori en utilisant le moins d'octets.

Défi

Votre tâche consiste à écrire un solveur pour les énigmes logiques Hitori (ひ と り, le mot pour «seul» en japonais; la signification du nom du jeu est «Laissez-moi tranquille»). Les règles sont les suivantes:

  • Vous êtes présenté avec une grille de cellules n par n, chaque cellule contient un entier compris entre 1 et n (inclus).
  • Votre objectif est de vous assurer qu'aucun numéro n'apparaît plus d'une fois dans chaque ligne et chaque colonne de la grille, en supprimant les numéros de la grille donnée, sous réserve de la restriction indiquée dans les deux règles suivantes,
  • Vous ne pouvez pas supprimer deux nombres de deux cellules adjacentes (horizontalement ou verticalement).
  • Les cellules numérotées restantes doivent toutes être connectées les unes aux autres. Cela signifie que deux cellules numérotées restantes peuvent être connectées avec une courbe composée uniquement de segments reliant les nombres restants adjacents (horizontalement ou verticalement). (Merci à @ user202729 d'avoir signalé que cela manquait)

J'espère que les règles sont claires maintenant. S'il n'y a rien de clair sur les règles, consultez la page Wikipedia .

Cas de test

Les cellules desquelles les nombres sont supprimés sont représentées par des 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 

Ces cas de test proviennent respectivement de Concept Is Puzzles , PuzzleBooks , Concept Is Puzzles , Wikipedia et Youtube .

Spécifications

  • Pas besoin de vous soucier de la gestion des exceptions.

  • Vous pouvez supposer que l'entrée est toujours un puzzle valide avec une solution unique et vous pouvez en profiter en écrivant votre code.

  • C'est le , le plus petit nombre d'octets gagne.

  • 4 <= n <= 9 (16 à l'origine, changé en 9 suivant la suggestion de Stewie Griffin, économise également quelques problèmes dans les E / S)

  • Vous pouvez prendre des entrées et fournir des sorties sous n'importe quelle forme standard , et vous êtes libre de choisir le format.

  • Certaines suggestions pour le format de sortie sont (mais vous n'êtes pas limité à celles-ci)

    • Sortie de la grille finale
    • Sortie de la grille contenant tous les numéros supprimés
    • Afficher une liste de coordonnées de l'un des éléments ci-dessus
  • Comme d'habitude, les failles par défaut s'appliquent ici.


Connexes (inspirées par ce défi): Vérifiez si tous les éléments d'une matrice sont connectés

Mon dernier défi: l' extension du Game of Sevens

Weijun Zhou
la source
2
Je suggère que vous ayez besoin d'une exécution déterministe ou que le plus grand cas de test puisse être résolu en moins d'une minute (ou peut-être plus / moins). Vous dites aussi 4 <= n <= 16, mais le plus grand cas de test est pour n=9. Je vous suggère soit de poster un n=16cas de test, soit de dire 4 <= n <= 9. Beau défi d'ailleurs :)
Stewie Griffin
1
@StewieGriffin que diriez-vous d'avoir juste un défi d'algorithme plus rapide séparé?
Jonathan Allan
@StewieGriffin J'ai essayé d'ajouter un 16x16 mais pas encore tout à fait prêt. Changé à 9 maintenant.
Weijun Zhou
@JonathanAllan Comme vous le souhaitez.
Weijun Zhou
Re "Je décide de faire un changement pour voir si ce serait mieux": Ce serait certainement pire. Vous ne devez pas non plus modifier un défi déjà publié.
user202729

Réponses:

3

Haskell , 374 octets

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

Essayez-le en ligne!

Roman Czyborra
la source
Merci. Très impressionnant. Personnellement, je suis un débutant mais aussi un grand fan de Haskell.
Weijun Zhou
tio.run/…
H.PWiz
1
Ce qui précède était trop de personnages trop laisser un commentaire à côté. Il suffit de supprimer des espaces
H.PWiz
2

APL (Dyalog Unicode) , 133 octets 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}

Essayez-le en ligne!

Mon implémentation de la règle # 4 (les cellules doivent former un seul composant connecté) est plutôt inutile, mais cela passe tous les tests en 10 secondes environ sur TIO.


L'algorithme global: stockez deux matrices booléennes bet wpour les cellules qui sont sûrement noires et blanches respectivement. Initialiser bcomme tout à zéro. Initialiser wà 1 uniquement pour les cellules qui ont des voisins correspondants opposés.

Répétez jusqu'à ce bque vous vous winstalliez:

  • ajouter aux bcellules qui sont sur la même ligne (horizontale ou verticale) et de la même valeur qu'une cellule dansw

  • ajouter aux wvoisins immédiats de toutes les cellulesb

  • ajouter à wtous les points de coupure - cellules dont la suppression diviserait le graphique des cellules non noires en plusieurs composants connectés

Enfin, sortie not(b)multipliée par la matrice d'origine.

ngn
la source
Merci beaucoup pour votre intérêt et vos explications. Je pense que ce que vous avez décrit est également un algorithme typique utilisé pour résoudre le puzzle à la main.
Weijun Zhou
1
Pour être honnête, je n'ai même jamais essayé de résoudre Hitori à la main. J'ai obtenu ces astuces de Wikipedia et je n'ai aucune preuve que l'algorithme convergerait toujours jusqu'à la solution (unique).
ngn
2

Gelée , 62 octets

Utilise le lien monadique isConnected de l'utilisateur202729 à partir d'une autre question.


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

Un programme complet imprimant une représentation d'une liste de listes.
Fonctionne par force brute et est stupidement inefficace.

Essayez-le en ligne! - un 3 par 3, car il est trop inefficace pour exécuter même une taille 4 dans la limite de 60 secondes TIO!

Comment?

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
la source
Comme un début. Merci. J'y jetterais un œil.
Weijun Zhou
Vous avez oublié la 4ème règle. (connecté)
user202729
(bonne chance avec l'implémentation de BFS / DFS / DSU dans Jelly)
user202729
Oh ... va supprimer quand sur un ordinateur. Merci.
Jonathan Allan
ouais, je ne pense pas que ce soit possible dans, disons, <60 octets de Jelly, pour ne pas dire <100 ...
Erik the Outgolfer