JSFiddle - React, Tailwind, and code Playground

by Станислав Некрасов

HTML

<div class="board">
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
  <div class="cell"></div>
</div>

CSS

.board {
  display: grid;
  grid-template-rows: repeat(4, 40px);
  grid-template-columns: repeat(4, 40px);
}

.cell {
  border: 1px solid #8e72e8;
  background: #000;
}

.cell.active {
  border: 1px solid #8e72e8;
  background: #fff;
}

JavaScript

const cells = [...document.querySelectorAll('.cell')];
const count = cells.length, p = [1];
for (let i = 1; i < count; i++) p.push(p[i - 1] * 2);

let state = 0, stack = [];
let program = '012+~-';

let execute = (pos=0) => {
	if (pos >= program.length) return pos;
  let number = Number.parseInt(program[pos], 16);
  if (!isNaN(number)) {
  	stack.push(number);
  } else if (program[pos] == '+') {
  	let c = stack.pop();
  	state |= p[c];
    cells[c].classList.toggle('active', true);
  } else if (program[pos] == '~') {
  	let c = stack.pop();
    state ^= p[c];
    cells[c].classList.toggle('active');
  } else if (program[pos] == '-') {
  	let c = stack.pop();
    state ^= state & p[c];
    cells[c].classList.toggle('active', false);
  } else if (program[pos] == '.') {
  	return pos + 1;
  }
  return execute(pos + 1);
}

let update = () => cells.forEach((cell, num) => {
 	cell.classList.toggle('active', state & p[num]);
});

cells.forEach(
	(cell, num) => cell.addEventListener('click', event => {
    state ^= p[num];
    execute();
    update();
  })
)