AdventJS 2023: Día 1
Tags: javascript, challenge, node, spanish
Published: 2023-12-02 14:10:08

Solución del [Reto #1](https://adventjs.dev/es/challenges/2023/1) del [AdventJS 2023](https://adventjs.dev/es/)
Solución del [Reto #2](https://dev.to/fenriuz/adventjs-2023-dia-2-3e89)

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

- [Introducción](#intruducción)
- [Descripción del reto](#descripción-del-reto)
- [Análisis](#análisis)
- [Solución](#solución)

{%- # TOC end -%}

## Introducción
El 1 de diciembre se ha empezado el [AdventJS](https://adventjs.dev/), una serie de retos para practicar y mejorar como desorrollador de software. Consiste en que todos los días se estará habilitando un nuevo reto de programación, desde el 1 de diciembre hasta el 25 que sea navidad. 🎄

## Descripción del reto
En la fábrica de juguetes del Polo Norte, cada juguete tiene un número de identificación único.

Sin embargo, debido a un error en la máquina de juguetes, algunos números se han asignado a más de un juguete.

¡Encuentra el primer número de identificación que se ha repetido, donde la segunda ocurrencia tenga el índice más pequeño!

En otras palabras, si hay más de un número repetido, debes devolver el número cuya segunda ocurrencia aparezca primero en la lista. Si no hay números repetidos, devuelve -1.

```javascript
const giftIds = [2, 1, 3, 5, 3, 2]
const firstRepeatedId = findFirstRepeated(giftIds)
console.log(firstRepeatedId) // 3
// Aunque el 2 y el 3 se repiten
// el 3 aparece primero por segunda vez

const giftIds2 = [1, 2, 3, 4]
const firstRepeatedId2 = findFirstRepeated(giftIds2)
console.log(firstRepeatedId2) // -1
// Es -1 ya que no se repite ningún número

const giftIds3 = [5, 1, 5, 1]
const firstRepeatedId3 = findFirstRepeated(giftIds3)
console.log(firstRepeatedId3) // 5
```
¡Ojo! Los elfos dicen que esto es una prueba técnica de Google.

## Análisis
El objetivo es encontrar el primer número repetido donde la segunda ocurrencia de ese número tenga el índice más bajo posible en la lista. Si no hay números repetidos se devolverá -1.


### Entrada
- Una lista de números enteros (gifts), donde cada número representa un identificador único de un juguete.

### Salida
- El primer número de identificación que se repite con el índice más bajo en su segunda aparición.
- `-1` si no hay números repetidos.

### Análisis conceptual
- Se debe encontrar la primera repetición, por lo tanto no es necesario iterar más de una vez.
- Necesitamos una manera eficiente de llevar un registro de los números ya revisados.
- Detendremos la ejecución al encontrar el primer número repetido y retornarlo.

## Solución
Creando un [Set](https://developer.mozilla.org/es/docs/Web/JavaScript/Reference/Global_Objects/Set) se pueden ir almacenando los valores repetidos mientras se va recorriendo el arreglo. Se va evaluando cada elemento almacenado y al encontrar una repetición se retorna la respuesta.

```javascript
/**
 * Encuentra el primer regalo repetido en el array dado.
 *
 * @param {Array} gifts - El array de regalos en el que buscar elementos repetidos.
 * @returns {any} - El primer regalo repetido, o -1 si no se encuentra ningún regalo repetido.
 */
function findFirstRepeated(gifts) {
  // Crea un Set para almacenar los regalos únicos
  const set = new Set();

  // Itera a través del array de regalos
  for (const gift of gifts) {
    // Si el regalo ya está en el Set, devuélvelo como el primer regalo repetido
    if (set.has(gift)) {
      return gift;
    }

    // Agrega el regalo al Set
    set.add(gift);
  }

  // Devuelve -1 si no se encuentra ningún regalo repetido
  return -1;
}
```
### Soluciones alternativas
Dejaré algunas soluciones que ha dejado la comunidad

Solución de [SantiMenendez19](https://github.com/SantiMenendez19/adventjs/blob/main/2023/challenge01/solution.js)
```javascript
function findFirstRepeated(gifts) {
  const repeated = gifts.filter((gift, i) => gifts.indexOf(gift) !== i)
  return repeated.length > 0 ? repeated[0] : -1
}
```

Solución de [marta-vilaseca](https://github.com/marta-vilaseca/adventjs-2023/blob/main/01/01.js)
```javascript
function findFirstRepeated(gifts) {
  const unique = new Set();
  for (let i = 0; i < gifts.length; i++) {
    if (unique.has(gifts[i])) {
      return gifts[i];
    } else {
      unique.add(gifts[i]);
    }
  }
  return -1;
}
```
¿Tienes otra alternativa? ¡Déjala en los comentarios!