92 lines
3.0 KiB
JavaScript
92 lines
3.0 KiB
JavaScript
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") |