Kannst du einen Hexomino in einen Würfel falten?

24

Eines der Lieblingsspielzeuge meines Kindes ist ein Set wie dieses . Eigentlich ist es eines meiner Lieblingsspielzeuge - ich habe damit gespielt und mir einige Ideen für PPCG-Herausforderungen gegeben. Hier ist eine:

Schreiben Sie ein Programm oder eine Funktion, die eine ASCII-Strichzeichnung als Eingabe verwendet und entscheidet, ob sie in einen Würfel gefaltet wird oder nicht.

Eingang

Die Eingabe besteht aus genau einem Hexomino aus Quadraten wie folgt:

+-+
| |
+-+

Ein gültiges Eingabe-Heximino ist zum Beispiel:

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

Ausgabe

  • Ein wahrer Wert, wenn das Hexomino in einen Würfel gefaltet werden kann, oder
  • Ein falscher Wert sonst.

Um uns ein bisschen Arbeit zu ersparen, hat Wikipedia schöne Grafiken von:

  • Alle 35 Hexominos:

  • Alle 11 Hexominos, die sich in Würfel falten lassen:

Anmerkungen

  • Eingangshexominos können eine beliebige Drehung oder Reflexion aufweisen, nicht nur die in den obigen Bildern gezeigten
  • Eingabehexominos können führende Leerzeichen enthalten, werden jedoch in Bezug auf sich selbst korrekt ausgerichtet
  • Eingabe-Hexominos können am Ende von Zeilen Leerzeichen und am Ende von Eingaben Zeilenumbrüche enthalten
Digitales Trauma
quelle
1
Können Sie erklären, warum es hier ein Bildverarbeitungs-Tag gibt? Weder die Frage noch die Antwort müssen irgendeine Art von Bildverarbeitung durchführen, um die Herausforderung zu lösen.
Optimierer
Erläuterung zu führenden / nachfolgenden Leerzeichen: Sind unnötige führende / nachfolgende Leerzeichen in jeder Zeile und unnötige Zeilenumbrüche in der Eingabe zulässig? Sollte ich in der Lage sein, mehr als 1000 Zeichen einzugeben?
edc65
@ edc65 ja, du solltest den unnötigen Leerraum erwarten, den du beschreibst. Die maximale Eingabegröße von 1000 Zeichen erscheint vernünftig - das bearbeite ich in
Digital Trauma
Hmm. Ich frage mich, wie viele Würfelhexominos auf einer gedruckten Seite nebeneinander gepresst werden können.
Luser Droog

Antworten:

7

PMA / Schnecken , 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

oder mehr "lesbar",

?
.!(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

Ungewöhnlich ist ein Problem aufgetreten, das durch die begrenzte Anzahl der bisher implementierten Funktionen behoben werden kann. Das !(z\ )Muster bestimmt, dass sich die aktuelle Position auf dem Feld in der Mitte eines Quadrats befindet, wobei die negative Behauptung verwendet wird, dass ein Feld in einer "oktilinearen" Richtung vorhanden ist. Die allgemeine Idee ist, nach einem Muster zu suchen, bei dem ein Quadrat an jeder der 5 erforderlichen Stellen relativ zu dem Quadrat platziert wird, auf dem die Übereinstimmung beginnt. Es muss auch überprüft werden, dass es sich nicht in einem 2x2-Quadratblock befindet. Bevor das Programm funktionieren würde, musste ich einen Fehler beim Parsen von Klammern beheben.

Wenn das Hexomino keinen Würfel abbildet, 0wird gedruckt. In diesem Fall wird eine positive Ganzzahl ausgegeben (Anzahl der Übereinstimmungen).

Ich habe diesen Polyomino-Generator angepasst , um alle möglichen Testfälle zu erstellen:

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)]
Feersum
quelle
hahahahahahahah "lesbarer"
Optimierer
5

Ruby, 173 148 145 143 Bytes

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]}

Letzte Änderung: /2rechts von <ersetzt durch *2links. Ermöglicht die Beseitigung eines Satzes von()

Erläuterung

Der Code besteht aus zwei Teilen: einer unbenannten Hauptfunktion, die das Parsen ausführt, und einer unbenannten Hilfsfunktion, die der Variablen zugewiesen ist h, die die Prüfung durchführt.

Die Hauptfunktion durchsucht den String nacheinander und addiert die x- und y-Koordinaten i,jaller +gefundenen Symbole zu x[]und y[]. Es ruft dann hzweimal an. Beim ersten Mal wird davon ausgegangen, dass das Hexomino horizontal ist ( x[]enthält die Längen und y[]Breiten), und beim zweiten Mal wird davon ausgegangen, dass es vertikal ist.

Die Funktion hnimmt die bLängskoordinaten im Array und dann die Breitenkoordinaten im Array c. Es berechnet die Länge (in Quadraten) nach dem Ausdruck (b.max.b.min)/2. Wenn dies kleiner oder gleich 3 ist, sollte das Hexomino in die andere Richtung ausgewertet werden, damit es hzurückkehrt false.

Die Überprüfung der Hexominos zeigt, dass die Hexominos, die sich zu einem Würfel falten, bei einer+ Länge von 4 nicht mehr als 2 Quadrate (3 Symbole) in der ersten und letzten Reihe haben . Die meisten Quadrate konzentrieren sich auf die mittlere Reihe, die zum Äquator des Würfels wird. Diese Bedingung erweist sich als notwendig und ausreichend für ein Hexomino der Länge 4, das sich zu einem Würfel falten wird.

Es gibt nur ein Hexomino der Länge 5, das sich zu einem Würfel falten lässt. Es hat 3 Quadrate (4 +Symbole) in seiner ersten und letzten Reihe. Alle anderen Hexominos der Länge 5 haben 5 oder mehr +Symbole in der ersten oder letzten Reihe.

Es gibt nur ein Hexomino der Länge 6. Es enthält 7 +Symbole in jeder Zeile.

Zusammengenommen genügt es zu überprüfen, ob die Länge des Hexominos größer als 3 ist und die Anzahl der +Symbole in der ersten und letzten Zeile (je nachdem, welcher Wert höher ist) kleiner als die Länge ist.

Ungolfed im Testprogramm

#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["
  +-+-+-+
  | | | |
  +-+-+-+-+
      | | |
      +-+-+
        | |
        +-+
"]
Level River St
quelle
Pentonimo → Hexonimo in Ihrem Text?
Paŭlo Ebermann
3

JavaScript (ES6), 443 431

Bearbeiten Bug - Fix, Fehler bei der Eingabe Parse, Entfernen leere Spalten

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

Das ist sehr lang und noch länger, da das Parsen von Eingaben einen großen Teil der Aufgabe ausmacht.

Ich überprüfe nur, ob der angegebene Eingang einer der 11 faltbaren Hexominos ist.

Jedes faltbare Hexomino kann auf eine 5x5-Bitmap abgebildet werden (bis zu 8 verschiedene, mit Simmetrie und Rotation). Die Bitmaps als 25-Bit-Zahl genommen, habe ich die minimalen Werte für die 11 notierten Hexominos unter Verwendung des folgenden Codes gefunden (mit sehr einfachem Eingabeformat).

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

Das gibt [1505,2530,3024,4578,252,6552,2529,4577,2499,4547,7056]

Angesichts der eingegebenen Zeichenfolge muss ich dasselbe tun, um die min-Bitmap zu finden, und dann true zurückgeben, wenn diese Nummer in meiner Precalc-Liste vorhanden ist.

// 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
)

Führen Sie das Snippet aus, um es in Firefox zu testen

edc65
quelle
Verzeihen Sie mir, wenn ich etwas vermisse, aber können Sie das nicht ,\nt=tam Ende der zweiten Zeile / am Anfang der dritten Zeile?
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ Ein halbes Jahr später konnte der Parsing-Code um 10 ... 15 Byte verkürzt werden. Wie es ist, brauche ich die Zuweisung zu t in Zeile 2 und erneut zu Zeile 3, da in Zeile 3 die Anzahl der zu schneidenden Leerzeichen auf der linken Seite ermittelt wird.
Edc65