<button id="add">Add your AoC 2022 Day 12 input</button>
<section>
<div id="app"></div>
</section>
body {
  background: #1d1e22;
  font-size: 0.5vw;
}

#app {
  position: relative;
  display: inline-block;
}

.hiker {
  position: absolute;
  transition: all 0.3s ease-in-out;
  transform: scale(2)
}
document.querySelector('#add').addEventListener('click', () => {
  input = prompt("Whats yor AoC 2022 day 12 input?");
  init(input);
})

const waitseconds = ms => new Promise(r => setTimeout(r, ms));

const getCharValue = (char) => char.charCodeAt();

const getNeighbors = (row, col, matrix, part2) => {
  const neighbors = [];
  const current = matrix[row][col];

  if (!part2) {
    // check for out of bounds
    // part 1 conditions
    // also the elevation of the destination square can be at most one higher
    // than the elevation of your current square;
    if (col + 1 < matrix[row].length && matrix[row][col + 1] <= current + 1) {
      neighbors.push({ row, col: col + 1 });
    }

    if (col - 1 >= 0 && matrix[row][col - 1] <= current + 1) {
      neighbors.push({ row, col: col - 1 });
    }

    if (row + 1 < matrix.length && matrix[row + 1][col] <= current + 1) {
      neighbors.push({ row: row + 1, col });
    }

    if (row - 1 >= 0 && matrix[row - 1][col] <= current + 1) {
      neighbors.push({ row: row - 1, col });
    }
  } else {
    // part 2 conditions
    // go in reverse path so we can go from E -> a
    // so the elevation of the destination square can be at most one less
    // than the elevation of your current square;
    if (col + 1 < matrix[row].length && matrix[row][col + 1] >= current - 1) {
      neighbors.push({ row, col: col + 1 });
    }

    if (col - 1 >= 0 && matrix[row][col - 1] >= current - 1) {
      neighbors.push({ row, col: col - 1 });
    }

    if (row + 1 < matrix.length && matrix[row + 1][col] >= current - 1) {
      neighbors.push({ row: row + 1, col });
    }

    if (row - 1 >= 0 && matrix[row - 1][col] >= current - 1) {
      neighbors.push({ row: row - 1, col });
    }
  }
  return neighbors;
};

/* 
https://en.wikipedia.org/wiki/Breadth-first_search
 1  procedure BFS(G, root) is
 2      let Q be a queue
 3      label root as explored
 4      Q.enqueue(root)
 5      while Q is not empty do
 6          v := Q.dequeue()
 7          if v is the goal then
 8              return v
 9          for all edges from v to w in G.adjacentEdges(v) do
10              if w is not labeled as explored then
11                  label w as explored
12                  w.parent := v
13                  Q.enqueue(w)
*/

const getPath = (matrix, part2, start, end = null) => {
  // let Q be a queue
  const queue = [];
  const visited = {};
  const [row, col] = start;

  // record 'a' location for part 2
  let goalKey;

  // label root as explored
  visited[`${row}-${col}`] = {
    key: `${row}-${col}`,
  };
  // Q.enqueue(root)
  queue.push({ row, col });

  // while Q is not empty do
  while (queue.length > 0) {
    // v := Q.dequeue()
    const { row, col } = queue.shift();
    const currentKey = `${row}-${col}`;

    // if v is the goal then stop
    if (!part2 && row === end[0] && col === end[1]) {
      break;
    }

    // if we reach 'a', then stop
    if (part2 && matrix[row][col] === 0) {
      break;
    }

    // for all edges from v to w in G.adjacentEdges(v) do
    const neighbors = getNeighbors(row, col, matrix, part2);
    for (let i = 0; i < neighbors.length; i++) {
      const { row: neighborRow, col: neighborCol } = neighbors[i];
      const key = `${neighborRow}-${neighborCol}`;

      // if w is not labeled as explored then
      if (key in visited) {
        continue;
      }

      // label w as explored
      // w.parent := v
      visited[key] = {
        key: currentKey,
      };

      if (part2 && matrix[neighborRow][neighborCol] === 0) {
        goalKey = key;
      }

      // Q.enqueue(w)
      queue.push(neighbors[i]);
    }
  }

  const path = [];
  let startKey = `${row}-${col}`;
  let currentKey = !part2 ? `${end[0]}-${end[1]}` : goalKey;

  // backtrack on visited nodes till we find the destination
  while (currentKey !== startKey) {
    //const [currentRow, currentCol] = currentKey.split("-").map(Number);
    path.push(currentKey);
    currentKey = visited[currentKey].key;
  }

  return path;
};

const drawPath = async (matrix, path, part2 = false) => {
  document.querySelector('body').style.fontSize = `${100/matrix[0].length*.7}vw` ;
  const map = document.querySelector('#app');
  map.innerHTML = "";
  for (let row = 0; row < matrix.length; row++) {
    const pathPoints = [];
    const mapRow = document.createElement('div');
    let rowLine = "";
    for (let col = 0; col < matrix[row].length; col++) {
      const current = matrix[row][col];
      pathPoints.push(current);
      if (path.includes(`${row}-${col}`) || (!part2 && current === "S")) {
        rowLine += "⚫";
      } else {
        let color = ["🌳", "🌲"][Math.floor(Math.random() * 2)];
        const currentChar = current.charCodeAt() - "a".charCodeAt();
        if (currentChar > 22) {
          color = "⚪";
        } else if (currentChar > 12) {
          color = "🟤";
        } else if (currentChar > 5) {
          color = [...[..."🌊".repeat(50)], "🦐", "🐟"][
            Math.floor(Math.random() * 52)
          ];
        } else if (currentChar > 2) {
          color = 
            ["🪵", "🪨"][
              Math.floor(Math.random() * 2)
            ];
        } else if (currentChar > 1) {
          color = [
            ...[..."🌳".repeat(50)],
            ...[..."🌲".repeat(50)],
            "🐅",
            "🦍",
            "🐘",
            "🦛",
            "🦏",
          ][Math.floor(Math.random() * 105)];
        }

        rowLine += color;
      }
    }
    mapRow.textContent = rowLine;
    map.appendChild(mapRow);
  }
  
  const hiker = document.createElement('div');
  hiker.textContent = '🚶';
  hiker.classList.add('hiker');
  app.appendChild(hiker);
  const {width, height} = app.getBoundingClientRect();
  
  path.reverse();
  let prevLeft = 0;
  
  for(const point of path) {
    const [top, left] = point.split('-').map(Number);
    hiker.style.top = `${(top/matrix.length)*height}px`;
    const nextLeft = (left/matrix[0].length)*width;
    hiker.style.transform = `scale(${nextLeft > prevLeft ? -1.5 : 1.5}, 1.5)`;
    hiker.style.left = `${nextLeft}px`;
    prevLeft = nextLeft;
    await waitseconds(100)
  }
  
  const phone = document.createElement('div')
  phone.textContent = '📱';
  hiker.appendChild(phone)
  
  
};

const init = (input) => {
  
  let start, end;



const data = input.split("\n").map((row) => [...row]);

const dataAsNumbers = data.map((row, rowIndex) =>
  row.map((char, colIndex) => {
    if (char === "S") {
      start = [rowIndex, colIndex];
      return 0;
    }
    if (char === "E") {
      end = [rowIndex, colIndex];
      return 25;
    } else return getCharValue(char) - getCharValue("a");
  })
);
  const path = getPath(dataAsNumbers, false, start, end);
  drawPath(data, path);
  console.log(path.length);
};

init(`abcccaaaaaaccccccccaaaaaccccccaaaaaaccccccaaaaaaaacccaaaaaaaccaaaacccccccccccccccccccccccccaaaaaacccccccccccccccccccccccccccccaaaaaa
abcccaaaaaacccccccaaaaaaccccaaaaaaaacccccccaaaaaaaaaaaaaaaaccaaaaacccccccccccccccccccccccccaaaaaacccccccccccccccccccccccccccccaaaaaa
abccccaaaaacaaaccaaaaaaaacccaaaaaaaaacccccccaaaaaaaaaaaaaaaacaaaaaacccccccccaaacccccccccccaaaaaaaaccccccccccaaccccccccccccccccaaaaaa
abccccaaaaccaaaaaaaaaaaaacccaaaaaaaaaacccccaaaaaaaaaaaaaaaaaaacaaaacccccccccaaaacccccccccaaaaaaaaaacccccccccaaaccccccccccccccccccaaa
abcccccccccaaaaaacccaacccccccccaaacaaaccccccaacccccccaaaaaaaaacaacccccccccccaaaacccccccccaaaaaaaaaacccccccccaaaccacaaccccccccccccaaa
abcccccccccaaaaaacccaacccccccccaaacccccccccccccccccccaaaacaaaacccccccaacaaccaaaccccccccccaccaaaaacacccccccccaaaacaaaaccccccccccccaac
abccccccccccaaaaacccccccccccccccacccaaaacccccccccccccaaaacccccccccccccaaaacccccccccccaacccccaaaaccccccccjjjjaaaaaaaaaccccccccccccccc
abccccccccccaaaacccccccccccccccccccaaaaacccccccccccccaaaccccccccccccccaaaaacccccccccaaaaaacccaaccccccccjjjjjjkkaaaacccccccccaacccccc
abcccccaaccccccccccccccccccccccccccaaaaaacccccccccccccaacccccccccccccaaaaaaccccccccccaaaaaccccccccccccjjjjjjjkkkkaacccccaacaaacccccc
abccaaaacccccccccccccccccccccccccccaaaaaaccccccccccccccccccccccccccccaaaacaccccccccaaaaaaaccccaacccccjjjjoooookkkkkkkklllaaaaaaacccc
abccaaaaaacccccccccccccccccccccccccaaaaacccccccccccccccccccccccccccccccaaccccccccccaaaaaaaaccaaaaccccjjjoooooookkkkkkkllllaaaaaacccc
abcccaaaaacccccccccccccccccccccccccccaaaccccccccaaaacccccccccccccccccccccccccccccccaaaaaaaaccaaaaccccjjooooooooppkkppplllllaccaacccc
abccaaaaaccccccccccccaccccccccccccccccccccccccccaaaacccccccccccccccccccccccccccccccccaaacacccaaaacccijjooouuuuoppppppppplllccccccccc
abcccccaacccccccccccaaaaaaaaccccccccccccccccccccaaaaccccaaccccccccaaacccccccccccccaacaaccccccccccccciijoouuuuuuppppppppplllcccaccccc
abcccccccccccccccccccaaaaaaccccccccccccccccccccccaaccccaaaacccccccaaaaccccccccccaaaaaaccccccccccccciiiiootuuuuuupuuuvvpppllccccccccc
abcccccccccccccccccccaaaaaaccaaaaacccccccccccccccccccccaaaacccccccaaaaccccccccccaaaaaaccccccccccccciiinnotuuxxxuuuuvvvpppllccccccccc
abccccccccccccccacccaaaaaaaacaaaaaaacccccccccccccccccccaaaacccccccaaacccccaaaaccaaaaaccccaaccccccciiiinnnttxxxxuuyyyvvqqqllccccccccc
abcccccccccccaaaaccaaaaaaaaaaaaaaaaaaccaacccccccccccccccccccccccccccccccccaaaacccaaaaaccaaacccccciiinnnnnttxxxxxyyyyvvqqqllccccccccc
abaaaacccccccaaaaaaaaaaaaaaaaaaaaaaaaaaaacccccccccccccccccccccccccccccccccaaaacccaaaaaacaaaccccciiinnnnttttxxxxxyyyyvvqqmmmccccccccc
abaaaaccccccccaaaaacccaaaaacaaaaaacaaaaaaccccccccccccccccaaccccccccccccccccaacccccccaaaaaaaaaaciiinnnnttttxxxxxyyyyvvqqqmmmccccccccc
SbaaaacccccccaaaaaccccaaaaaccaaaaaaaaaaaccccccccccccccccaaacaacccccccccccccccccccccccaaaaaaaaachhhnnntttxxxEzzzzyyvvvqqqmmmccccccccc
abaaaacccccccaacaacccccaaaaaaaacaaaaaaaaaccccccccccccccccaaaaaccccccccccccccccccccccccaaaaaaacchhhnnntttxxxxxyyyyyyvvvqqmmmdddcccccc
abaaaacccccccccccccccccccaaaaaacaaaaaaaaaacccccccccccccaaaaaaccccccccaaaccccccccccccccaaaaaaccchhhnnntttxxxxywyyyyyyvvvqqmmmdddccccc
abaacccccccccccccccccccaaaaaaacccccaaaaaaacccccccccccccaaaaaaaacccccaaaacccccccccccccaaaaaaacaahhhmmmttttxxwwyyyyyyyvvvqqmmmdddccccc
abcccccccccccccccccccccaaaaaaacaaccaaacccccccccccccccccaacaaaaacccccaaaacccccccccccccaaacaaaaaahhhmmmmtsssswwyywwwwvvvvqqqmmdddccccc
abcccccccccccccccaaaccccaaaaaaaaaacaaccaaccccccccccccccccaaacaccccccaaaacccccccccccccccccaaaaacahhhmmmmmsssswwywwwwwvvrrqqmmdddccccc
abcccccccccccccaaaaaaccccaaaaaaaaaccaaaacccccccccccccccccaacccccccccccccccccccccccaaaccccaaaaaaahhhhhmmmmssswwwwwrrrrrrrrmmmmddccccc
abcccccccccccccaaaaaaccccaaaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccaaaaaacccccaaaaachhhhhmmmmsswwwwrrrrrrrrrkkmdddccccc
abccccccccccccccaaaaaccccccaaaaaaaaaaaaaaaccccccccccccccccccccccccccccccccccccccaaaaaaccccaaaaacccchhggmmmssswwrrrrrkkkkkkkkdddacccc
abccaaaacccccccaaaaacccccccccaaaaaacaaaaacccccccccccccccccccccccccccccccccccccccaaaaaaccccaacaaaccccggggmmsssssrrlkkkkkkkkkdddaccccc
abccaaaacccccccaaaaacccccccccaaaaaaccccaacccccccccccccccccccccccccccccccccccccccaaaaaccccccccaaccccccgggmllssssrllkkkkkkkeeeddaccccc
abccaaaacccccccaaacccccccccccaaaaaacccccccccccccccccccaacccccccccccccccccccccccaaaaaacccccccccccccccccggllllssslllkkeeeeeeeeeaaacccc
abcccaaccccccccaaacaaaccccccaaaaaaaaaaacccccccccccccaaaaaacccccccccccccccccccccaaacaaacccccaacccccccccggglllllllllfeeeeeeeeaaaaacccc
abccccccccccaaaaaaaaaaccccccccccccaccaaaccacccccccccaaaaaaccccaaccaacccaaccccccaaaaaaacccccaaccccccccccggglllllllfffeeecccaaaaaacccc
abccccccccccaaaaaaaaacccccccccccccccaaaaaaaccccccccccaaaaaccccaaaaaacccaaaaaaccaaaaaacccaaaaaaaacccccccggggllllfffffccccccaacccccccc
abcccccccccccaaaaaaacccccccccccccccccaaaaaaccaacccccaaaaaccccccaaaaacccaaaaaacaaaaaaacccaaaaaaaaccccccccgggffffffffccccccccccccccccc
abccccccccccccaaaaaaacccccccccccccaaaaaaaaacaaaaccccaaaaacaaaaaaaaaacaaaaaaacaaaaaaaaaccccaaaacccccccccccggffffffacccccccccccccccaaa
abccccccccccccaaaaaaacaaccccccccccaaaaaaaaacaaaacccccaaaaaaaaaaaaaaaaaaaaaaacaaaaaaaaaacccaaaaacccccccccccaffffaaaaccccccccccccccaaa
abccccccccccccaaacaaaaaacccccccccccaaaaaaaacaaaaaaaaaaaaaaaaaaaaaaaaacaaaaaaacccaaacaaaccaaaaaacccccccccccccccccaaaccccccccccccccaaa
abccccccccccccaaccaaaaaccccccccccccccaaaaaaaccccaaaaaaaaaaaaccccaacccccaaaaaacccaaaccccccaaccaacccccccccccccccccaaacccccccccccaaaaaa
abcccccccccccccccaaaaaaaaccccccccccccaacccacccccccaaaaaaaaaaccccaacccccaaccccccccaccccccccccccccccccccccccccccccccccccccccccccaaaaaa`)

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.