JSFiddle - React, Tailwind, and code Playground
by Josh Pullen
HTML
<script src="https://unpkg.com/[email protected]/lib/browser/math.js"></script>
CSS
body {
margin: 0;
width: 100vw;
height: 100vh;
display: flex;
align-items: stretch;
background: #fcba03;
font-family: sans-serif;
}
.home {
flex-grow: 1;
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: 1fr;
grid-template-areas:
"nav"
"main";
}
.main {
grid-area: main;
display: flex;
justify-content: center;
align-items: center;
}
.levelButtons {
display: inline-grid;
grid-template-rows: repeat(3, auto);
grid-template-columns: repeat(2, auto);
}
.levelButton {
margin: 8px;
font-size: 24px;
background: #3903fc;
background: linear-gradient(0deg, rgba(57,3,252,1) 0%, rgba(94,49,255,1) 100%);
box-shadow:
inset 0 2px 6px rgba(255, 255, 255, 0.3),
inset 0 -4px 8px rgba(0, 0, 0, 0.3),
0 3px 8px rgba(25, 0, 117, 0.4);
border: none;
border-radius: 999px;
color: #fff;
padding: 12px 28px;
}
.question {
flex-grow: 1;
display: grid;
grid-template-rows: auto 1fr;
grid-template-columns: 2fr 1fr;
grid-template-areas:
"nav nav"
"workbox answers";
}
.nav {
grid-area: nav;
background: #362c0d;
display: flex;
padding: 8px;
font-size: 20px;
color: #fff;
}
.score {
margin-left: auto;
}
.workbox {
grid-area: workbox;
display: flex;
flex-direction: column;
justify-content: center;
}
.charButtons {
display: flex;
justify-content: center;
}
.charButton {
background: linear-gradient(0deg, rgba(195,16,201,1) 0%, rgba(239,66,245,1) 100%);
border: none;
margin: 2px;
width: 24px;
height: 24px;
font-size: 18px;
border-radius: 4px;
box-shadow:
inset 0 -1px 3px rgba(0, 0, 0, 0.4),
inset 0 1px 2px rgba(255, 255, 255, 0.3);
color: #fff;
text-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}
.charButton:disabled {
opacity: 0.4;
}
.equationArea {
display: flex;
align-self: center;
flex-direction: column;
align-items: stretch;
}
.equation {
display: flex;
margin: 8px 0;
}
.equation span {
display: flex;
...
JavaScript
import { html, render, useState } from "https://unpkg.com/htm/preact/standalone.module.js";
/*
function allStrings(charPool, prefix = "") {
let result = [];
if (prefix.length > 0) result.push(prefix);
for (let i = 0; i < charPool.length; i++) {
result = [
...result,
...allStrings(
[...charPool.slice(0, i), ...charPool.slice(i + 1)],
prefix + charPool[i]
)
];
}
return result;
}
const charOptions = ["2", "3", "6", "7", "8", "+", "×", "="];
console.log(JSON.stringify([... new Set(
allStrings(charOptions)
.filter(eq => {
if (eq.startsWith("+")) return false;
if (eq.startsWith("-")) return false;
if (eq.includes("=+")) return false;
if (eq.includes("=-")) return false;
if (eq.includes("+-")) return false;
if (eq.includes("-+")) return false;
if (eq.includes("++")) return false;
if (eq.includes("--")) return false;
return true;
})
.map(eq => {
eq = eq.replaceAll("=", "==");
eq = eq.replaceAll("×", "*");
eq = eq.replaceAll("÷", "/");
return eq;
}).filter(eq => {
try {
return math.evaluate(eq) === true;
} catch (err) {
return false;
}
})
.map(eq => {
eq = eq.replaceAll("==", "=");
eq = eq.replaceAll("*", "×");
eq = eq.replaceAll("/", "÷");
return eq;
})
.sort((a, b) => a.length - b.length)
)])
);
*/
const questions = [
{
charOptions: ["2", "4", "7", "8", "×", "÷", "="],
solutions: [
["2×4=8", "4×2=8", "8=2×4", "8=4×2"],
["8÷2=4", "4=8÷2"],
["8÷4=2", "2=8÷4"],
["4×7=28", "7×4=28", "28=4×7", "28=7×4"],
["28÷4=7", "7=28÷4"],
["28÷7=4", "4=28÷7"],
]
},
{
charOptions: ["1", "2", "4", "4", "8", "+", "-", "="],
solutions: [
["4=4"],
["4+4=8", "8=4+4"],
["8-4=4", "4=8-4"],
["12-4=8", "8=12-4"],
["12-8=4", "4=12-8"],
["4+8=12", "8+4=12", "12=4+8", "12=8+4"],
...