Riesci a piegare un hexomino in un cubo?


24

Uno dei giocattoli preferiti di mio figlio è un set come questo . In realtà è uno dei miei giocattoli preferiti - ci ho giocato e mi ha dato alcune idee di sfida PPCG. Eccone uno:

Scrivi un programma o una funzione che accetta un disegno di linea ASCII come input e decide se deve essere piegato o meno in un cubo.

Ingresso

L'input consisterà esattamente di un hexomino costruito da quadrati come questo:

+-+
| |
+-+

Ad esempio un heximino di input valido è:

+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
  | |
  +-+

Produzione

  • Un valore veritiero se l'esomino può essere piegato in un cubo, oppure
  • Un valore falso altrimenti.

Per salvarci un po 'di lavoro, Wikipedia ha una bella grafica di:

  • Tutti i 35 esomi:

  • Tutti e 11 gli esomini che si piegano in cubetti:

Gli appunti

  • Gli esomini di input possono avere qualsiasi rotazione o riflesso, non solo quelli mostrati nelle immagini sopra
  • Gli esomini di input possono avere spazi iniziali, ma saranno allineati correttamente rispetto a se stessi
  • Gli esomini di input possono avere uno spazio finale alla fine delle linee e nuove righe alla fine dell'input

1
Puoi spiegare perché esiste un tag di elaborazione delle immagini qui? Né la domanda, né la risposta dovranno fare alcun tipo di elaborazione delle immagini per risolvere la sfida.
— Ottimizzatore,

Chiarimento sullo spazio iniziale / finale: sono consentiti spazi iniziali / finali non necessari su ogni riga e newline non necessarie sono consentite nell'input? Dovrei essere in grado di gestire un input di oltre 1000 caratteri?
— edc65,

@ edc65 sì, dovresti aspettarti lo spazio bianco non necessario che descrivi. La dimensione massima in ingresso di 1000 caratteri sembra ragionevole - La modificherò in
— Digital Trauma

Hmm. Mi chiedo quanti cubi esomini possono essere spremuti, giustapposti, su una pagina stampata?
— Luser droog

Risposte:


7

PMA / Lumache , 130

.!(z\ |o{c..!(z\ }3){w=(..!(z\ )|b..!(z\ )o{..!(z\ }2|c{..!(z\ }1,2w..!(z\ )|w{..!(z\ }1,2c..!(z\ }4o..!(z\ )(..!(z\ )|n..!(z\ )`2

o più "leggibile",

?
.!(z\  | o{c..!(z\ }3  )
{w =( ..!(z\ ) | b ..!(z\ ) o {..!(z\ }2  | c {..!(z\ }1,2w..!(z\ ) | w {..!(z\ }1,2c..!(z\  }4
o  ..!(z\ ) ( ..!(z\ ) | n ..!(z\ ) `2

Insolitamente, si è verificato un problema che può essere gestito dalla quantità limitata di funzionalità implementate finora. Il!(z\ ) modello determina che la posizione corrente si trova nello spazio nel mezzo di un quadrato usando un'asserzione negativa che esiste uno spazio in una direzione "ottinineare". L'idea generale è di verificare la presenza di uno schema che posiziona un quadrato in ciascuna delle 5 posizioni necessarie rispetto al quadrato su cui inizia la partita. Inoltre, deve verificare che non si trovi in ​​un blocco di quadrati 2x2. Prima che il programma funzionasse, dovevo correggere un bug con l'analisi delle parentesi.

Se l'esomino non mappa un cubo, 0 viene stampato. In tal caso, viene stampato un numero intero positivo (numero di corrispondenze).

Ho adattato questo generatore di poliomino per creare tutti i possibili casi di test:

n=input()
r=range
T=lambda P:set(p-min(p.real for p in P)-min(p.imag for p in P)*1j for p in P)
A=[]
for i in r(1<<18):
 P=[k%3+k/3*1j for k in r(18)if i>>k&1]
 C=set(P[:1])
 for x in P:[any(p+1j**k in C for k in r(4))and C.add(p)for p in P]
 P=T(P)
 if not(C^P or P in A or len(P)-n):
  #for y in r(4):print''.join(' *'[y+x*1j in P] for x in r(6))
  o = [ [' ']*13 for _ in r(9)]
  for y in r(4):
   for x in r(6):
    if y+x*1j in P: X=2*x;Y=2*y; o[Y][X]=o[Y+2][X]=o[Y][X+2]=o[Y+2][X+2]='+'; o[Y][X+1]=o[Y+2][X+1]='-';o[Y+1][X+2]=o[Y+1][X]='|'
  print '\n'.join(map(''.join,o))
  A+=[T([p*1j**k for p in P])for k in r(4)]

hahahahahahahah più "leggibile"
— Ottimizzatore

5

Rubino, 173 148 145 143 byte

h=->b,c{[c.count(c.max),c.count(c.min),3].max*2<b.max-b.min}
->s{x=[];y=[];i=j=0
s.bytes{|e|e==43&&x<<i|y<<j;i=e<32?0*j+=1:i+1}
h[x,y]||h[y,x]}

Ultima modifica: /2 sul lato destro del <sostituito da *2sul lato sinistro. Consente l'eliminazione di un set di()

Spiegazione

Il codice è diviso in due parti: una principale funzione senza nome che esegue l'analisi e una funzione ausiliaria senza nome assegnata alla variabile h che esegue il controllo.

La funzione principale esegue la scansione per byte attraverso la stringa, aggiungendo le coordinate xey i,jdi tutti i +simboli trovati in x[]e y[]. Quindi chiama hdue volte. La prima volta che assume che l'esomino sia orizzontale ( x[]contiene le lunghezze ey[] le larghezze) e la seconda volta che assume che sia verticale.

La funzione haccetta le coordinate longitudinali nella matrice, bquindi le coordinate longitudinali nella matrice c. Calcola la lunghezza (in quadrati) dall'espressione (b.max.b.min)/2. Se questo è inferiore o uguale a 3, l'esomino dovrebbe essere valutato nell'altra direzioneh ritorna false.

L'ispezione degli hexominos mostrerà che se la lunghezza è 4, quegli hexominos che si piegheranno in un cubo non hanno più di 2 quadrati (3+ simboli) nella prima e nell'ultima riga . La maggior parte dei quadrati è concentrata sulla riga centrale, che diventerà l'equatore del cubo. Questa condizione risulta necessaria e sufficiente per un hexomino di lunghezza 4 che si piegherà in un cubo.

C'è un solo esomino di lunghezza 5 che si piegherà in un cubo. Ha 3 quadrati (4+ simboli) nella sua prima e ultima riga. Tutti gli altri esomi di lunghezza 5 hanno 5 o più +simboli nella prima o nell'ultima riga.

C'è solo un hexomino di lunghezza 6. Ha 7 +simboli su ogni riga.

Mettendo tutto questo insieme, è sufficiente verificare che la lunghezza dell'esomino sia maggiore di 3 e che il numero di +simboli sulla prima e sull'ultima riga (qualunque sia maggiore) sia inferiore alla lunghezza.

Non registrato nel programma di test

#checking function as explained in text
h=->b,c{[c.count(c.max),c.count(c.min),3].max<(b.max-b.min)/2}

#main function for parsing
f=->s{
  x=[]                 #separate assignments required, 
  y=[]                 #otherwise we get 2 pointers to the same array
  i=j=0                #start coordinates 0,0
  s.bytes{|e|          #scan string bytewise
    e==43&&x<<i|y<<j     #if byte is a + symbol (ascii 43) add the coordinates to arrays x and y
    i=e<32?0*j+=1:i+1    #if byte is before ascii 32 assume newline, increment j and zero i. Otherwise increment i
  }
  h[x,y]||h[y,x]       #call h twice, with x and y in each possible order
}



#VALID INPUTS
puts f["
+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
| |
+-+"]

puts f["
+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
  | |
  +-+"]

puts f["
+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
    | |
    +-+"]
puts f["
+-+
| |
+-+-+-+
| | | |
+-+-+-+-+
    | | |
    +-+-+"]

puts f["
+-+
| |
+-+-+-+-+
| | | | |
+-+-+-+-+
      | |
      +-+"]

puts f["
    +-+
    | |
+-+-+-+-+
| | | | |
+-+-+-+-+
    | |
    +-+"]
puts f["
    +-+
    | |
+-+-+-+
| | | |
+-+-+-+-+
    | | |
    +-+-+"]


puts f["
  +-+
  | |
+-+-+-+-+
| | | | |
+-+-+-+-+
    | |
    +-+"]
puts f["
  +-+
  | |
+-+-+-+
| | | |
+-+-+-+-+
    | | |
    +-+-+"]  
puts f["
+-+-+
| | |
+-+-+-+
  | | |
  +-+-+-+
    | | |
    +-+-+"]

puts f["
  +-+-+-+
  | | | |
  +-+-+-+-+-+
      | | | |
      +-+-+-+
"]


#INVALID INPUTS

puts f["
  +-+-+-+
  | | | |
  +-+-+-+
  | | | |
  +-+-+-+
"]


puts f["
  +-+-+-+-+-+-+
  | | | | | | |
  +-+-+-+-+-+-+

"]


puts f["
  +-+-+
  | | |
  +-+-+
  | |
  +-+
  | |
  +-+
  | |
  +-+
  | |
  +-+
"]

puts f["
  +-+-+-+-+-+
  | | | | | |
  +-+-+-+-+-+
    | |
    +-+
"]

puts f["
      +-+
      | |
  +-+-+-+-+-+
  | | | | | |
  +-+-+-+-+-+
"]

puts f["
  +-+-+-+-+
  | | | | |
  +-+-+-+-+-+
        | | |
        +-+-+"]

puts f["
  +-+-+-+-+
  | | | | |
  +-+-+-+-+
      | | |
      +-+-+
"] 


puts f["
  +-+-+-+-+
  | | | | |
  +-+-+-+-+
  | | | |
  +-+ +-+
"]

puts f["
 +-+   +-+
 | |   | |
 +-+-+-+-+
 | | | | |
 +-+-+-+-+
"]

puts f["
   +-+-+
   | | |
 +-+-+-+-+
 | | | | |
 +-+-+-+-+
"]

puts f["
  +-+
  | |
  +-+
  | |
  +-+-+-+-+
  | | | | |
  +-+-+-+-+
"]

puts f["
  +-+
  | |
  +-+-+-+
  | | | |
  +-+-+-+
  | |
  +-+
  | |
  +-+
"]

puts f["
  +-+
  | |
+-+-+-+
| | | |
+-+-+-+
| |
+-+
| |
+-+"]

puts f["
  +-+-+
  | | |
  +-+-+
  | |
  +-+-+
  | | |
  +-+-+
    | |
    +-+
"]

puts f["
  +-+-+-+
  | | | |
  +-+-+-+-+
    | | | |
    +-+-+-+
"]

puts f["
  +-+-+-+
  | | | |
  +-+-+-+
      | |
      +-+-+
      | | |
      +-+-+
"]


puts f["
  +-+-+-+
  | | | |
  +-+-+-+-+
      | | |
      +-+-+
        | |
        +-+
"]

pentonimo → hexonimo nel tuo testo?
— Paŭlo Ebermann,

3

JavaScript (ES6), 443 431

Modifica correzione bug, problema durante l'analisi di input, rimozione di colonne vuote

F=t=>(a=b=c=d=e=f=g=h=0,M=Math.min,
t=t.split('\n').filter(r=>r.trim()>''),
t=t.map(r=>r.slice(M(...t.map(r=>r.search(/\S/))))),
t.map((r,i)=>i&1&&[...r].map((_,j)=>j&1&&r[j-1]==r[j+1]&t[i-1][j]==t[i+1][j]&r[j-1]=='|'
&&(y=i>>1,x=j>>1,z=y*5,w=x*5,a|=1<<(z+x),e|=1<<(w+y),b|=1<<(4+z-x),f|=1<<(4+w-y),c|=1<<(20-z+x),g|=1<<(20-w+y),d|=1<<(24-z-x),h|=1<<(24-w-y)
))),~[1505,2530,3024,4578,252,6552,2529,4577,2499,4547,7056].indexOf(M(a,b,c,d,e,f,g,h)))

È molto lungo e anche più lungo poiché l'analisi dell'input è una parte importante dell'attività.

Quello che faccio è verificare se l'input dato è uno degli 11 hexominoes pieghevoli.

Ogni hexomino pieghevole può essere mappato a circa 5x5 bitmap (fino a 8 diversi, con simmetria e rotazioni). Prese le bitmap come numero a 25 bit, ho trovato i valori minimi per gli 11 esomini noti, usando il seguente codice (con un formato di input molto semplice)

h=[ // Foldable hexominoes
'o\noooo\no', ' o\noooo\n o', // pink
'o\noooo\n   o', ' o\noooo\n  o', 'ooo\n  ooo', 'oo\n oo\n  oo', //blue
'o\noooo\n o', 'o\noooo\n  o', 'oo\n ooo\n o', 'oo\n ooo\n  o', 'o\nooo\n  oo' // gray
]
n=[]
h.forEach(t=>(
  a=[],
  t.split('\n')
    .map((r,y)=>[...r]
      .map((s,x)=>s>' '&&(
         a[0]|=1<<(y*5+x),a[1]|=1<<(x*5+y),  
         a[2]|=1<<(y*5+4-x),a[3]|=1<<(x*5+4-y),  
         a[4]|=1<<(20-y*5+x),a[5]|=1<<(20-x*5+y),  
         a[6]|=1<<(24-y*5-x),a[7]|=1<<(24-x*5-y))
     )
  ),
n.push(Math.min(...a))
))

Questo dà [1505,2530,3024,4578,252,6552,2529,4577,2499,4547,7056]

Quindi, data la stringa di input, devo fare lo stesso per trovare la bitmap minima, quindi restituire true se questo numero è presente nel mio elenco di precalc.

// Not so golfed 

F=t=>(  
  a=b=c=d=e=f=g=h=0,M=Math.min,
  t=t.split('\n').filter(r=>r.trim()>''), // remove blank lines
  t=t.map(r=>r.slice(M(...t.map(r=>r.search(/\S/))))), // remove blank colums to the left
  t.map((r,i)=>i&1&&[...r] // only odd rows
   .map((_,j)=>j&1&& // only odd columns
      r[j-1]==r[j+1]&t[i-1][j]==t[i+1][j]&r[j-1]=='|' // found a cell
         &&(y=i>>1,x=j>>1,z=y*5,w=x*5, // find bitmaps for 8 rotations/simmetries
            a|=1<<(z+x),e|=1<<(w+y),  
            b|=1<<(4+z-x),f|=1<<(4+w-y),  
            c|=1<<(20-z+x),g|=1<<(20-w+y),  
            d|=1<<(24-z-x),h|=1<<(24-w-y)  
    ))),
   ~[1505,2530,3024,4578,252,6552,2529,4577,2499,4547,7056].indexOf(Math.min(a,b,c,d,e,f,g,h)) // look for min
)

Esegui lo snippet per testare in Firefox


Perdonatemi se mi manca qualcosa, ma non potreste voi ,\nt=tdalla fine della seconda riga / l'inizio della terza riga?
— Conor O'Brien,

@ CᴏɴᴏʀO'Bʀɪᴇɴ, esaminando sei mesi dopo, il codice di analisi potrebbe essere ridotto di 10 ... 15 byte. Così com'è, ho bisogno dell'assegnazione t nella riga 2 e di nuovo nella riga 3 perché nella riga 3 viene utilizzato per trovare il numero di caratteri vuoti da tagliare sul lato sinistro.
— edc65,
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.