Saturday 2 November 2024

Halloween 2024

I spent a happy few hours working on these challenges, these are my solutions:

function createMagicPotion(potions, target) {
  const c = potions.reduce((acc, _, index) => {
    for (let i = index + 1; i < potions.length; i++) {
      if (potions[index] + potions[i] === target) {
        acc.push([index, i]);
      }
    }
    return acc;
  }, []);
  return c[0].length === 1
    ? c[0]
    : c[0].length > 1
      ? c.sort((a, b) => a[1] - b[1])[0]
      : undefined;
}
console.log(createMagicPotion([4, 5, 6, 2], 8));
console.log(createMagicPotion([1, 2, 3, 4], 9));
console.log(createMagicPotion([1, 2, 3, 4], 5));

function battleHorde(zombies, humans) {
  const iteration = Math.max(zombies.length, humans.length);
  const z = zombies.split("").map((e) => Number(e));
  const h = humans.split("").map((e) => Number(e));
  for (let i = 0; i < iteration; i++) {
    if (i + 1 < iteration) {
      console.log(`zombie ${z[i]} vs human ${h[i]}`);
      console.log(`start: humans ${h.join("")}, zombies ${z.join("")}`);
      if (z[i] === h[i]) {
        console.log("tie");
      } else {
        if (z[i] > h[i]) {
          console.log(`zombie wins (${z[i] - h[i]})`);
          z[i + 1] = z[i + 1] + (z[i] - h[i]);
        } else {
          console.log(`human wins (${h[i] - z[i]})`);
          h[i + 1] = h[i + 1] + (h[i] - z[i]);
        }
      }
      console.log(`end: humans ${h.join("")}, zombies ${z.join("")}`);
    } else {
      if (z[i] > h[i]) {
        return `${z[i] - h[i]}z`;
      } else if (z[i] < h[i]) {
        return `${h[i] - z[i]}h`;
      } else {
        return "x";
      }
    }
  }
}
console.log(battleHorde("242", "334"));
console.log(battleHorde("444", "282"));

function findSafestPath(dream) {
  function findPaths(arr, path, i, j, paths) {
    if (i === M - 1 && j === N - 1) {
      path.push(arr[i][j]);
      paths.push(path.reduce((a, c) => a + c, 0));
      path.pop();
      return;
    }
    if (i < 0 || i >= M || j < 0 || j >= N) {
      return;
    }
    path.push(arr[i][j]);
    if (j + 1 < N) {
      findPaths(arr, path, i, j + 1, paths);
    }
    if (i + 1 < M) {
      findPaths(arr, path, i + 1, j, paths);
    }
    path.pop();
  }
  const arr = JSON.parse(JSON.stringify(dream));
  const path = [];
  const paths = [];
  let i = 0,
    j = 0;
  const M = arr.length;
  const N = arr[0].length;
  findPaths(arr, path, i, j, paths);
  return Math.min(...paths);
}
console.log(
  findSafestPath([
    [1, 3, 1],
    [1, 5, 1],
    [4, 2, 1],
  ]),
);

function findTheKiller(whisper, suspects) {
  const regex = new RegExp(
    whisper.substring(whisper.length - 1) === "$"
      ? whisper.replaceAll("~", ".")
      : `${whisper.replaceAll("~", ".")}.*`,
    "i",
  );
  return suspects
    .filter((suspect) => regex.exec(suspect)?.[0] === suspect)
    .join(",");
}
console.log(
  findTheKiller("d~~~~~a", [
    "Dracula",
    "Freddy Krueger",
    "Jason Voorhees",
    "Michael Myers",
  ]),
);
console.log(findTheKiller("~r~dd~", ["Freddy", "Freddier", "Fredderic"]));
console.log(findTheKiller("~r~dd$", ["Freddy", "Freddier", "Fredderic"]));
console.log(findTheKiller("mi~~def", ["Midudev", "Midu", "Madeval"]));

function escapePyramidHead(room) {
  const rows = room.length;
  const cols = room[0].length;

  // Find start (▲) and end (T) positions
  let start, end;
  for (let y = 0; y < rows; y++) {
    for (let x = 0; x < cols; x++) {
      if (room[y][x] === "") {
        start = [x, y];
      } else if (room[y][x] === "T") {
        end = [x, y];
      }
    }
  }

  // If either start or end not found
  if (!start || !end) {
    return -1;
  }

  // Possible moves: up, right, down, left
  const directions = [
    [-1, 0], // left
    [0, 1], // down
    [1, 0], // right
    [0, -1], // up
  ];

  // Helper function to check if a point is valid
  function isValidPoint(row, col) {
    return row >= 0 && row < rows && col >= 0 && col < cols;
  }

  // Initialize visited array and queue for BFS
  const visited = Array(rows)
    .fill()
    .map(() => Array(cols).fill(false));
  const queue = [];

  // Start BFS
  queue.push({ y: start[1], x: start[0], distance: 0 });
  visited[start[1]][start[0]] = true;

  while (queue.length > 0) {
    const current = queue.shift();

    // Check if we reached the end point
    if (current.y === end[1] && current.x === end[0]) {
      return current.distance;
    }

    // Try all possible directions
    for (const [dx, dy] of directions) {
      const newY = current.y + dy;
      const newX = current.x + dx;

      // Check if the new position is valid and not visited
      if (
        isValidPoint(newY, newX) &&
        !visited[newY][newX] &&
        room[newY][newX] !== "#"
      ) {
        visited[newY][newX] = true;
        queue.push({
          y: newY,
          x: newX,
          distance: current.distance + 1,
        });
      }
    }
  }

  // If we get here, no path was found
  return -1;
}

console.log(
  escapePyramidHead([
    [".", ".", "#", ".", ""],
    ["#", ".", "#", ".", "#"],
    [".", ".", ".", ".", "."],
    ["#", "#", "#", ".", "#"],
    ["T", ".", ".", ".", "."],
  ]),
);
console.log(
  escapePyramidHead([
    ["", ".", "#", "."],
    [".", ".", ".", "."],
    ["T", ".", ".", "#"],
    [".", "#", "#", "#"],
  ]),
);
console.log(
  escapePyramidHead([
    ["#", "#", "#"],
    ["", ".", "#"],
    [".", "#", "T"],
  ]),
);