Argyle ASCII Art


27

Escriba un programa (o función) que tome un entero positivo.

Si la entrada es 1, imprima (o devuelva) dos diamantes adyacentes uno al lado del otro, cada uno con una longitud de 1 barra diagonal:

/\/\
\/\/

Para cada entrada Nmayor que 1, observe la salida para N-1y para cada par de diamantes vecinos, inserte un nuevo diamante entre ellos cuya longitud lateral sea la suma de las longitudes laterales de los dos vecinos. Imprima (o devuelva) este nuevo patrón de diamantes.

Entonces, cuando 2se ingresa, miramos la salida 1y podemos ver que hay dos diamantes vecinos, ambos con longitud de lado 1. Así que insertamos un diamante de longitud lateral 2 (1 + 1) entre ellos:

   /\
/\/  \/\
\/\  /\/
   \/

Para la entrada 3, miramos la salida 2y agregamos dos diamantes con longitud lateral 3 (1 + 2 y 2 + 1) entre los dos pares de diamantes vecinos:

    /\        /\
   /  \  /\  /  \
/\/    \/  \/    \/\
\/\    /\  /\    /\/
   \  /  \/  \  /
    \/        \/

Continuando con el patrón, la salida para 4es:

                    /\            /\
     /\            /  \          /  \            /\
    /  \    /\    /    \        /    \    /\    /  \
   /    \  /  \  /      \  /\  /      \  /  \  /    \
/\/      \/    \/        \/  \/        \/    \/      \/\
\/\      /\    /\        /\  /\        /\    /\      /\/
   \    /  \  /  \      /  \/  \      /  \  /  \    /
    \  /    \/    \    /        \    /    \/    \  /
     \/            \  /          \  /            \/
                    \/            \/

Y así.

Sus salidas pueden tener espacios finales en cualquier línea, pero solo hasta una nueva línea final (y no nuevas líneas iniciales).

El código más corto en bytes gana.


1
OEIS relevantes: oeis.org/A002487 .
orlp

Respuestas:


8

Pyth, 50 49 bytes

L.rR"\/"_bjbyK.tsm+Jm+*\ k\\dyJu.iGsM.:G2tQjT9djK

Demostración

Explicación:

L.rR"\/"_bjbyK.tsm+Jm+*\ k\\dyJu.iGsM.:G2tQjT9djK
                                                     Implicit:
                                                     Q = eval(input())
                                                     T = 10
                                                     d = ' '
                                                     b = '\n'
L                                                    def y(b): return
 .rR"\/"                                             Swap \ and / in
        _b                                           reversed input.
                                                     This effectively vertically
                                                     mirrors the input.
                               u                     Apply the function repeatedly
                                           jT9       Starting with [1, 1]
                                         tQ          and repeating Q - 1 times
                                .iG                  interlace G (input) with
                                     .:G2            All 2 element substrings of G
                                   sM                mapped to their sums.
                 m                                   map over these values
                                                     implicitly cast to ranges
                    m       d                        map over the range values
                                                     impicitly cast to ranges
                     +*\ k\\                         to k spaces followed by
                                                     a backslash.
                   J                                 Save to J, which is roughly:
                                                     \
                                                      \
                  +          yJ                      And add on y(J), giving
                                                     \
                                                      \
                                                      /
                                                     /
                s                                    Combine the half diamonds
                                                     into one list.
              .t                              d      Traspose, filling with ' '.
             K                                       Save to K, giving
                                                     something like:
                                                     \  /
                                                      \/
            y                                        Vertically mirror.
          jb                                         Join on newlines and print.
                                               jK    Join K on (implicitly)
                                                     newlines and print.

1
¿Cuáles son las probabilidades? También exactamente tengo u.iGsM.:G2tQjT9en mi solución (parcial). Nunca miré tu respuesta ...
orlp

2
@orlp A menudo solo hay una mejor manera de hacer algo.
isaacg

5

Lisp común, 425

(labels((a(n)(if(> n 1)(loop for(x y)on(a(1- n))by #'cdr collect x when y collect(+ x y))'(1 1))))(lambda(~ &aux(l(a ~))(h(apply'max l))(w(*(apply'+ l)2))(o(* 2 h))(m(make-array(list o w):initial-element #\ ))(x 0)(y h))(labels((k(^ v)(setf(aref m y x)^(aref m(- o y 1)x)v)(incf x))(d(i)(when(plusp i)(k #\\ #\/)(incf y)(d(1- i))(decf y)(k #\/ #\\))))(mapc #'d l))(dotimes(j o)(fresh-line)(dotimes(i w)(princ(aref m j i))))))

Ejemplo

(funcall *fun* 4)

                    /\            /\                    
     /\            /  \          /  \            /\     
    /  \    /\    /    \        /    \    /\    /  \    
   /    \  /  \  /      \  /\  /      \  /  \  /    \   
/\/      \/    \/        \/  \/        \/    \/      \/\
\/\      /\    /\        /\  /\        /\    /\      /\/
   \    /  \  /  \      /  \/  \      /  \  /  \    /   
    \  /    \/    \    /        \    /    \/    \  /    
     \/            \  /          \  /            \/     
                    \/            \/                    

Sin golf

(labels
    ((sequence (n)
       (if (> n 1)
           (loop for(x y) on (sequence (1- n)) by #'cdr
                 collect x
                 when y
                   collect(+ x y))
           '(1 1))))
  (defun argyle (input &aux
                  (list (sequence input))
                  (half-height (apply'max list))
                  (width (* (apply '+ list) 2))
                  (height (* 2 half-height))
                  (board (make-array
                          (list height width)
                          :initial-element #\ ))
                  (x 0)
                  (y half-height))
    (labels ((engrave (^ v)
               (setf (aref board y              x) ^ ;; draw UP character
                     (aref board (- height y 1) x) v ;; draw DOWN character (mirrored)
                     )
               (incf x) ;; advance x
               )
             (draw (i)
               (when (plusp i)
                 (engrave #\\ #\/)  ;; write opening "<" shape of diamond
                 (incf y)
                 (draw (1- i))   ;; recursive draw
                 (decf y)
                 (engrave #\/ #\\)  ;; write closing ">" shape of diamond
                 )))
      ;; draw into board for each entry in the sequence
      (mapc #'draw list))

    ;; ACTUAL drawing
    (dotimes(j height)
      (fresh-line)
      (dotimes(i width)
        (princ (aref board j i))))
    board))

3

CJam, 59 58 57 bytes

YXbri({{_2$+\}*]}*:,_:|,S*0'\tf{fm>_W%'\f/'/f*}:+zN*_W%N@

Gracias a @ MartinBüttner por jugar golf en 1 byte.

Pruébelo en línea en el intérprete de CJam .

Idea

Para la entrada 3 , por ejemplo, generamos

\  
/  
\  
 \ 
  \
  /
 / 
/  
\  
 \ 
 / 
/  
\  
 \ 
  \
  /
 / 
/  
\  
/  

girando la cuerda  \y reemplazando algunas barras diagonales inversas con barras diagonales.

Luego, comprimimos la matriz resultante (transponer filas y columnas) para obtener la mitad inferior de la salida deseada.

La mitad superior es byte por byte igual a la mitad inferior en reversa.

Código

YXb     e# Push A := [1 1] and 2 in unary.
ri(     e# Read an integer fro STDIN and subtract 1.
{       e# Do the following that many times:
  {     e#   For each I in A but the first:
    _2$ e#     Push a copy of I and the preceding array element.
    +\  e#     Compute the sum of the copies and swap it with I.
  }*    e#
  ]     e#   Collect the entire stack in an array.
}*      e#
:,      e# Replace each I in A with [0 ... I-1].
_       e# Push a copy of A.
:|      e# Perform set union of all the ranges.
,S*     e# Get the length (highest I in A) and push a string of that many spaces.
0'\t    e# Replace the first space with a backslash.
f{      e# For each range in A, push the generated string; then:
  fm>   e#   Rotate the string by each amount in the array.
  _W%   e#   Push a reversed copy of the resulting array of strings.
  '\f/  e#   In each string, split at backslashes.
  '/f*  e#   Join each string, separating with slashes.
}       e#
:+      e# Concatenate the resulting arrays of strings.
zN*     e# Zip and join, separating by linefeeds.
_W%     e# Push a reversed copy of the string.
N@      e# Push a linefeed and rotate the original string on top of it.

1

Rev 1: Rubí 170

Nuevo método que evita crear el gran diamante y reducirlo.

->n{a=[1]
m=1<<n-1
(m-1).times{|i|a<<a[i]<<a[i]+a[i+1]}
(-b=a.max).upto(b-1){|j|0.upto(m){|i|d=' '*q=a[-i]*2
(j*2+1).abs<q&&(d[j%q]=?\\;d[-1-j%q]=?/)   
print d}
puts""}}

Rev 0: Rubí, 187

->n{a=[1]
m=1<<n-1
(m-1).times{|i|a<<a[i]<<a[i]+a[i+1]}
(2*b=a.max).times{|j|
0.upto(m){|i|d=' '*b*2;d[(b+j)%(b*2)]='\\';d[(b-1-j)%(b*2)]=?/
r=b-a[-i]
d.slice!(b-r,r*2)
print d}
puts ""}}

Los tamaños de los diamantes se calculan de acuerdo con la relación de recurrencia de https://oeis.org/A002487 Por lo tanto, hacemos la matriz que acontiene todos los elementos para todas las filas del 1 al n. Solo nos interesan los últimos 1<<n-1elementos (Ruby nos permite obtenerlos de la matriz usando índices negativos, siendo -1 el último elemento de la matriz), más un inicial 1desde la posición 0.

Línea por línea y diamante por diamante, dibujamos la fila de caracteres para el diamante más grande, luego cortamos las columnas del medio para obtener la fila del diamante requerido. Rev 1 es más corto, pero me gustó este método.

La aritmética modular se usa para envolver para que la misma expresión agregue todo /directamente y de la misma manera una expresión agrega todo \directamente.

Sin golf en el programa de prueba

f=->n{
  a=[1]
  m=1<<n-1
  (m-1).times{|i|a<<a[i]<<a[i]+a[i+1]}                   #concatenate a[i] and a[i]+a[i+1] to the end of a
    (2*b=a.max).times{|j|                                #run through lines (twice the largest number in a
      0.upto(m){|i|                                      #run through an initial '1' plus the last m numbers in a
      d=' '*b*2;d[(b+j)%(b*2)]='\\';d[(b-1-j)%(b*2)]=?/  #d is the correct string for this line of the largest diamond
      r=b-a[-i]                                          #calculate number of characters to be deleted from middle of d
      d.slice!(b-r,r*2)                                  #and delete them
      print d                                            #print the result
    }
    puts ""                                              #at the end of the line, print a newline
  }
}

f.call(gets.to_i)
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.