AdventJS 2023: Reto del Día 7
Tags: spanish, javascript, webdev, challenge
Published: 2023-12-09 04:25:08

Solución al [reto #7](https://adventjs.dev/es/challenges/2023/7) del [AdventJS 2023](https://adventjs.dev/es)
[Solución del reto anterior](https://dev.to/fenriuz/adventjs-2023-reto-del-dia-6-1lpk)
[Solución del siguiente reto](https://dev.to/fenriuz/adventjs-2023-reto-del-dia-8-i44)

{%- # TOC start (generated with https://github.com/derlin/bitdowntoc) -%}

- [Descripción del Reto](#descripción-del-reto)
- [Análisis](#análisis)
   * [Entradas](#entradas)
   * [Salida](#salida)
   * [Consideraciones](#consideraciones)
- [Solución](#solución)
   * [Código](#código)
   * [Soluciones de la comunidad](#soluciones-de-la-comunidad)

{%- # TOC end -%}

## 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:

```javascript
drawGift(4, '+')

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

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

drawGift(1, '^')
/*
#
*/
```
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:
```
    #####
   #***##
  #***#*#
 #***#**#
#####***#
#***#**#
#***#*#
#***##
#####
```
Lo de arriba es básicamente un rectangulo en 3D
![Rectángulo 3D](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ykvbxhyq03bf13ne0v5r.png)
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
```javascript
/**
 * 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";
}
```

### Soluciones de la comunidad

Solución por [marcode24](https://github.com/marcode24/adventjs-solutions/blob/main/2023/07-las-cajas-en-3d/index.js):

```javascript
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`;
};
```

Solución por [Achalogy](https://github.com/Achalogy/advent-js-2023/blob/main/retos/reto-7/main.ts):

```javascript
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
}
```

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