JSFiddle - React, Tailwind, and code Playground

by Mario Siric

HTML

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <meta name="viewport" content="width=device-width" />

    <title>Boggle solver</title>

    <link rel="stylesheet" href="style.css" />
  </head>

  <body>
    <h1>Boggle solver algorithm</h1>

    <div class="controls" tabindex="0">
      <form id="toolbar">
        <div>
          <div id="sizing">
            <label for="size">Number of cells/rows</label>
            <input
              type="number"
              class="tool"
              id="size"
              min="2"
              max="48"
              value="4"
            />
            <button type="submit" id="resize">Resize</button>
          </div>
        </div>
      </form>
      <form id="form">
        <table id="table"></table>
        <button type="submit" id="solve">Solve</button>
      </form>
      <div id="result"></div>
    </div>
  </body>
</html>

CSS

#table {
  max-width: 1200px;
}

#table td {
  position: relative;
}

.input {
  text-transform: uppercase;
  max-width: 20px;
}

.span {
  position: absolute;
  right: 5px;
  color: white;
  font-weight: bold;
}

#result {
  word-break: break-word;
}

.highlight {
  background-color: red;
}

.success {
  background-color: green;
}

JavaScript

// a dumb dictionary sample, replace with actual words
const list = [
  "a",
  "e",
  "i",
  "o",
  "u",
];

class Node {
  constructor(key) {
    this.key = key;
    this.children = {};
    this.end = false;
  }
}

class Trie {
  constructor() {
    this.root = new Node(null);
  }
  insert(word) {
    if (!word.trim()) return undefined;
    let current = this.root;
    for (let i = 0; i < word.length; i++) {
      if (!current.children[word[i]]) {
        current.children[word[i]] = new Node(word[i]);
      }

      current = current.children[word[i]];

      if (i === word.length - 1) {
        current.end = true;
      }
    }
  }
  contains(word = "") {
    let current = this.root;
    for (let i = 0; i < word.length; i++) {
      if (!current.children[word[i]]) {
        return false;
      }
      current = current.children[word[i]];
    }
    return current.end;
  }
  find(prefix = "") {
    let current = this.root;
    for (let i = 0; i < prefix.length; i++) {
      if (!current.children[prefix[i]]) {
        return [];
      }
      current = current.children[prefix[i]];
    }
    const iterate = (prefix, node, words) => {
      const values = Object.values(node.children);
      for (let value of values) {
        if (value.end) words.push(prefix + value.key);
        iterate(prefix + value.key, value, words);
      }

      return words;
    };
    return iterate(prefix, current, [...(current.end ? [prefix] : [])]);
  }
}

let trie;

const movements = (i, j) => [
  { row: i, column: j + 1, move: "RIGHT" },
  { row: i + 1, column: j + 1, move: "BOTTOM_RIGHT" },
  { row: i + 1, column: j, move: "BOTTOM" },
  { row: i + 1, column: j - 1, move: "BOTTOM_LEFT" },
  { row: i, column: j - 1, move: "LEFT" },
  { row: i - 1, column: j - 1, move: "TOP_LEFT" },
  { row: i - 1, column: j, move: "TOP" },
  { row: i - 1, column: j + 1, move: "TOP_RIGHT" },
];

const addStep = (() => {
  let counter = 1;
  return (i, j, matrix, isWord, action, steps) => {
   ...