Letter Jam word search

by thirdender

HTML

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.2.3/css/bootstrap.min.css">
<div class="input-group m-3 w-auto">
  <input type="text" class="form-control" aria-label="Letters" placeholder="Enter up to 5 letters to search" aria-describedby="search-button">
  <button class="btn btn-primary" type="button" id="search-button" disabled>Search</button>
</div>

<ul class="list-group m-3"></ul>

JavaScript

const alphabet = 'abcdefghijklmnopqrstuvwxyz'.split('');
const input = document.querySelector('input');
const button = document.querySelector('button');
const list = document.querySelector('ul');

(async () => {
  // Read in /usr/share/dict/words, lowercasing words and removing non-alphabet characters
  const nonAlphaRe = /\W/g;
  const words = String(await fetch('https://api.github.com/gists/8927565').then((res) => res.json()).then((data) => data.files.words.content))
    .split('\n')
    .map((word) => word.toLowerCase().replace(nonAlphaRe, ''));

  // Map all words to the unique letters that make up each word
  const dictionary = {};
  for (const word of words) {
    if (word.length < 5) {
      continue;
    }
    const letters = [...new Set(word.split(''))].sort().join('');
    if (!(letters in dictionary)) {
      dictionary[letters] = [];
    }
    dictionary[letters].push(word);
  }

	button.removeAttribute('disabled');
	button.addEventListener('click', () => {
    const inputLetters = input.value.toLowerCase().split(''); 
    const results = {};
    for (const letter of alphabet) {
      if (inputLetters.includes(letter)) {
        continue;
      }
      const allLetters = [...inputLetters, letter].sort().join('');
      for (let i = 1; i < 32; i++) {
        let key = '';
        for (let j = 0; j < 5; j++) {
          if (Math.pow(2, j) & i) {
            key += allLetters[j];
          }
        }
        if (key in dictionary) {
          results[key] = dictionary[key];
        }
      }
    }
    [...list.childNodes].forEach((el) => list.removeChild(el));
    [...new Set(Object.values(results).reduce((acc, arr) => [...acc, ...arr], []))]
      .sort()
      .forEach((word) => {
      	const li = document.createElement('li');
        li.className = 'list-group-item';
        li.textContent = word;
        list.appendChild(li);
			});
	});
})();