Forme di punti logici


12

Il gioco

Di recente, gran parte del mio tempo è stato occupato da un gioco avvincente sul mio telefono, chiamato Logic Dots, che mi ha ispirato a scrivere questa sfida. È più facile spiegare le regole se ti mostro la visualizzazione del gioco, quindi ecco uno screenshot di un puzzle irrisolto e risolto:

Ora qui, ci sono tre cose principali da notare.

  1. Il tabellone (la griglia 4x4 di quadrati al centro)
  2. Le forme richieste (i punti collegati nella seconda barra dall'alto, sotto il punteggio e il menu, ecc.), Che sono tutte linee o adi 1 rettangolo
  3. I numeri sopra le righe e le colonne, che indicano quanti punti devono essere presenti nella colonna, per una soluzione

L'obiettivo del gioco è quello di adattare le forme richieste alla griglia. Puoi ruotare le forme, ma non possono entrare in diagonale.

Nella soluzione, notare che tutte le forme vengono create esattamente una volta (perché sono solo nelle forme richieste una volta) e in questo caso sono tutte orizzontali ma possono anche essere verticali. I quadrati rosa riempiti indicano quadrati non utilizzati.

Ecco una griglia più grande e leggermente più complicata:

Nota che nel puzzle irrisolto, ci sono già alcuni quadrati riempiti. I quadrati in grigio indicano quadrati bloccati su cui NON PUOI posizionare un punto. I punti con la coda indicano che un punto si trova in quel punto e si collega ad almeno un altro punto nella direzione della coda, ma non in qualsiasi altra direzione (compresa la direzione opposta).

Notazione

Per il resto di questo post, farò riferimento alla lavagna usando i seguenti simboli:

  • <,>, ^, v - Indica un punto pre-posizionato con una coda che si estende nella direzione del punto
  • * - Indica un punto. Se indicato su una griglia non risolta (input), è una forma individuale. Se in uscita, è collegato ai punti circostanti.
  • #: Indica un quadrato della griglia bloccato (dove non è possibile posizionare un punto)
  • -, | (trattino e barra): indica un punto con una coda destra e una sinistra e un punto con una coda su e giù rispettivamente
  • ** (carattere spazio) - ** Indica uno spazio vuoto

Utilizzando questi simboli, l'ultimo caso di esempio (non risolto) può essere rappresentato come segue:

 <    



    # 
 ^ #

E la soluzione può essere rappresentata come:

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

Nota che non è possibile toccare due forme orizzontalmente, verticalmente o diagonalmente , quindi il seguente caso non è valido:

 *** 
**   
  ** 

Sfida

La tua sfida è risolvere qualsiasi puzzle di punti logici, da 4x4 a 9x9 inclusi. Riceverai quattro righe di input, quindi il tabellone. Le linee saranno le seguenti:

  • 1a linea, Forme - Le forme da trovare, ognuna data nella forma sizexquantity(ad es. 3x2Per due forme di lunghezza tre) e separate da uno spazio. Riga di esempio:3x1 2x1 1x1
  • 2nd line, Columns - Un elenco separato da spazi del conteggio dei punti richiesti per ogni colonna. Riga di esempio:1 1 2 2
  • 3a riga, Righe: un elenco separato da spazi del conteggio dei punti richiesti per ogni riga. Riga di esempio:3 0 3 0
  • 4a riga, Dimensione scheda - Un singolo numero intero, la dimensione della scheda, B

Viene quindi data la scheda, ed è Blinee di input che rappresentano la scheda utilizzando la notazione sopra menzionata. Ad esempio, l'input completo per quest'ultimo caso di esempio è il seguente:

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



    # 
 ^ #  

Il programma emetterà quindi la scheda risolta, nella stessa notazione. L'output corrispondente per l'input sopra è il seguente:

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

Nota che un tabellone di gioco può avere più soluzioni. In questo caso, emetti solo una soluzione valida. Inoltre, il programma deve produrre una soluzione corretta entro 10 secondi su un computer desktop ragionevole per una griglia 10x10 complicata.

Questo è il golf del codice, quindi vince meno byte.


Casi test

Ingresso 1

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


    #
  #  
    *

Uscita 1

*** *

 ***#
  #  
* * *

Ingresso 2

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


   # 

Uscita 2

* * *
  *  
  * *
*  # 
  * *

Ingresso 3

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


 #    
   <  

Uscita 3

#     
 *****

 **** 
 #    
* ** *

Sì, è corretto @flawr
globby

@flawr t no two shapes can touch horizontally, vertically or diagonally(questo dovrebbe essere all'inizio, non perso quasi alla fine, ma comunque ...)
edc65,

@globby Non ogni spazio vuoto verrebbe sostituito con #, suppongo che # sia quando tocchi uno spazio vuoto nel gioco. Quando finisci un livello, riempie tutte le celle vuote.
Teun Pronk,

@TeunPronk No. # sono spazi predeterminati che non è possibile posizionare un punto nel livello, come i quadrati grigi nel secondo esempio.
globby

2
Meglio che offrire una taglia, dovresti aggiungere casi di test più interessanti e correggere gli errori nella tua domanda. Ad esempio, l'ultimo output prima degli attuali casi di test contiene ancora <e ^
edc65

Risposte:


3

Python 2: 766 739 696 663 633 byte

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('*')])

Guardalo funzionare online: Ideone.com (la versione online potrebbe essere troppo lenta per griglie grandi e difficili, offline dovrebbe andare bene)

L'input avviene tramite stdin, basta copiare e incollare le linee dall'OP (ma attenzione, stackexchange a volte cancella spazi o linee).

Alcune idee di base di questo codice: utilizza una funzione ricorsiva f. fcerca di posizionare una forma sul tabellone. Per ogni possibile posizione si chiama con la scheda modificata. Ci sono 3 loop in esso. odetermina l'orientamento (2 - orizzontale, 3 - verticale). Posizionerà sempre la forma orizzontale, quindi alla fine o=2trasporrà la scheda con la funzione t. iè la riga e jsono tutte possibili colonne iniziali. Quindi si verificano molti controlli, se le estremità della forma hanno caratteri validi, se il centro della forma ha caratteri validi e se l'ambiente circostante è vuoto.


Stavo lottando per tagliare gli ultimi 6 byte, quando ho visto la tua ultima modifica (-30) e ho rinunciato ... Hai il mio voto per quello che vale
edc65,

3

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

Lavori in corso, possono essere abbreviati. Probabilmente troppo lento su una griglia complessa. Forse no.

Modifica Un po 'più a lungo, molto più veloce.
Modifica 2 Correzione bug, controllo colonne / righe. Per inciso, ora è più veloce

La funzione M è la principale. Il parametro w è una stringa multilinea con tutto l'input. La funzione analizza l'input e prepara una scheda di partenza. I personaggi <>^v|-*nel tabellone vengono sostituiti con ,, ognuno ,deve essere sostituito con *nella soluzione corretta.

La funzione R cerca in modo ricorsivo di posizionare tutte le forme nel tabellone. Quando viene posizionata una forma, questa si chiama passando un elenco più breve di forme e la scheda modificata. Quando vengono posizionate tutte le forme, una soluzione può essere comunque non valida se non viene ,sostituita da *.

La funzione P verifica se è possibile posizionare una forma in una data posizione e orientamento. Controlla tutti i costrain (all'interno del tabellone, nessuna sovrapposizione, nessun tocco, numero di righe e colonne valido)

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 nella 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

Uscita (tempo di esecuzione totale <1 sec)

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
 <    



    # 
 ^ #  

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

Sembra che @globby si sia dimenticato di quella generosità. Comunque, mi sono divertito molto in questa gara.
Jakube,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.