Escalar un mosaico de diamantes

27

Cualquier hexágono regular puede ser embaldosado con diamantes, por ejemplo, así:

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

Consideraremos lo anterior como un mosaico de tamaño 1(ya que los lados de los diamantes están hechos de uno /o \cada uno). El mismo mosaico de tamaño 2se vería así:

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

Su tarea es recibir un mosaico de arte ASCII (de tamaño 1) como entrada, junto con un entero positivo N(en decimal o unario), especificando el tamaño de la salida deseada. A continuación, debe generar una versión ampliada del mismo mosaico.

Tenga en cuenta que el hexágono puede ser de cualquier tamaño y tan pequeño como 1x1x1 (que contiene tres diamantes).

Ni la entrada ni la salida deben contener espacios finales, ni más espacios iniciales que los necesarios para alinear la forma del hexágono. Tanto la entrada como la salida pueden contener opcionalmente una nueva línea final (esta opción no tiene que ser la misma para la entrada y la salida).

Puede escribir un programa o función, tomando la entrada a través de STDIN (o la alternativa más cercana), argumento de línea de comando o argumento de función y generando el resultado a través de STDOUT (o la alternativa más cercana), el valor de retorno de la función o el parámetro de función (out).

Este es el código de golf, por lo que la respuesta más corta (en bytes) en victorias.

Ejemplos de inclinaciones

Aquí hay un puñado de inclinaciones de entrada que puede usar para probar su envío.

 __
/_/\
\_\/

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

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

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

El siguiente fragmento contiene las salidas correspondientes para las entradas a N = 1través N = 6.

Martin Ender
fuente
20
Veo que está interesado en los diamantes ahora que tiene uno junto a su nombre de usuario.
user12205
3
@ace: Sabes lo que dicen: los diamantes son los mejores amigos de un moderador.
Alex A.
Creo que sé la respuesta, pero espero estar equivocado: ¿Las líneas vacías iniciales contarían como espacios iniciales, que usted declaró ilegales? Mi solución inicial tiene N-1líneas vacías iniciales . :(
Reto Koradi
@RetoKoradi De hecho, no hay nuevas líneas principales. Lo siento.
Martin Ender
1
Lo supuse. Me costó unos 10 bytes. No es tan malo como parecía cuando reconocí el problema por primera vez.
Reto Koradi

Respuestas:

8

CJam, 85 79 76 72 bytes

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

El tamaño debe estar en la primera línea. Y el diamante sigue.

No jugaba muy bien ... Y la mitad de los personajes provenían de los detalles.

Explicaciones (de la versión anterior)

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.
jimmy23013
fuente
10

Pitón 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

Salida en casos de prueba.

Entonces, ¿qué está pasando aquí?

La idea principal es que cada personaje en el original explota en un n*nbloque. Por ejemplo, para n = 4, /podría convertirse en

   /
  /
 /
/___

El carácter original aparece una vez en cada línea, y hay relleno a cada lado. Aquí, está a la izquierda y _a la derecha. Solo se puede rellenar la fila inferior '_'; El resto es siempre ' '.

La principal dificultad es que el relleno de la derecha puede depender del próximo símbolo. Específicamente, '/ 'tiene un relleno diferente '/_', por lo que necesitaríamos un poco de anticipación. Además, para evitar espacios finales, tendríamos que tener en cuenta que estamos en el último símbolo y abstenerse de rellenar a la derecha.

Superamos estos dos problemas solo rellenando a la izquierda del personaje actual. Cuando lo hacemos, también realizamos el relleno derecho del carácter anterior utilizando el símbolo de relleno actual. Entonces, imprimimos el relleno derecho que se debe al carácter anterior, el relleno izquierdo del carácter actual y luego el carácter actual. También almacenamos la cantidad de "deuda" de relleno que el próximo personaje deberá pagar.

Ahora repasemos el código.

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 cadena de entrada es sy el factor de escala es n. Vamos línea por línea, imprimiendo nlíneas para cada línea de entrada W, con las copias indexadas j=n,n-1,...,2,1. La primera línea solo se copia una vez, lo que logramos al inicializar ja 1 pero cambiarla a ncada ciclo.

Iteramos a través de la línea de entrada, acumulando la línea para imprimir O. Primero, descubrimos el carácter de relleno apropiado q, que es un guión bajo si estamos en la línea inferior y si el carácter actual o anterior es un guión bajo y, de lo contrario, un espacio.

Luego, decidimos la cantidad de relleno a la izquierda ( e). Para /, es j-1(disminuyendo con la disminución del número de línea-copia), y la complementaria n-jpara \. Tratamos a otros personajes de la misma manera. Por ejemplo, aunque _parece que da una fila de nguiones bajos, en realidad da un solo guión bajo, rellenado por guiones bajos a la izquierda y a la derecha. Esto parece ineficiente, pero nos permite trabajar con _y en el mismo marco que /y \La posición del subrayado "central" no importa, por lo que lo agrupamos y con \; Esta opción también hace que la fila superior funcione sin una carcasa especial.

A continuación, agregamos a la cadena de salida. Hemos descubierto el símbolo de relleno qy la cantidad de relleno actual e, pero también debemos recordar la deuda de relleno ddel símbolo anterior. Entonces, agregamos q*(e+d). Luego, agregamos el símbolo actual c, excepto que debemos evitar los guiones bajos en una fila que no sea inferior, lo que arreglamos convirtiendo los guiones bajos en el símbolo de relleno.

Finalmente, registramos el monto de la deuda de relleno, que complementa n+~del monto actual del margen izquierdo. También registramos el símbolo actual en p, para que luego sepamos si el símbolo anterior era _.

xnor
fuente
3

JavaScript ( ES6 ) 274281 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>

edc65
fuente
3

Pitón 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 bytes gracias a Sp3000.

Llame mcon el primer argumento como el diamante como una cuerda, y el segundo argumento como el número de repetición.

Esto se basa en una secuencia de reemplazo de cadena de 3 pasos:

  • Primero, reemplace los guiones bajos por 2n-1 espacios o guiones bajos, según la línea.
  • Segundo, reemplace /\con / \, con el número de espacios intermedios que van de 2 a 2 * (n-1) sobre las líneas.
  • Tercero, reemplace \/con \ /, con el número de espacios intermedios que van de 2 * (n-1) a 2 sobre las líneas.

Luego, hay una gran variedad de estupideces para obtener los espacios iniciales correctos y para obtener la primera línea correcta.

Tenga en cuenta que la línea final del programa debe ser una pestaña, no 4 espacios. Markdown no admite pestañas.

isaacg
fuente
Dos campos de golf: (i+(n-i+~i)*(d[-1]>f)) --> [i,n+~i][d[-1]>f]y solo los usa '_'una vez, por lo que desperdicia un byte definiéndolo.
Sp3000
3

Python, 272 238 228 243 bytes

Versión actualizada, ahora toma una sola cadena como entrada, en lugar de una secuencia de cadena. También elimina los espacios en blanco finales que estaban presentes en la versión anterior. Lamentablemente, estos cambios aumentan el tamaño.

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

Versión con espacios en blanco y declaraciones divididas en unidades más pequeñas para facilitar la lectura:

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

El enfoque básico aquí es:

  1. Pase por todas las líneas de entrada.
  2. Para cada línea, realice un bucle sobre el tamaño de salida N, generando una línea de salida en cada iteración de bucle. Hay un caso especial para la primera línea, donde solo se genera la última línea de salida, para evitar generar líneas vacías al comienzo de la salida.
  3. Reemplace cada carácter en la línea por Ncaracteres, donde:
    • Cada espacio se reemplaza por Nespacios.
    • Cada guión bajo se reemplaza por Nespacios para las primeras N -1iteraciones del bucle y Nguiones bajos para la última iteración del bucle.
    • Las barras inclinadas y las barras invertidas se rellenan con N - 1espacios o guiones bajos.

La parte más difícil aquí es que el relleno para las barras inclinadas / barras invertidas utiliza espacios o guiones bajos dependiendo del carácter de entrada siguiente (para barras inclinadas) o anterior (para barras inclinadas invertidas). Eso no parecía encajar bien con la estrategia de sustitución de cuerdas.

Lo que hice para resolver esto es que primero reemplazo ciertas combinaciones de dos caracteres con diferentes caracteres, para poder tratarlos de manera diferente durante la sustitución real. Por ejemplo, /_se reemplaza por (_. Después de esto, (es efectivamente una "barra inclinada seguida de un guión bajo", que luego puede sustituirse en consecuencia.

Programa principal utilizado para probar la función:

import sys
import Golf

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

Golf.d(t, n)
Reto Koradi
fuente
1
n-1-kesn+~k
recursivo
En interés de la divulgación completa: acabo de descubrir que mi solución produce algunos espacios finales. Como eso no está permitido en la definición de salida, no cumple con los requisitos. En el peor de los casos, tendré que agregar un .rstrip()para 9 caracteres más. Espero poder hacerlo mejor, y también encontré una forma de recortar 5 caracteres.
Reto Koradi
Parece que su formato de entrada no está permitido. sys.stdinno es un parámetro de entrada permitido; debe manipular la cadena en sí.
isaacg
Bien puede utilizar sys.stdiny int(sys.argv[1])que no vas a obtener de forma gratuita al esperar que se pasan como las variables (si eso era un juego justo, entonces también podría esperar alias rangey replace` y todo lo que necesita para estar predefinido) .
Martin Ender
@ MartinBüttner Dice que puedo tomar la entrada como un argumento de función. ¿No es esto lo que estoy haciendo aquí? Iba a cambiar el argumento de la función a una lista de cadenas de todos modos. ¿Estaría bien? No es muy diferente, ya que ambos stdiny una lista de cadenas son secuencias de cadenas.
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}

Entrada combinada STDIN y ARGV. Ejemplo:

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

Rubí 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}

Prueba en línea: http://ideone.com/e6XakQ

Este es el código antes de jugar al 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
}
Cristian Lupascu
fuente