const { pipe } = await import("https://unpkg.com/bruh@1.0.18/src/util/index.mjs") const { listen, map, filter, forEach, tap } = await import("https://unpkg.com/bruh@1.0.18/src/util/iterable/async.mjs") const makePuzzle = (n = 4) => { const solvedPuzzle = [...Array(n)] .map((_, rowI) => [...Array(n)].map((_, colI) => rowI * n + colI + 1) ) solvedPuzzle[n - 1][n - 1] = null return [...Array(100)] .map(() => ["up", "down", "left", "right"][Math.floor(Math.random() * 4)] ) .reduce((puzzle, direction) => move(puzzle, direction), solvedPuzzle) } const move = (puzzle, direction) => { const result = puzzle.map(row => [...row]) const emptyRow = puzzle.findIndex(row => row.includes(null)) const emptyCol = puzzle[emptyRow].indexOf(null) const [fromRow, fromCol] = ({ up: [emptyRow + 1, emptyCol ], down: [emptyRow - 1, emptyCol ], left: [emptyRow , emptyCol + 1], right: [emptyRow , emptyCol - 1] })[direction] if (puzzle[fromRow]?.[fromCol]) { result[emptyRow][emptyCol] = puzzle[fromRow][fromCol] result[fromRow][fromCol] = null } return result } const display = puzzle => { console.clear() if (puzzle.flat().slice(0, -1).every((n, i) => n == i + 1)) { const name = puzzle.flat().slice(0, -1).length console.log(`You solved the "${name} puzzle" in ${moves} moves!`) return } const maxWidth = Math.max( ...puzzle.flat() .map(n => (n || "").toString().length) ) const table = puzzle .map(row => row .map(n => (n || "").toString() .padStart(maxWidth + 1) .padEnd(maxWidth + 2) ) .join("") ) .map(row => "\n" + row + "\n") .join("") console.log(table) } let currentPuzzle = makePuzzle( parseInt(prompt("Choose your difficulty level", 4)) ) let moves = 0 display(currentPuzzle) pipe( listen(document, "keydown"), map(({ key }) => ({ ArrowUp: "up", ArrowDown: "down", ArrowLeft: "left", ArrowRight: "right" })[key] ), filter(direction => direction != undefined), forEach(direction => { currentPuzzle = move(currentPuzzle, direction) moves++ display(currentPuzzle) }) )