AdventJS 2023: Reto del Día 11
Tags: spanish, webdev, javascript, challenge
Published: 2023-12-15 02:33:35

Solución al [reto #11](https://adventjs.dev/es/challenges/2023/11) del [AdventJS 2023](https://adventjs.dev/es)

[Solución del reto anterior](https://dev.to/fenriuz/adventjs-2023-reto-del-dia-10-h5d)

[Solución del siguiente reto](https://dev.to/fenriuz)

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

- [Descripción del Reto](#descripción-del-reto)
- [Análisis](#análisis)
   * [Entrada](#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
En el taller de Santa, los elfos aman los acertijos 🧠. Este año, han creado uno especial: un desafío para formar un palíndromo navideño.

Un palíndromo es una palabra que se lee igual hacia adelante y hacia atrás. Los elfos quieren saber si es posible formar un palíndromo haciendo, como mucho, un intercambio de letras.

Crea una función `getIndexsForPalindrome` que reciba una cadena de caracteres y devolverá:

- Si ya es un palíndromo, un array vacío.
- Si no es posible, null.
- Si se puede formar un palíndromo con un cambio, un array con las dos posiciones (índices) que se deben intercambiar para poder crearlo.
Por ejemplo:

```javascript
getIndexsForPalindrome('anna') // []
getIndexsForPalindrome('abab') // [0, 1]
getIndexsForPalindrome('abac') // null
getIndexsForPalindrome('aaaaaaaa') // []
getIndexsForPalindrome('aaababa') // [1, 3]
getIndexsForPalindrome('caababa') // null
```javascript
Si se puede formar el palíndromo con diferentes intercambios, siempre se debe devolver el primero que se encuentre.

## Análisis
En este reto nuestro objetivo es encontrar un palindromo intercambiando de lugar dos elementos del string y retornar el índice de esos dos elementos, de no encontrar un palindromo se retorna un array vacío.

### Entrada

1. Word(`word`): Un string con la palabra a evaluar.

### Salida
- Un array de dos elementos con los índices a cambiar para encontrar el palindromo
- Si ya es un palindromo se retorna un array vacío
- Si no se cumplen ninguna de las dos anteriores se retorna `null`

### Consideraciones
- Si se pueden formar varios palindromos siempre debemos devolver el primero en ser encontrado.

## Solución
Se puede solucionar recorriendo cada elemento del string, y dentro de esa iteración volverlo a recorrer e ir intercambiando elementos para comparar.

### Código

```javascript
/**
 * Devuelve los índices de los caracteres que deben invertirse para hacer que una palabra sea un palíndromo.
 *
 * @param {string} word - La palabra para verificar sus propiedades palindrómicas.
 * @return {number[] | null} - Un array de dos índices que representan los caracteres a invertir, o null si no existen dichos índices.
 */
function getIndexsForPalindrome(word) {
  // Verifica si la palabra dada ya es un palíndromo
  const isPalindrome = (s) => s === s.split("").reverse().join("");

  // Si la palabra ya es un palíndromo, devuelve un array vacío
  if (isPalindrome(word)) {
    return [];
  }

  // Itera a través de todas las posibles combinaciones de índices
  for (let i = 0; i < word.length; i += 1) {
    for (let j = i + 1; j < word.length; j += 1) {
      // Crea una nueva palabra intercambiando los caracteres en los índices i y j
      const newWord =
        word.substring(0, i) +
        word[j] +
        word.substring(i + 1, j) +
        word[i] +
        word.substring(j + 1);

      // Si la nueva palabra es un palíndromo, devuelve los índices i y j
      if (isPalindrome(newWord)) {
        return [i, j];
      }
    }
  }

  // Si no existen dichos índices, devuelve null
  return null;
}
```

### Soluciones de la comunidad

Solución por [iswilljr](https://github.com/iswilljr/adventjs/blob/master/2023/challenge-11/challenge-11.ts):

```javascript
function getIndexsForPalindrome(word: string) {
  const _letters = [...word]
  const palindrome = word === [..._letters].reverse().join('')

  let initial: number[] | null = [null, []][+palindrome]
  let index = 0
  let aux = 1

  const letters = [_letters, []][+palindrome]
  let auxLetters = letters.slice(1)

  for (const letter of letters) {
    for (const auxLetter of auxLetters) {
      const w = [...letters]
      w[index] = auxLetter
      w[aux] = letter

      const isPalindrome = +(w.join('') === w.reverse().join(''))
      const isInitialNull = +(initial == null)
      const isDifferentIndex = +(index !== aux)

      const values = [initial, initial, initial, [index, aux]]

      initial = values[isInitialNull + isDifferentIndex + isPalindrome]
      aux++
    }

    index++
    aux = 1
    auxLetters = [[], auxLetters][+(initial == null)]
  }

  return initial
}
```

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

```javascript
function getIndexsForPalindrome(word) {
  let res: any = null
  for (const a of Array.from({ length: word.length }).keys()) {
    for (const b of Array.from({ length: word.length }).keys()) {
      let swapped = [...word]
      let aux = word[a]
      swapped[a] = word[b]
      swapped[b] = aux

      let left = swapped.slice(0, Math.floor(word.length / 2)).join("")
      let right = swapped.slice(Math.ceil(word.length / 2)).reverse().join("")

      res = [
        [
          null
          , [
            []
            , [a, b]
          ][+((a + b) > 0)]
        ][+(left == right)]
        , res
      ][+!!res]
    }
  }
  return res
}
```

Y ese fue el reto para el 11 de diciembre y sus soluciones. Dale like si te ha gustado el reto o la solución!
¿Tienes otra solución alternativa? ¡Déjala en los comentarios!