DEV Community

Cover image for AdventJS 2023: Reto del Día 7
Fenriuz
Fenriuz

Posted on

AdventJS 2023: Reto del Día 7

Solución al reto #7 del AdventJS 2023
Solución del reto anterior
Solución del siguiente reto

Descripción del Reto

Santa está experimentando con nuevos diseños de regalos y necesita tu ayuda para visualizarlos en 3D.

Tu tarea es escribir una función que, dado un tamaño n (entero), genere un dibujo de un regalo en 3D utilizando caracteres ASCII.

Las líneas de los regalos se dibujan con # y las caras con el símbolo que nos pasan como parámetro:

drawGift(4, '+')

/*
   ####
  #++##
 #++#+#
####++#
#++#+#
#++##
####
*/

drawGift(5, '*')
/*
    #####
   #***##
  #***#*#
 #***#**#
#####***#
#***#**#
#***#*#
#***##
#####
*/

drawGift(1, '^')
/*
#
*/
Enter fullscreen mode Exit fullscreen mode

Importante: Nos han dicho que siempre hay que dejar un salto de línea al final del dibujo.

Nota: Ten en cuenta que, en los tests, la primera línea se ve empujada por el caracter ".

Análisis

En este reto básicamente hay que dibujar los regalos en base a los parámetros que nos da el ejercicio, al puro estilo del ASCII Art. Por si no has terminado de entenderlo, aquí un ejemplo:

    #####
   #***##
  #***#*#
 #***#**#
#####***#
#***#**#
#***#*#
#***##
#####
Enter fullscreen mode Exit fullscreen mode

Lo de arriba es básicamente un rectangulo en 3D
Rectángulo 3D
Donde los # representan el contorno del rectángulo, es decir las líneas, mientras que el símbolo que nos pasen como parámetro (en este caso *) representa la cara o la superficie del rectángulo.

Entradas

  1. Size(size): Un número que representa el tamaño del regalo, es la longitud en caracteres de cada línea del regalo.
  2. Symbol(symbol): Un string que será lo que rellene el regalo, básicamente llena cada cara del rectángulo.

Salida

  • Un string que se verá como el dibujo del regalo solocitado en las entradas. ### Consideraciones
  • Siempre hay que dejar un salto de línea al final del dibujo.
  • Hay que tomar en cuenta los espacios en la primera mitad del dibujo, son importantes para darle forma al regalo.

Solución

El ejercicio en sí no tiene mucha complejidad, lo complicado en realidad puede ser manejar el string para dibujar, pero JavaScript ofrece suficientes métodos para ello.

Código

/**
 * Genera un regalo hecho de símbolos en forma de rectángulo.
 *
 * @param {number} size - El tamaño del regalo, determina el ancho y la altura del rectángulo.
 * @param {string} symbol - El símbolo utilizado para dibujar el regalo.
 * @return {string} - La representación del regalo como una cadena.
 */
function drawGift(size, symbol) {
  // El espacio al principio del regalo
  let space = size;

  // Inicializa la primera parte del regalo
  // el espacio al principio del regalo
  // y concatena # con el tamaño del regalo
  let firstPart = " ".repeat(--space) + "#".repeat(size) + "\n";

  // si el tamaño es 1, devuelve la primera parte `#`
  if (size === 1) {
    return firstPart;
  }

  // Inicializa la segunda parte del regalo
  // esta parte es después de la mitad del regalo
  let secondPart = "";

  // bucle a través del tamaño del regalo -2
  // -2 porque ya tenemos la primera y la última línea
  for (let i = 0; i < size - 2; i += 1) {
    // comienza con el espacio al principio del regalo
    const initialSpace = " ".repeat(--space);
    // añade `#` y el símbolo con el tamaño del regalo - 1
    const upperFace = "#".padEnd(size - 1, symbol);
    // añade `#` y llena el espacio con el símbolo
    const rightFace = "#".padEnd(i + 1, symbol)
    // concatena todos ellos y añade el salto de línea
    firstPart += initialSpace + upperFace + rightFace + "#\n";

    // añade los símbolos en la cara frontal
    const frontFace = symbol.repeat(size - 2);
    // añade los símbolos en la cara inferior derecha
    const lowerRightFace = "#".padEnd(size - i - 2, symbol);
    // concatena todos ellos
    secondPart += "#" + frontFace + lowerRightFace + "#\n";
  }

  // la mitad es `#` con el tamaño del regalo y el símbolo con el tamaño del regalo - 2
  const half = "#".repeat(size) + symbol.repeat(size - 2) + "#\n";

  // devuelve la primera parte, la mitad y la segunda parte
  return firstPart + half + secondPart + "#".repeat(size) + "\n";
}
Enter fullscreen mode Exit fullscreen mode

Soluciones de la comunidad

Solución por marcode24:

const drawGift = (size, symbol) => {
  const WRAPPER = '#';
  const SPACE = ' ';

  if (size <= 1) return `${WRAPPER}\n`;

  const top = [SPACE.repeat(size - 1) + WRAPPER.repeat(size)];
  const bottom = [`${WRAPPER.repeat(size)}`];
  const middle = `${WRAPPER.repeat(size)}${symbol.repeat(Math.abs(size - 2))}`
    + `${WRAPPER}\n`;
  for (let i = 1; i < size; i++) {
    const line = `${WRAPPER}${symbol.repeat(size - 2)}${WRAPPER}`
      + `${symbol.repeat(i - 1)}${WRAPPER}`;
    top.push(SPACE.repeat(size - i - 1) + line);
    bottom.push(line);
  }

  top.pop();
  bottom.pop();
  top.push(middle);
  bottom.reverse();
  return `${top.join('\n')}${bottom.join('\n')}\n`;
};
Enter fullscreen mode Exit fullscreen mode

Solución por Achalogy:

function drawGift(size, symbol) {
  let bgSize = size - 2

  bgSize += +!(bgSize + 1)

  let response = ""

  let topCenter = ""
  let bottomCenter = ""

  for (const a of [...Array.from({ length: bgSize }).keys()]) {
    const c = "#"
      + symbol.repeat(bgSize)
      + "#" + symbol.repeat(a) + "#"
    bottomCenter = c + "\n" + bottomCenter
    topCenter += " ".repeat(bgSize - a) + c + "\n"
  }

  response = " ".repeat(size - 1) + "#".repeat(size) + "\n"
    + (topCenter
      + "#".repeat(size) + symbol.repeat(bgSize) + "#" + "\n"
      + bottomCenter
      + "#".repeat(size) + "\n").repeat(+!!(size - 1))

  return response
}
Enter fullscreen mode Exit fullscreen mode

Y ese fue el reto para el 7 de diciembre y sus soluciones. ¿Tienes otra solución alternativa? ¡Déjala en los comentarios!

Top comments (0)