Élargissez un carrelage diamant


27

Tout hexagone ordinaire peut être carrelé de diamants, par exemple comme ceci:

   ______
  /_/_/\_\
 /_/\_\/\_\
/\_\/_/\/_/\
\/_/\_\/_/\/
 \_\/_/\_\/
  \_\_\/_/

Nous considérerons ce qui précède comme un carrelage de taille 1(puisque les côtés des diamants sont constitués d'un /ou de \chacun). Le même pavage de taille 2ressemblerait à:

      ____________ 
     /   /   /\   \  
    /___/___/  \___\ 
   /   /\   \  /\   \  
  /___/  \___\/  \___\ 
 /\   \  /   /\  /   /\  
/  \___\/___/  \/___/  \ 
\  /   /\   \  /   /\  /
 \/___/  \___\/___/  \/ 
  \   \  /   /\   \  /
   \___\/___/  \___\/ 
    \   \   \  /   /
     \___\___\/___/ 

Votre tâche consiste à recevoir un tel pavage d'art ASCII (de taille 1) en entrée, avec un entier positif N(en décimal ou unaire), spécifiant la taille de la sortie souhaitée. Vous devez ensuite sortir une version agrandie du même pavage.

Notez que l' hexagone peut être de n'importe quelle taille et aussi petit que 1x1x1 (contenant trois diamants).

Ni l'entrée ni la sortie ne doivent contenir d'espaces de fin, ni plus d'espaces de tête que nécessaire pour aligner la forme hexagonale. L'entrée et la sortie peuvent éventuellement contenir une seule nouvelle ligne de fin (ce choix ne doit pas nécessairement être le même pour l'entrée et la sortie).

Vous pouvez écrire un programme ou une fonction, en prenant une entrée via STDIN (ou l'alternative la plus proche), un argument de ligne de commande ou un argument de fonction et en sortant le résultat via STDOUT (ou l'alternative la plus proche), une valeur de retour de fonction ou un paramètre de fonction (out).

Il s'agit du code golf, donc la réponse la plus courte (en octets) en victoires.

Exemples de pavages

Voici une poignée de pavages d'entrée que vous pouvez utiliser pour tester votre soumission.

 __
/_/\
\_\/

  ____
 /_/\_\
/\_\/_/\
\/_/\_\/
 \_\/_/

   ______
  /_/_/\_\
 /_/\_\/\_\
/\_\/_/\/_/\
\/_/\_\/_/\/
 \_\/_/\_\/
  \_\_\/_/

    ________
   /_/\_\_\_\
  /\_\/\_\_\_\
 /\/_/\/_/_/\_\
/\/\_\/_/_/\/\_\ 
\/\/_/\_\_\/\/_/
 \/\_\/_/\_\/_/
  \/\_\_\/_/_/
   \/_/_/_/_/

L'extrait de code suivant contient les sorties correspondantes pour les entrées N = 1via N = 6.


20
Je vois que les diamants vous intéressent maintenant que vous en avez un à côté de votre nom d'utilisateur.
user12205

3
@ace: Vous savez ce qu'ils disent: les diamants sont les meilleurs amis des modérateurs.
Alex A.

Je pense que je connais la réponse, mais j'espère que je me trompe: les lignes vides de tête compteraient comme espace de tête, que vous avez déclaré illégal? Ma solution initiale a N-1des lignes vides en tête. :(
Reto Koradi

@RetoKoradi En effet, aucune nouvelle ligne de premier plan. Désolé.
Martin Ender

1
J'ai pensé. Me coûte environ 10 octets. Pas aussi mauvais qu'il n'y paraissait lorsque j'ai reconnu le problème pour la première fois.
Reto Koradi

Réponses:


8

CJam, 85 79 76 72 octets

li:Tlf*NqN/T,f{ff{"_/"2$#_1<@+*~ST*@t}:+z{S+e`);e~{"_ "/"__"*W%}T2**N}/}

La taille doit être sur la première ligne. Et le diamant suit.

Pas très bien joué au golf ... Et la moitié des personnages venaient des détails.

Explications (de la version précédente)

li:T            e# Read the size and save to T.
qN/             e# Read and split to lines.
\,fm*           e# Convert each character X to [X 0] [X 1]... [X T(]
{~              e# For each [X I] in each line:
    ST*         e# T spaces.
    \           e# I.
    "_\\"3$#    e# If X is '_, '\ or '/, return Y = 0, 1, -1 respectively.
    _W>@+       e# If it was '_ or '\, increase I by one.
    *(          e# I * Y - 1.
    @t          e# Set the character at that position to X.
}f%
:z:+            e# Make the returned lists from each iteration across T lines.
{S+e`);e~N+}%   e# Boring details to remove trailing spaces and append a newline.
T(>(\s          e# Boring details to extract the first line and only work on others.
{_{"_ "/"__"*W%}2*_@=!}g
                e# Boring details to make underlines expand left and right.

10

Python 2, 164

def g(s,n,j=1):
 for W in s.split("\n"):exec"O=p='';d=0\nfor c in W:q=' _'[j*'_'in p+c];e=[n-j,j-1][c=='/'];O+=q*(e+d)+[c,q][c>'^'];p=c;d=n+~e\nprint O;j-=1;"*j;j=n

Sortie sur les cas de test.

Alors, que se passe-t-il ici?

L'idée principale est que chaque personnage de l'original explose dans un n*nbloc. Par exemple, pour n = 4, /pourrait devenir

   /
  /
 /
/___

Le caractère d'origine apparaît une fois sur chaque ligne et il y a un rembourrage de chaque côté. Ici, c'est à gauche, et _à droite. Seule la rangée inférieure peut être rembourrée '_'; le reste est toujours ' '.

La principale difficulté est que le rembourrage à droite peut dépendre du prochain symbole. Plus précisément, '/ 'a un rembourrage différent de '/_', nous aurions donc besoin d'un peu d'anticipation. De plus, pour éviter de laisser des espaces, nous devons noter que nous sommes au dernier symbole et nous abstenir de remplir à droite.

Nous avons surmonté ces deux problèmes en remplissant uniquement à gauche le caractère actuel. Lorsque nous le faisons, nous effectuons également le remplissage à droite du caractère précédent en utilisant le symbole de remplissage actuel. Ainsi, nous imprimons le remplissage droit dû au caractère précédent, le remplissage gauche du caractère actuel, puis le caractère actuel. Nous stockons également le montant de la «dette» de rembourrage que le prochain personnage devra payer.

Passons maintenant en revue le code.

def g(s,n,j=1):
    for W in s.split("\n"):
        while j:
            O=p='';d=0
            for c in W:
                q=' _'[j*'_'in p+c]
                e=[n-j,j-1][c=='/']
                O+=q*(e+d)+[c,q][c>'^']
                p=c
                d=n+~e
            print O;j-=1;
        j=n

La chaîne d'entrée est set le facteur d'échelle est n. Nous allons ligne par ligne, en imprimant des nlignes pour chaque ligne d'entrée W, avec les copies indexées j=n,n-1,...,2,1. La première ligne n'est copiée qu'une seule fois, ce que nous réalisons en initialisant jà 1 mais en la modifiant dans nchaque boucle.

Nous parcourons la ligne d'entrée, accumulant la ligne à imprimer O. Tout d'abord, nous déterminons le caractère de remplissage approprié q, qui est un trait de soulignement si nous sommes sur la dernière ligne et que le caractère actuel ou précédent est un trait de soulignement, et sinon un espace.

Ensuite, nous décidons de la quantité de rembourrage à mettre à gauche ( e). Pour /, c'est j-1(décroissant avec le nombre de copies de ligne décroissant), et le complémentaire n-jpour \. Nous traitons les autres personnages de la même manière. Par exemple, bien qu'il _semble donner une rangée de ntraits de soulignement, il donne en fait un seul trait de soulignement, complété par des traits de soulignement à gauche et à droite. Cela semble inefficace, mais cela nous permet de travailler avec _et dans le même cadre que /et \La position du trait de soulignement "central" n'a pas d'importance, nous le regroupons donc avec \; ce choix permet également à la rangée supérieure de fonctionner sans boîtier spécial.

Ensuite, nous ajoutons à la chaîne de sortie. Nous avons déterminé le symbole de remplissage qet le montant de remplissage actuel e, mais nous devons également nous souvenir de la dette dde remplissage du symbole précédent. Donc, nous ajoutons q*(e+d). Ensuite, nous ajoutons le symbole actuel c, sauf que nous devons éviter les traits de soulignement dans une ligne non inférieure, que nous corrigeons en convertissant les traits de soulignement en symbole de remplissage.

Enfin, nous enregistrons le montant de la dette de remplissage, qui est le complément n+~ddu montant de remplissage à gauche actuel. Nous enregistrons également le symbole actuel dans p, afin que nous sachions plus tard si le symbole précédent l'était _.


3

JavaScript ( ES6 ) 274 281 289 338

// GOLFED
F=(b,n)=>{
b=b[R='replace'](/ |_/g,c=>c[T='repeat'](n))[R](/_(?=[\\\/])/g,'_'[T](n))[R](/\/\\/g,`/${'  '[T](n-1)}\\`)
.split('\n');
for(i=l=b.length*n-n+1;--i;)
b[i]=i%n?b[i+1][R](/_/g,' ')[R](/\/ ?/g,' /')[R](/ \\(.)?/g,'\\$1$1')
:' '[T](i>l/2?n-1:0)+b[i/n];
return b.join('\n')}


// UNGOLFED
U=(b,n)=>{
  b=b
  .replace(/ |_/g,c=>c.repeat(n))
  .replace(/_(?=[\/\\])/g,'_'.repeat(n))
  .replace(/\/\\/g,`/${'  '.repeat(n-1)}\\`)
  .split('\n');
  for(i=l=b.length*n-n+1;--i;)
  {
    if(i%n)
     b[i]=b[i+1]
     .replace(/_/g,' ')
     .replace(/\/ ?/g,' /')
     .replace(/ \\/g,'\\ ').replace(/ +$/,'')
     .replace(/ \\(.)?/g,'\\$1$1')
    else {
      b[i]=b[i/n]
      if(i>l/2)b[i]=' '.repeat(n-1)+b[i];
    }
  }
  return b.join('\n')
}

//TEST

test=[
' __\n/_/\\\n\\_\\/',
'  ____\n /_/\\_\\\n/\\_\\/_/\\\n\\/_/\\_\\/\n \\_\\/_/',
'   ______\n  /_/_/\\_\\\n /_/\\_\\/\\_\\\n/\\_\\/_/\\/_/\\\n\\/_/\\_\\/_/\\/\n \\_\\/_/\\_\\/\n  \\_\\_\\/_/',
'    ________\n   /_/\\_\\_\\_\\\n  /\\_\\/\\_\\_\\_\\\n /\\/_/\\/_/_/\\_\\\n/\\/\\_\\/_/_/\\/\\_\\\n\\/\\/_/\\_\\_\\/\\/_/\n \\/\\_\\/_/\\_\\/_/\n  \\/\\_\\_\\/_/_/\n   \\/_/_/_/_/'
]

test.forEach(t=>{
  var row = '<td>'+t+'<td>'
  for(rr=2;rr<5;rr++)
    row += '<td>'+F(t,rr)+'</td>'
  OUT.innerHTML += '<tr>'+row+'</tr>'
})
td {
  font-family: monospace;
  white-space: pre;
}
(better full page)
<table id=OUT></table>


3

Python 2, 217 211 195 194 190

b,f,s='\/ '
R=str.replace
def m(g,n,z=1):
 for d in g.split('\n'):
    for i in range(z):a=z+~i;print[i,a][d[-1]>f]*s+R(R(R(R(d,s,s*n),'_','_ '[i<z-1]*(z+n-1)),f+b,f+s*2*i+b),b+f,b+s*2*a+f);z=n

6 octets grâce au Sp3000.

Appelez mavec le premier argument étant le diamant sous forme de chaîne et le deuxième argument le numéro de répétition.

Ceci est basé sur une séquence de remplacement de chaîne en 3 étapes:

  • Tout d'abord, remplacez les traits de soulignement par des espaces 2n-1 ou des traits de soulignement, selon la ligne.
  • Ensuite, remplacez /\par / \, le nombre d'espaces intermédiaires allant de 2 à 2 * (n-1) sur les lignes.
  • Troisièmement, remplacez \/par \ /, le nombre d'espaces intermédiaires passant de 2 * (n-1) à 2 sur les lignes.

Ensuite, il y a une variété de déblayage pour obtenir les bons espaces de tête et obtenir la première ligne droite.

Notez que la dernière ligne du programme doit être une tabulation et non 4 espaces. Markdown ne prend pas en charge les onglets.


Deux golfs: (i+(n-i+~i)*(d[-1]>f)) --> [i,n+~i][d[-1]>f]et vous n'utilisez '_'qu'une seule fois, vous perdez donc un octet en la définissant.
Sp3000

3

Python, 272 238 228 243 octets

Version mise à jour, prend désormais une seule chaîne en entrée, au lieu d'une séquence de chaînes. Supprime également les espaces de fin qui étaient présents dans la version précédente. Malheureusement, ces changements augmentent la taille.

s,u,f,b=' _/\\'
r=str.replace
def d(t,n,j=1):
 for p in t.split('\n'):
  for k in range(n-j,n):m,v=n+~k,'_ '[k<n-1];print r(r(r(r(r(r(r(r(p,f+u,'(_'),u+b,'_)'),s,s*n),u,v*n),f,s*m+f+s*k),'(',v*m+f+v*k),b,s*k+b+s*m),')',v*k+b+v*m).rstrip();j=n

Version avec espace blanc et instructions divisées en unités plus petites pour plus de lisibilité:

s, u, f, b = ' ', '_', '/', '\\'
def d(t, n):
    j = n - 1
    for p in t:
        for k in range(j, n):
            m, v = n - 1 - k, '_ '[k < n - 1]
            q = p[:-1]
            q = q.replace(f + u, '(_')
            q = q.replace(u + b, '_)')
            q = q.replace(s, s * n)
            q = q.replace(u, v * n)
            q = q.replace(f, s * m + f + s * k)
            q = q.replace('(', v * m + f + v * k)
            q = q.replace(b, s * k + b + s * m)
            q = q.replace(')', v * k + b + v * m)
            print q
            j = 0

L'approche de base ici est:

  1. Boucle sur toutes les lignes en entrée.
  2. Pour chaque ligne, bouclez sur la taille de sortie N, générant une ligne de sortie dans chaque itération de boucle. Il existe un cas particulier pour la première ligne, où seule la dernière ligne de sortie est générée, pour éviter de générer des lignes vides au début de la sortie.
  3. Remplacez chaque caractère de la ligne par des Ncaractères, où:
    • Chaque espace est remplacé par des Nespaces.
    • Chaque trait de soulignement est remplacé par des Nespaces pour les premières N -1itérations de boucle et des Ntraits de soulignement pour la dernière itération de boucle.
    • Les barres obliques et les barres obliques inversées sont remplies d' N - 1espaces ou de traits de soulignement.

La partie la plus délicate ici est que le remplissage des barres obliques / barres obliques inverses utilise des espaces ou des traits de soulignement en fonction du caractère d'entrée suivant (pour les barres obliques) ou précédent (pour les barres obliques inverses). Cela ne semblait pas bien correspondre à la stratégie de substitution de chaînes.

Ce que j'ai fait pour résoudre ce problème, c'est que je remplace d'abord certaines combinaisons de deux caractères par des caractères différents, afin de pouvoir les traiter différemment lors de la substitution réelle. Par exemple, /_est remplacé par (_. Après cela, il (s'agit effectivement d'une "barre oblique suivie d'un trait de soulignement", qui peut ensuite être remplacée en conséquence.

Programme principal utilisé pour tester la fonction:

import sys
import Golf

n = int(sys.argv[1])
t = ''.join(sys.stdin).rstrip()

Golf.d(t, n)

1
n-1-kestn+~k
récursif

Dans l'intérêt d'une divulgation complète: je viens de découvrir que ma solution produit des espaces de fin. Comme cela n'est pas autorisé dans la définition de sortie, il ne répond pas aux exigences. Dans le pire des cas, je devrai ajouter un .rstrip()pour 9 caractères supplémentaires. J'espère que je peux faire mieux, et j'ai également trouvé un moyen de découper 5 caractères.
Reto Koradi

Il semble que votre format d'entrée ne soit pas autorisé. sys.stdinn'est pas un paramètre d'entrée autorisé - vous devez manipuler la chaîne elle-même.
isaacg

Eh bien, vous pouvez les utiliser sys.stdinet int(sys.argv[1])vous ne les obtiendrez pas gratuitement en vous attendant à ce qu'ils soient passés en tant que variables (si c'était un jeu équitable, vous pouvez également vous attendre à des alias pour rangeet à remplacer` et tout ce que vous devez prédéfinir) .
Martin Ender

@ MartinBüttner Il dit que je peux prendre l'entrée comme argument de fonction. N'est-ce pas ce que je fais ici? J'allais quand même changer l'argument de la fonction en une liste de chaînes. Serait-ce ok? Ce n'est pas très différent, car les deux stdinet une liste de chaînes sont des séquences de chaînes.
Reto Koradi

1

Perl, 132

#!perl -p
INIT{$f=pop}s!.!$&x$f!ge;s! $!! while s!\\+\K\\|/(/)! $1!;
for$x(2..m!/!*$f){print y!_! !r;s!\\.?! \\!g;s!./(.)?!/$1$1!g;s!_ !__!g}

Entrée combinée STDIN et ARGV. Exemple:

$ perl ~/hex.pl <~/hex.txt 3
         __________________
        /     /     /\     \
       /     /     /  \     \
      /_____/_____/    \_____\
     /     /\     \    /\     \
    /     /  \     \  /  \     \
   /_____/    \_____\/    \_____\
  /\     \    /     /\    /     /\
 /  \     \  /     /  \  /     /  \
/    \_____\/_____/    \/_____/    \
\    /     /\     \    /     /\    /
 \  /     /  \     \  /     /  \  /
  \/_____/    \_____\/_____/    \/
   \     \    /     /\     \    /
    \     \  /     /  \     \  /
     \_____\/_____/    \_____\/
      \     \     \    /     /
       \     \     \  /     /
        \_____\_____\/_____/

1

Rubis 236 237

->i,z{i.split(?\n).map{|l|z.times.map{|y|l.size.times.map{|i|z.times.map{|x|c=l[i]
z<y+2&&(l[i-1..i]=='_\\'||l[i..i+1]=='/_')&&o=?_
(c<?!||(x==y&&c==?\\)||(z==y+1&&c>?^)||(x+y+1==z&&c==?/))&&o=c
o||' '}.join}.join.rstrip}-['']}.join ?\n}

Test en ligne: http://ideone.com/e6XakQ

Voici le code avant de jouer au golf:

-> diamond, zoom {
  diamond.split(?\n).map do |l|
    zoom.times.map do |y|
      l.size.times.map do |i|
        zoom.times.map do |x|
          out_char = crt_char = l[i]

          out_char = ' '

          # _ has to be continued under / or \
          if zoom == y+1 && l[i-1..i]=='_\\'
            out_char = ?_
          end
          if zoom == y+1 && l[i..i+1]=='/_'
            out_char = ?_
          end

          # logic to "zoom" \, / and _ characters 
          out_char = crt_char if crt_char == ' '
          out_char = crt_char if x==y && crt_char == ?\\  
          out_char = crt_char if zoom==y+1 && crt_char == ?_
          out_char = crt_char if x+y+1==zoom && crt_char == ?/

          out_char
        end.join
      end.join.rstrip
    end - ['']
  end.join ?\n
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.