Formes de points logiques

12

Le jeu

Récemment, une grande partie de mon temps a été occupée par un jeu addictif sur mon téléphone, appelé Logic Dots, qui m'a inspiré pour écrire ce défi. Il est plus facile d'expliquer les règles si je vous montre l'affichage du jeu, voici donc une capture d'écran d'un puzzle non résolu et résolu:

Maintenant, ici, il y a trois choses principales à noter.

  1. Le plateau de jeu (la grille 4x4 des carrés au centre)
  2. Les formes requises (les points liés dans la deuxième barre du haut, sous la partition et le menu, etc.), qui sont toutes des lignes, ou apar 1 rectangles
  3. Les nombres sur les lignes et les colonnes, qui indiquent combien de points doivent être dans la colonne, pour une solution

L'objectif du jeu est d'adapter les formes requises à la grille. Vous pouvez faire pivoter les formes, mais elles ne peuvent pas entrer en diagonale.

Dans la solution, notez que toutes les formes sont créées exactement une fois (car elles ne sont qu'une fois dans les formes requises), et dans ce cas, elles sont toutes horizontales mais elles peuvent également être verticales. Les carrés roses remplis indiquent les carrés non utilisés.

Voici une grille plus grande et légèrement plus compliquée:

Notez que dans le casse-tête non résolu, il y a déjà quelques carrés remplis Les carrés grisés signifient des carrés bloqués sur lesquels vous NE POUVEZ PAS placer de point. Les points avec une queue vous indiquent qu'un point se trouve à cet endroit et qu'il est lié à au moins un point supplémentaire dans la direction de la queue, mais pas dans aucune autre direction (y compris la direction opposée).

Notation

Pour le reste de cet article, je ferai référence au tableau en utilisant les symboles suivants:

  • <,>, ^, v - Signifie un point pré-placé avec une queue s'étendant dans la direction du point
  • * - Signifie un point. S'il est donné sur une grille non résolue (entrée), il s'agit d'une forme individuelle. S'il est en sortie, il est connecté aux points qui l'entourent.
  • # - Signifie un carré de grille bloqué (où vous ne pouvez pas placer de point)
  • -, | (trait d'union et barre) - Signifient respectivement un point avec une queue droite et gauche et un point avec une queue haut et bas
  • ** (caractère espace) - ** Signifie un espace vide

En utilisant ces symboles, le dernier exemple de cas (non résolu) peut être représenté comme suit:

 <    



    # 
 ^ #

Et la solution peut être représentée comme:

*< * *
   *  
     *
 *   *
 * *#*
 ^ # *

Notez que deux formes ne peuvent pas toucher horizontalement, verticalement ou en diagonale , donc le cas suivant n'est pas valide:

 *** 
**   
  ** 

Défi

Votre défi est de résoudre n'importe quel puzzle de points logiques, du 4x4 au 9x9 inclus. Vous recevrez quatre lignes d'entrée, puis le plateau de jeu. Les lignes seront les suivantes:

  • 1ère ligne, Formes - Les formes à trouver, chacune donnée dans le formulaire sizexquantity(par exemple 3x2pour deux formes de longueur trois) et séparées par un espace. Exemple de ligne:3x1 2x1 1x1
  • 2e ligne, Colonnes - Une liste séparée par des espaces du nombre de points requis pour chaque colonne. Exemple de ligne:1 1 2 2
  • 3e ligne, lignes - Une liste séparée par des espaces du nombre de points requis pour chaque ligne. Exemple de ligne:3 0 3 0
  • 4ème ligne, taille de la carte - Un seul entier, la taille de la carte, B

La carte est alors donnée, et est des Blignes d'entrée représentant la carte en utilisant la notation mentionnée ci-dessus. Par exemple, l'entrée complète pour ce dernier exemple de cas est la suivante:

4x1 3x1 2x2 1x2
1 4 0 3 0 5
4 1 1 2 3 2
6
 <    



    # 
 ^ #  

Votre programme sortira ensuite la carte résolue, dans la même notation. La sortie correspondante pour l'entrée ci-dessus est la suivante:

** * *
   *  
     *
 *   *
 * *#*
 * # *

Notez qu'un plateau de jeu peut avoir plusieurs solutions. Dans ce cas, sortez simplement une solution valide. De plus, votre programme doit produire une solution correcte dans les 10 secondes sur un ordinateur de bureau raisonnable pour une grille 10x10 compliquée.

C'est le golf de code, donc le moins d'octets gagne.


Cas de test

Entrée 1

3x2 1x4
2 2 3 1 2
4 0 3 0 3
5


    #
  #  
    *

Sortie 1

*** *

 ***#
  #  
* * *

Entrée 2

3x1 1x6
2 0 4 0 3
3 1 2 1 2
5
*    


   # 

Sortie 2

* * *
  *  
  * *
*  # 
  * *

Entrée 3

5x1 4x1 2x1 1x2
1 2 3 3 2 2
0 5 0 4 0 4
6
#     
  -   


 #    
   <  

Sortie 3

#     
 *****

 **** 
 #    
* ** *
globby
la source
Oui, c'est correct @flawr
globby
@flawr t no two shapes can touch horizontally, vertically or diagonally(cela devrait être au début, pas perdu presque vers la fin, mais de toute façon ...)
edc65
@globby Est-ce que chaque espace vide ne serait pas remplacé par #, je suppose que le # est lorsque vous appuyez une seule fois sur un espace vide dans le jeu. Lorsque vous terminez un niveau, il remplit toutes les cellules vides.
Teun Pronk
@TeunPronk No. # sont des espaces prédéterminés que vous ne pouvez pas placer de point dans le niveau, comme les carrés gris dans le deuxième exemple.
globby
2
Mieux que d'offrir une prime, vous devriez ajouter des cas de test plus intéressants et corriger les erreurs dans votre question. Par exemple, la dernière sortie avant les cas de test actuels contient toujours <et ^
edc65

Réponses:

3

Python 2: 766 739 696 663 633 octets

def f(B,S,o=0):
 if[]==S:print'\n'.join(B);exit()
 s=S[0]
 for i in r:
  for j in R(Z-s+1):
   if(B[i][j]in' '+'>v'[o])*(B[i][j+s-1]in' '+'<^'[o])*({' ','-|'[o]}>=set(B[i][j+1:j+s-1]))*all(B[x][y]in'# 'for x,y in [(x,y)for y in R(j-1,j+s+1)for x in i-1,i+1]+[(i,j-1),(i,j+s)]if 0<=x<Z>y>=0):q=B[:];q[i]=q[i][:j]+'*'*s+q[i][j+s:];q=(q,t(q))[o];any((t(q)+q)[k].count('*')>m[k]for k in R(Z+Z))or f(q,S[1:])
 o or f(t(B),S,1)
y=raw_input;S=[];s=str.split
for i in s(y()):u,v=map(int,s(i,'x'));S+=[u]*v
m=map(int,s(y())+s(y()));Z=input();R=range;r=R(Z);B=[y()for _ in r];J=''.join;t=lambda x:map(J,zip(*x))
f(B,S[:len(S)-J(B).count('*')])

Voyez-le fonctionner en ligne: Ideone.com (la version en ligne peut être trop lente pour les grilles volumineuses et difficiles, hors ligne ça devrait aller)

L'entrée se fait via stdin, il suffit de copier et de coller les lignes de l'OP (mais attention, stackexchange supprime parfois des espaces ou des lignes).

Quelques idées de base de ce code: Il utilise une fonction récursive f. fessaie de placer une forme sur la planche. Pour chaque emplacement possible, il s'appelle avec la carte modifiée. Il contient 3 boucles. odétermine l'orientation (2 - horizontale, 3 - verticale). Il placera toujours la forme à l'horizontale, donc à la fin o=2, il transposera la planche avec la fonction t. iest la ligne et jsont toutes les colonnes de départ possibles. Ensuite, de nombreuses vérifications se produisent, si les extrémités de la forme ont des caractères valides, si le milieu de la forme a des caractères valides et si l'entourage est vide.

Jakube
la source
J'avais du mal à couper les 6 derniers octets, quand j'ai vu votre dernier montage (-30) et j'ai abandonné ... Vous avez mon vote pour ce qu'il vaut
edc65
3

JavaScript (ES6) 661 667 695 702 745 755 786 790 784 798

Les travaux en cours peuvent être raccourcis. Probablement trop lent sur une grille complexe. Peut être pas.

Modifier un peu plus longtemps, beaucoup plus vite.
Modifier 2 Correction de bogue, vérification des colonnes / lignes. Soit dit en passant, maintenant c'est plus rapide

La fonction M est la principale. Le paramètre w est une chaîne multiligne avec toutes les entrées. La fonction analyse l'entrée et prépare une planche de départ. Les caractères <>^v|-*du tableau de départ sont remplacés par ,, chacun ,doit être remplacé par *dans la bonne solution.

La fonction R essaie récursivement de placer toutes les formes dans la planche. Lorsqu'une forme est placée, elle s'appelle en passant une liste plus courte de formes et la planche modifiée. Lorsque toutes les formes sont placées, une solution peut toujours être invalide si elle n'est ,pas remplacée par *.

Le test de fonction P si une forme peut être placée à une position et une orientation données. Il vérifie tous les costrains (à l'intérieur du tableau, pas de chevauchement, pas de toucher, nombre de lignes et de colonnes valide)

M=w=>(
  [x,c,r,z]=w=w[S='split'](n='\n'),
  (b=[...w.slice(4).join(n)])
  .map((c,p)=>~(k='*<>-*^v|'.indexOf(c))&&[(q=k>3?z:1,0),k&1&&-q,k&2&&q].map(o=>b[p+o]=0),
    c=c[S](e=' '),r=r[S](e),w=z++,f='*',s='',x[S](e).map(v=>s+=v[0].repeat(v[2]))),
  R=(s,b,x=0,y=0,n=s[0],V=i=>b[i]>'#',
    P=(p,o,q,t,g,l,d=[...b])=>{
        if(l<z-n&!V(p+o*l-o)&!V(p+o*l+o*n))
        {
          for(i=-1;v=d[p],++i<w;p+=o,t-=v==f)
            if(i>=l&i-n<l)
              for(v!=e&v!=0|[q,w,~z].some(w=>V(p+w)|V(p-w))?t=0:d[p]=f,j=o*i,u=k=0;
                  ++k<z;(u+=d[j]==f)>g[i]?t=0:j+=q);
          return t>=n&&d.join('')
        }
    })=>{
    if(b){
      if(!n)return~b.search(0)?0:b;
      for(s=s.slice(1);y<w||(y=0,++x<w);++y)
        if(h=R(s,P(y*z,1,z,r[y],c,x))||n>1&&R(s,P(x,z,1,c[x],r,y)))return h
    }
  })(s,b)

Test dans la console FireFox / FireBug

;['3x2 1x4\n2 2 3 1 2\n4 0 3 0 3\n5\n     \n     \n    #\n  #  \n    *\n'
,'3x1 1x6\n2 0 4 0 3\n3 1 2 1 2\n5\n*    \n     \n     \n   # \n     \n'
,'5x1 4x1 2x1 1x2\n1 2 3 3 2 2\n0 5 0 4 0 4\n6\n#     \n  -   \n      \n      \n #    \n   <  \n'
,'4x1 3x1 2x2 1x2\n1 4 0 3 0 5\n4 1 1 2 3 2\n6\n <    \n      \n      \n      \n    # \n ^ #  \n']
.forEach(x=>console.log(x,M(x).replace(/ /g,'`'))) // space replaced with ` for clarity

Sortie (temps d'exécution total <1 s)

3x2 1x4
2 2 3 1 2
4 0 3 0 3
5


    #
  #  
    *

***`*
`````
`***#
``#``
*`*`*

3x1 1x6
2 0 4 0 3
3 1 2 1 2
5
*    


   # 


*`*`*
``*``
``*`*
*``#`
``*`*

5x1 4x1 2x1 1x2
1 2 3 3 2 2
0 5 0 4 0 4
6
#     
  -   


 #    
   <  

#`````
`*****
``````
`****`
`#````
*`**`*

4x1 3x1 2x2 1x2
1 4 0 3 0 5
4 1 1 2 3 2
6
 <    



    # 
 ^ #  

**`*`*
```*``
`````*
`*```*
`*`*#*
`*`#`*
edc65
la source
On dirait que @globby a oublié cette prime. Quoi qu'il en soit, je me suis beaucoup amusé dans cette course.
Jakube