import fs from 'node:fs' const data = fs.readFileSync('input.txt', ({ encoding: "utf-8" }), data => data).split('\n') const paper = [] for (let y = 0; y < data.length; y++) { for (let x = 0; x < data[y].length; x++) { const char = data[y][x] paper.push({ pos: { x: x, y: y }, char: char }) } } class Puzzle { #directions = [] constructor() { this.i = 0 this.solutions = 0 this.#directions = [ [-1, -1], [-1, 0], [-1, +1], [0, -1], [0, +1], [+1, -1], [+1, 0,], [+1, +1] ] } shootInDirection(y, x, dy, dx, length) { const positions = [] for (let i = 1; i <= length; i++) { positions.push([y + (dy * i), x + (dx * i)]) } return positions } isCharacterAt(char, x, y) { const solutions = paper.filter(character => character.pos.x === x && character.pos.y === y && character.char === char) return solutions.length === 0 ? false : true } findCharacter(c) { return [...paper.filter(character => character.char === c)] } getDirections(x, y) { return [...new Set([ [Math.max(0, x - 1), Math.max(0, y - 1)], [x, Math.max(0, y - 1)], [Math.min(x + 1), Math.max(0, y - 1)], [Math.max(0, x - 1), y], [Math.min(x + 1), y], [Math.max(x - 1), y + 1], [x, Math.min(y + 1)], [Math.min(x + 1), Math.min(y + 1)], ])] } isInBoundary(x, y) { let max_width = data[0].length let max_height = data.length let within_width = x >= 0 && x <= max_width ? true : false let within_height = y >= 0 && y <= max_height ? true : false return within_width && within_height ? true : false } checkForWord(coords, word) { for (let i = 0; i < coords.length; i++) { let [y, x] = coords[i] if (!this.isInBoundary(x, y)) return false if (!this.isCharacterAt(word[i + 1], x, y)) return false } return true } solve(puzzle) { console.log("--- solve ".padEnd(50, "-")) const needed_length = puzzle.split('').length const word = puzzle.split('') const letter_positions = word.map(letter => { return { letter: letter, pos: this.findCharacter(letter).map(l => l.pos) } }) const starting_letter = letter_positions[0] let sum = 0 for (let i = 0; i < starting_letter.pos.length; i++) { for (let j = 0; j < this.#directions.length; j++) { let [dy, dx] = this.#directions[j] let coords = this.shootInDirection(starting_letter.pos[i].y, starting_letter.pos[i].x, dy, dx, word.length - 1) if (this.checkForWord(coords, word)) sum += 1 } } let total_words_possible = starting_letter.pos.length console.log(sum, "of possible", total_words_possible) } } const p = new Puzzle() p.solve("XMAS")