Il est temps de se lancer dans une quête périlleuse pour vaincre le renseignement britannique. Le but de ce défi est d'écrire le code le plus court qui résoudra un nonogramme.
Qu'est-ce qu'un nonogramme?
Les règles sont simples. Vous avez une grille de carrés qui doivent être remplis en noir ou laissés en blanc. À côté de chaque ligne de la grille sont répertoriées les longueurs des séries de carrés noirs sur cette ligne. Au-dessus de chaque colonne sont répertoriées les longueurs des séries de carrés noirs dans cette colonne. Votre objectif est de trouver tous les carrés noirs. Dans ce type de casse-tête, les nombres sont une forme de tomographie discrète qui mesure le nombre de lignes ininterrompues de carrés remplis dans une ligne ou une colonne donnée. Par exemple, un indice de "4 8 3" signifierait qu'il y a des ensembles de quatre, huit et trois carrés remplis, dans cet ordre, avec au moins un carré vide entre les groupes successifs. [ 1 ] [ 2 ]
La solution au nonogramme ci-dessus serait donc:
Détails d'implémentation
Vous pouvez choisir de représenter le Nonogramme comme vous le souhaitez et de le prendre comme entrée de la manière que vous jugerez appropriée pour votre langue. Il en va de même pour la sortie. Le but de ce défi est littéralement de simplement faire le travail; si vous pouvez résoudre le non-programme avec n'importe quelle sortie de votre programme, c'est valable. Une mise en garde est que vous ne pouvez pas utiliser un solveur en ligne :)
Ce problème est très complexe sur le plan algorithmique (np-complet) en ce qu'il n'y a pas de solution complètement efficace et en tant que tel, vous ne serez pas pénalisé pour ne pas pouvoir en résoudre de plus grandes, bien que votre réponse sera fortement récompensée si elle est capable de gérer de gros cas (voir bonus). En tant que référence, ma solution fonctionne jusqu'à environ 25x25 en 5 à 10 secondes. Pour permettre la flexibilité entre les différentes langues, les solutions qui prennent moins de 5 minutes pour un nonogramme 25x25 sont assez bonnes.
Vous pouvez supposer un puzzle dans toujours un nonogramme NxN carré.
Vous pouvez utiliser ce fabricant de puzzles en ligne sans programme pour tester vos solutions.
Notation
Bien sûr, vous êtes libre d'utiliser la langue de votre choix et comme il s'agit de code golf, les entrées seront triées dans l'ordre: accuracy -> length of code -> speed.
Cependant, ne vous découragez pas par les langues de golf de code, les réponses dans toutes les langues qui montrent des tentatives de golf d'une manière intéressante sera voté!
Prime
J'ai en fait entendu parler des Nonograms grâce à une carte de Noël cryptographique publiée par le British Intelligence ici . La première partie était essentiellement un nonogramme massif de 25x25. Si votre solution est capable de résoudre ce problème, vous obtiendrez des félicitations :)
Pour vous faciliter la vie en termes de saisie de données, j'ai fourni comment j'ai représenté les données de ce puzzle spécifique pour votre utilisation gratuite. Les 25 premières lignes sont les indices de ligne, suivis d'une ligne de séparation `` - '', suivis de 25 lignes des indices de colonne, suivis d'une ligne de séparation `` # '', puis d'une représentation de la grille avec les indices carrés remplis.
7 3 1 1 7
1 1 2 2 1 1
1 3 1 3 1 1 3 1
1 3 1 1 6 1 3 1
1 3 1 5 2 1 3 1
1 1 2 1 1
7 1 1 1 1 1 7
3 3
1 2 3 1 1 3 1 1 2
1 1 3 2 1 1
4 1 4 2 1 2
1 1 1 1 1 4 1 3
2 1 1 1 2 5
3 2 2 6 3 1
1 9 1 1 2 1
2 1 2 2 3 1
3 1 1 1 1 5 1
1 2 2 5
7 1 2 1 1 1 3
1 1 2 1 2 2 1
1 3 1 4 5 1
1 3 1 3 10 2
1 3 1 1 6 6
1 1 2 1 1 2
7 2 1 2 5
-
7 2 1 1 7
1 1 2 2 1 1
1 3 1 3 1 3 1 3 1
1 3 1 1 5 1 3 1
1 3 1 1 4 1 3 1
1 1 1 2 1 1
7 1 1 1 1 1 7
1 1 3
2 1 2 1 8 2 1
2 2 1 2 1 1 1 2
1 7 3 2 1
1 2 3 1 1 1 1 1
4 1 1 2 6
3 3 1 1 1 3 1
1 2 5 2 2
2 2 1 1 1 1 1 2 1
1 3 3 2 1 8 1
6 2 1
7 1 4 1 1 3
1 1 1 1 4
1 3 1 3 7 1
1 3 1 1 1 2 1 1 4
1 3 1 4 3 3
1 1 2 2 2 6 1
7 1 3 2 1 1
#
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 1 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 0 0 0 0 1 1 0 0 0 0 1 0 0 0 0 1 1 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
Et voici une version légèrement différente pour votre commodité; un tuple séparé par des virgules (ligne, col) où chaque élément est une liste de listes.
([[7, 3, 1, 1, 7],
[1, 1, 2, 2, 1, 1],
[1, 3, 1, 3, 1, 1, 3, 1],
[1, 3, 1, 1, 6, 1, 3, 1],
[1, 3, 1, 5, 2, 1, 3, 1],
[1, 1, 2, 1, 1],
[7, 1, 1, 1, 1, 1, 7],
[3, 3],
[1, 2, 3, 1, 1, 3, 1, 1, 2],
[1, 1, 3, 2, 1, 1],
[4, 1, 4, 2, 1, 2],
[1, 1, 1, 1, 1, 4, 1, 3],
[2, 1, 1, 1, 2, 5],
[3, 2, 2, 6, 3, 1],
[1, 9, 1, 1, 2, 1],
[2, 1, 2, 2, 3, 1],
[3, 1, 1, 1, 1, 5, 1],
[1, 2, 2, 5],
[7, 1, 2, 1, 1, 1, 3],
[1, 1, 2, 1, 2, 2, 1],
[1, 3, 1, 4, 5, 1],
[1, 3, 1, 3, 10, 2],
[1, 3, 1, 1, 6, 6],
[1, 1, 2, 1, 1, 2],
[7, 2, 1, 2, 5]],
[[7, 2, 1, 1, 7],
[1, 1, 2, 2, 1, 1],
[1, 3, 1, 3, 1, 3, 1, 3, 1],
[1, 3, 1, 1, 5, 1, 3, 1],
[1, 3, 1, 1, 4, 1, 3, 1],
[1, 1, 1, 2, 1, 1],
[7, 1, 1, 1, 1, 1, 7],
[1, 1, 3],
[2, 1, 2, 1, 8, 2, 1],
[2, 2, 1, 2, 1, 1, 1, 2],
[1, 7, 3, 2, 1],
[1, 2, 3, 1, 1, 1, 1, 1],
[4, 1, 1, 2, 6],
[3, 3, 1, 1, 1, 3, 1],
[1, 2, 5, 2, 2],
[2, 2, 1, 1, 1, 1, 1, 2, 1],
[1, 3, 3, 2, 1, 8, 1],
[6, 2, 1],
[7, 1, 4, 1, 1, 3],
[1, 1, 1, 1, 4],
[1, 3, 1, 3, 7, 1],
[1, 3, 1, 1, 1, 2, 1, 1, 4],
[1, 3, 1, 4, 3, 3],
[1, 1, 2, 2, 2, 6, 1],
[7, 1, 3, 2, 1, 1]])
la source
s=[].fill([].fill(0,0,25),0,25);s[3][3]=s[3][4]=s3[3][12]=s3[3][13]=s3[3][21]=s[8][6]=s[8][7]=s[8][10]=s[8][14]=s[8][15]=s[8][18]=s[16][6]=s[16][11]=s[16][16]=s[16][20]=s[21][3]=s[21][4]=s[21][9]=s[21][10]=s[21][15]=s[21][20]=s[21][21]=1;
Réponses:
Brachylog ,
7069 octetsCela prend une liste de deux listes (d'abord les indicateurs de lignes, puis ceux de colonne). Chaque indicateur est lui-même une liste (pour les situations comme
[3,1]
sur une ligne).Cette version prend environ 3 minutes pour résoudre l'exemple 5 par 5 du défi.
Version beaucoup plus efficace, 91 octets
Essayez-le en ligne!
Celui-ci n'est pas une force brute complète: la seule différence est que celui-ci impose des contraintes sur les valeurs des cellules de sorte que le nombre de 1 dans chaque ligne et colonne corresponde aux nombres donnés comme indicateurs en entrée. La seule partie de force brute est alors de trouver la grille unique avec les contraintes pour lesquelles les "blocs" de 1 correspondent à ce qui est donné à titre indicatif.
Celui-ci prend environ 0,05 seconde sur l'exemple 5 par 5 du défi. C'est encore beaucoup trop lent pour le cas bonus, car je ne sais pas comment exprimer les blocs de ceux séparés par un ou plusieurs zéros en termes de contraintes.
Explication
J'expliquerai ci-dessous la version 93 octets. La seule différence entre les deux est l'appel au prédicat 3 qui n'existe pas dans la version 70 octets, et la numérotation des prédicats (car il y en a un de moins).
Prédicat principal:
Prédicat 1: force les lignes à avoir une longueur spécifique et à ce que chaque cellule soit 0 ou 1.
Prédicat 2: contraindre une variable à 0 ou 1
Prédicat 3: La somme de 1 dans une liste doit être égale à la somme des indicateurs (par exemple, si l'indicateur est [3: 1] alors la liste doit avoir la somme 4)
Prédicat 4: Vérifiez que les blocs de 1 correspondent à l'indicateur
Prédicat 5: Vrai pour les blocs de 1, faux sinon
la source
Haskell,
242 230 201 199 177 177 163 160 149131 octetsEnfin moins de 200 octets, crédit à @Bergi. Un grand merci à @nimi pour avoir aidé à réduire de moitié la taille.
Sensationnel. Presque à moitié maintenant, en partie à cause de moi mais principalement à cause de @nimi.
La fonction magique est
(#)
. Il trouve toutes les solutions d'un nonogramme donné.Cela peut résoudre tous les cas, mais peut être super lent, car sa complexité est à peu près
O(2^(len a * len b))
. Un benchmark rapide a révélé 86 Go alloués pour un nonogramme 5x5.Fait amusant: il fonctionne pour tous les non-programmes, pas seulement les carrés.
Comment ça fonctionne:
a#b
: Étant donné des listes de listes d'entiers qui représentent le nombre de carrés, générez toutes les grilles (map(chunk$length b).mapM id$a>>b>>[[0,1]]
) et filtrez les résultats pour ne garder que ceux valides.g
: Étant donné un nonogramme potentiel, il additionne les séquences de 1 horizontalement.la source
m(chunk$l b)
etreplicate(l$a>>b)
import Data.Lists
est suffisant, car il réexporte à la foisData.List
etData.List.Split
.Pyth,
917271 octetsUn programme qui accepte une entrée d'une liste de la forme dans
[size, [horizontal clues], [vertical clues]]
laquelle chaque indice est une liste de nombres entiers (indices vides sont la liste vide,[]
), et imprime chaque solution, nouvelle ligne séparée, sous la forme d'une grille binaire où1
est ombrée et0
est non ombrée .Il s'agit d'une force brute, tout comme l'est en gros
O(2^n^2)
. Cela commence à prendre beaucoup de temps pour les énigmes plus grandes, mais résoudra toute taille arbitraire avec un temps suffisant.Essayez-le en ligne
Comment ça fonctionne
Le programme génère toutes les dispositions possibles en prenant le produit cartésien répété de
[0, 1]
avec une longueur égale àsize^2
. Ceci est ensuite divisé en morceaux, donnant une liste pour chaque ligne horizontale. Chaque ligne est codée en longueur, filtrée par la présence de1
et aplatie, laissant l'indice de cette ligne. Ceci est ensuite vérifié par rapport à l'entrée. Le processus ci-dessus est répété pour la transposition des morceaux, en vérifiant les lignes verticales. S'il y a un hit, chaque morceau est concaténé, et les morceaux concaténés sont joints sur des retours à la ligne et implicitement imprimés, avec un retour à la ligne de fin.Merci à @ Pietu1998 pour quelques conseils
la source
=ZhZ
est égal à=hZ
etFN
est égal àV
.Javascript (ES6),
401386333 octetsIl s'agit d'une première tentative. Ce n'est pas très efficace mais j'étais curieux de tester une solution en utilisant des expressions régulières sur la représentation binaire des lignes et des colonnes.
Par exemple, il traduira l'indice
[3,1]
en l'expression régulière suivante:Pour l'instant, cette version ne tient pas compte des indices carrés. J'ajouterai probablement cela plus tard.
Code
Production
La solution est affichée au format binaire. Tel que:
Tester
Il s'agit d'un test simple sur l'exemple de grille.
la source
Haskell, 109 octets
Avertissement: ceci est dérivé de la réponse de @ ThreeFx . Je l'ai aidé à comprendre sa réponse mais il semble avoir perdu tout intérêt à inclure mes dernières améliorations substantielles, alors je les poste comme nouvelle réponse.
Exemple d'utilisation:
[[2],[3],[3],[3,1],[1]] # [[2],[3],[4],[2],[2]]
->[[" ## "," ### ","### ","### #"," #"]]
.Force brute. Essayez toutes les combinaisons de
et
#
, séparez les morceaux de#
, comptez les longueurs et comparez-les à l'entrée.la source
PHP,
751833 (720)753724726710691680682 octetsJ'étais impatient de construire un incrément de séquence spécialisé et d'essayer à nouveau mon générateur cartésien;
mais a abandonné le cartésien en faveur du retour en arrière pour résoudre le grand puzzle plus rapidement.
$r
pour les conseils de ligne,$c
pour les conseils de colonne et$s
pour les conseils carrés.invalid argument supplied for foreach
s'il ne trouve pas de solution.\n
et supprimez les deux autres sauts de ligne.la description
1) à partir des indications de ligne,
générez des lignes possibles qui satisfont les indications de carré
et rappelez-vous leur nombre pour chaque index de ligne.
2) revenir en arrière sur les combinaisons de lignes:
si la combinaison satisfait les indications de la colonne, recherchez une combinaison plus profonde ou réussie,
sinon essayez la possibilité suivante pour cette ligne
3) solution d'impression
Le dernier golf a eu un impact sévère sur la performance;
mais j'ai supprimé les affectations de profilage pour les repères finaux.
Remplacez
$n=$n*($f=($p[$y][$i[$y]]>>$x&1)==$v)+$k=$f?:($v=!$v)||$n==$h[$z++];
par
if(($p[$y][$i[$y]]>>$x&1)-$v){$k=($v=!$v)||$n==$h[$z++];$n=1;}else$n++;
pour annuler la dernière étape de golf.
exemples
Pour le petit exemple (
17 à 21vers12876,75,3 ms), utilisezpour le puzzle de noël:
5037,845,5environ 36 secondesmettre les données de la question dans un fichier
christmas.nonogram
et utiliser ce code pour importer:panne
la source
$d
doit être dans le bon ordre pourforeach