const fs = require("fs"); const input = fs.readFileSync("input", "utf-8").trim(); const tiles = Object.fromEntries( input .split("\n\n") .map((tile) => tile.split("\n")) .map((line) => [line[0].match("[0-9]+")[0], line.slice(1)]) ); // console.log(tiles); const tileEdges = {}; for (const [id, tile] of Object.entries(tiles)) { const n = tile[0]; const w = tile.map((line) => line[0]).join(""); const e = tile.map((line) => line[line.length - 1]).join(""); const s = tile[tile.length - 1]; tileEdges[id] = [n, w, e, s]; } // console.log(tileEdges); const edgeMap = {}; const reverse = (str) => str.split("").reverse().join(""); const isCanonical = (edge) => edge < reverse(edge); for (const [id, edges] of Object.entries(tileEdges)) { for (const edge of edges) { const key = isCanonical(edge) ? edge : reverse(edge); if (typeof edgeMap[key] === "undefined") { edgeMap[key] = []; } edgeMap[key].push(id); if (edgeMap[key].length > 2) { console.warn( "Assumption does not hold: One edge is present in more than two tiles" ); } } } // console.log(edgeMap); const edgeTiles = new Set(); const cornerTiles = new Set(); for (const ids of Object.values(edgeMap)) { if (ids.length === 1) { const id = ids[0]; if (edgeTiles.has(id)) { edgeTiles.delete(id); cornerTiles.add(id); } else { edgeTiles.add(id); } } } console.log(Array.from(cornerTiles).reduce((a, b) => a * b, 1));