JSFiddle - React, Tailwind, and code Playground
JavaScript
// based on https://www.keithschwarz.com/interesting/code/?dir=lights-out
var puzzle = [];
var toggle = [];
var solution = [];
// initialize toggle matrix where each cell in puzzle has a corresponding row
// each row in toggle is the same length as the total number of cells in the puzzle
// the true values in each row determain which tiles are toggled when a tile is pressed
// in this case, this is the pressed tile and each tile above, below, left, and right of it
function createToggle(p) {
let t = Array.from({length: area}, () => Array(area).fill(false));
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
for (let yOff = -1; yOff <= 1; yOff++) {
for (let xOff = -1; xOff <= 1; xOff++) {
let [xNew, yNew] = [x + xOff, y + yOff];
if (Math.abs(xOff) + Math.abs(yOff) < 2 && 0 <= yNew && yNew < height && 0 <= xNew && xNew < width) {
t[x + y * width][xNew + yNew * width] = true;
}
}
}
}
}
return t
}
// solve the puzzle using its toggle matrix and a bunch of fancy math formulas by people smarter than me
// for a great explanation, check the link at the top
function solve(puzzle, toggle) {
// initialize s, create new copies of p and t
let p = puzzle.slice(0);
let t = toggle.map((arr) => {return arr.slice(0)});
let s = new Array(area).fill(false);
// gaussian elimination
let yNext = 0;
for (let x = 0; x < area; x++) {
// find next pivot row
let pivot = -1;
for (let y = yNext; y < area; y++) {
if (t[y][x]) {
pivot = y;
break
}
}
if (pivot == -1) continue
// swap index of pivot row and next row in toggle and puzzle
[t[pivot], t[yNext]] = [t[yNext], t[pivot]];
[p[pivot], p[yNext]] = [p[yNext], p[pivot]];
// apply XOR to...