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.