Pouvez-vous plier un hexomino en cube?

24

L'un des jouets préférés de mon enfant est un ensemble comme celui-ci . En fait, c'est l'un de mes jouets préférés - j'ai joué avec et ça m'a donné des idées de défis PPCG. En voici un:

Écrivez un programme ou une fonction qui prend en entrée un dessin au trait ASCII et décide s'il se replie ou non en cube.

Contribution

L'entrée consistera en exactement un hexomino construit à partir de carrés comme celui-ci:

+-+
| |
+-+

Par exemple, un heximino d'entrée valide est:

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

Sortie

  • Une valeur vraie si l'hexomino peut être plié en cube, ou
  • Une valeur de falsey sinon.

Pour nous faire économiser un peu de travail, wikipedia a de jolis graphismes de:

  • Les 35 hexominos:

  • Les 11 hexominos qui se replient en cubes:

Remarques

  • Les hexominos d'entrée peuvent avoir une rotation ou une réflexion, et pas seulement ceux montrés dans les images ci-dessus
  • Les hexominos d'entrée peuvent avoir des espaces de tête, mais seront correctement alignés par rapport à eux-mêmes
  • Les hexominos d'entrée peuvent avoir un espace de fin à la fin des lignes et des sauts de ligne à la fin de l'entrée
Traumatisme numérique
la source
1
Pouvez-vous expliquer pourquoi il existe une balise de traitement d'image ici? Ni la question, ni la réponse ne devront faire aucun traitement d'image pour résoudre le défi.
Optimizer
Clarification sur les espaces de début / fin: les espaces de début / fin inutiles sur chaque ligne et les retours à la ligne inutiles sont-ils autorisés en entrée? Dois-je être en mesure de gérer une entrée de plus de 1000 caractères?
edc65
@ edc65 oui, vous devez vous attendre à l'espace blanc inutile que vous décrivez. La taille d'entrée maximale de 1000 caractères semble raisonnable - je le modifierai dans
Digital Trauma
Hmm. Je me demande combien d'hexominos cubes peuvent être pressés, juxtaposés, sur une page imprimée?
luser droog

Réponses:

7

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

ou plus "lisiblement",

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

Fait inhabituel, un problème est survenu qui peut être géré par le nombre limité de fonctionnalités mises en œuvre jusqu'à présent. le!(z\ ) motif détermine que la position actuelle est à l'espace au milieu d'un carré en utilisant une affirmation négative qu'il y a un espace dans une direction "octilinéaire". L'idée générale est de vérifier un motif qui place un carré à chacun des 5 emplacements nécessaires par rapport au carré sur lequel la correspondance commence. En outre, il doit vérifier qu'il ne se trouve pas dans un bloc de carrés 2x2. Avant que le programme ne fonctionne, j'ai dû corriger un bogue avec l'analyse des parenthèses.

Si l'hexomino ne mappe pas un cube, 0 est imprimé. Si c'est le cas, un entier positif est imprimé (nombre de correspondances).

J'ai adapté ce générateur polyomino pour créer tous les cas de test possibles:

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
la source
hahahahahahahah plus "lisiblement"
Optimizer
5

Rubis, 173148145143 octets

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

Dernier changement: /2à droite de <remplacé par *2à gauche. Permet l'élimination d'un ensemble de()

Explication

Le code est en deux parties: une fonction principale sans nom qui effectue l'analyse, et une fonction auxiliaire sans nom affectée à la variable hqui effectue la vérification.

La fonction principale parcourt la chaîne par octets, en ajoutant les coordonnées x et y i,jde tous les +symboles trouvés dans x[]et y[]. Il appelle ensuite hdeux fois. La première fois qu'il suppose que l'hexomino est horizontal ( x[]contient les longueurs et y[]les largeurs) et la deuxième fois, il suppose qu'il est vertical.

La fonction hprend les coordonnées longitudinales dans le tableau bpuis les coordonnées longitudinales dans le tableau c. Il calcule la longueur (en carrés) de l'expression (b.max.b.min)/2. S'il est inférieur ou égal à 3, l'hexomino doit être évalué dans l'autre sens, donc hretournefalse .

L'inspection des hexominos montrera que si la longueur est de 4, les hexominos qui se replieront en cube n'auront pas plus de 2 carrés (3 +symboles) dans la première et la dernière rangée . La plupart des carrés sont concentrés sur la rangée du milieu, qui deviendra l'équateur du cube. Cette condition s'avère nécessaire et suffisante pour un hexomino de longueur 4 qui se repliera en cube.

Il n'y a qu'un seul hexomino de longueur 5 qui se repliera en cube. Il a 3 carrés (4 +symboles) dans ses première et dernière lignes. Tous les autres hexominos de longueur 5 en ont 5 ou plus+ symboles dans la première ou la dernière ligne.

Il n'y a qu'un seul hexomino de longueur 6. Il a 7 +symboles sur chaque ligne.

En combinant tout cela, il suffit de vérifier que la longueur de l'hexomino est supérieure à 3 et que le nombre de +symboles sur les première et dernière lignes (selon le plus élevé) est inférieur à la longueur.

Non testé dans le programme de 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["
  +-+-+-+
  | | | |
  +-+-+-+-+
      | | |
      +-+-+
        | |
        +-+
"]
Level River St
la source
pentonimo → hexonimo dans votre texte?
Paŭlo Ebermann
3

JavaScript (ES6), 443 431

Modifier la correction de bogue, problème lors de l'analyse d'entrée, suppression des colonnes vides

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

C'est très long, et même plus car l'analyse des entrées est une grande partie de la tâche.

Ce que je fais est de vérifier si l'entrée donnée est l'un des 11 hexominos pliables.

Chaque hexomino pliable peut être mappé sur un bitmap 5x5 (jusqu'à 8 différents, avec simulation et rotations). Pris les bitmaps en tant que nombre 25 bits, j'ai trouvé les valeurs min pour les 11 hexominos notés, en utilisant le code suivant (avec un format d'entrée très simple)

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

Ça donne [1505,2530,3024,4578,252,6552,2529,4577,2499,4547,7056]

Donc, étant donné la chaîne d'entrée, je dois faire de même pour trouver le bitmap min, puis retourner true si ce nombre est présent dans ma liste de précalcification.

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

Exécutez l'extrait de code pour tester dans Firefox

edc65
la source
Pardonnez-moi si je manque quelque chose, mais ne pourriez-vous pas ,\nt=tpartir de la fin de la deuxième ligne / du début de la troisième ligne?
Conor O'Brien
@ CᴏɴᴏʀO'Bʀɪᴇɴ revoyant six mois plus tard, le code d'analyse pourrait être raccourci de 10 ... 15 octets. En l'état, j'ai besoin de l'affectation à t à la ligne 2 et à nouveau à la ligne 3 car à la ligne 3, il est utilisé pour trouver le nombre de caractères vierges à couper sur le côté gauche.
edc65