Boolean Solver - Interactive Truth Table Explorer

Boolean Solver

Interactive Truth Table Explorer with Walsh-Hadamard Transform, Shannon Split, and NAND Circuit Synthesis

Explore all boolean functions interactively — complete for n=0,1,2,3, including the trivial cases. Click cells to build any truth table and watch three live solvers analyze your function in real-time.


Overview

The Boolean Solver is an interactive React + Three.js tool that transforms abstract boolean algebra into a tangible, visual experience. It enables you to explore all possible boolean functions for n=0 through n=3 inputs (1, 4, 16, and 256 functions respectively) through direct manipulation of truth tables.

This tool was originally developed as part of a deep dive conversation exploring the mathematical foundations of computing — how boolean logic forms the bedrock of all digital systems. It demonstrates that even the simplest questions (“What are all possible 2-input boolean functions?”) lead to rich, complex insights when approached systematically.

Physics Connection: Boolean logic is the foundation of digital computation, which in turn underlies all modern physics simulations and quantum computing. The discrete nature of boolean values (0/1, TRUE/FALSE) mirrors the binary states found in quantum bits (qubits) and classical digital circuits, making this tool relevant to both computer science and theoretical physics.


Features

1. Interactive Truth Table Editor

2. Function Identification

3. Fast Walsh-Hadamard Transform

The Walsh-Hadamard transform is to boolean functions what the Fourier transform is to signals. It decomposes any boolean function into its spectral components, revealing mathematical properties.

What it calculates:

Mathematical insight:

4. Shannon Split Analysis

Decomposes the boolean function based on Shannon’s information theory, splitting by the first variable (x1).

What it reveals:

Possible relationships:

5. Minimal-Depth NAND Circuit Synthesis

Finds the minimum-depth network of NAND gates that implements your function. NAND is universal — any boolean function can be implemented using only NAND gates.

Why NAND?

What it provides:


How to Use

Getting Started

  1. Select n — Choose the number of inputs (0-3) from the top navigation
  2. Click cells — In the truth table grid, click any cell to toggle its value
  3. Watch it update — The function name, Walsh coefficients, Shannon analysis, and NAND synthesis all update in real-time
  4. Explore 3D — Click “view in 3D” to see a spatial visualization of all functions

Learning Path

Beginner

Intermediate

Advanced


Mathematical Foundations

Boolean Functions Basics

A boolean function with n inputs has 2^n possible input combinations. Therefore, there are 2^(2^n) possible boolean functions.

nInput CombinationsPossible Functions
012
124
2416
38256

Walsh-Hadamard Transform

For a boolean function f: {0,1}^n → {0,1}, the Walsh-Hadamard transform computes:

Ĝ(S) = (1/2^n) * Σ_{x∈{0,1}^n} (-1)^{f(x)} * (-1)^{S·x}

Where S is a subset of input variables, and S·x is the dot product (mod 2).

Properties:

Shannon Entropy

For a boolean function, the entropy measures its information content:

H = - Σ_{x∈{0,1}} P(x) log₂ P(x)

Where P(x) is the probability of each output value.

Interpretation:

Circuit Complexity


All 16 Boolean Functions for n=2

Here’s a complete reference of all possible 2-input boolean functions:

Constants (0 and 4 ones)

NameTruth TableOnesProperties
FALSE0 0 / 0 00Constant 0
TRUE1 1 / 1 14Constant 1

Single-Output (1 one)

NameTruth TableOnesMeaning
NOR0 0 / 0 11NOT (A OR B)
A AND NOT B0 0 / 0 11A ∧ ¬B
NOT A AND B0 0 / 1 01¬A ∧ B
AND0 0 / 0 11A ∧ B

Two-Output (2 ones)

NameTruth TableOnesMeaning
XOR0 1 / 1 02A ⊕ B (differ)
XNOR1 0 / 0 12A ≡ B (same)
NOT A1 1 / 0 02¬A (ignore B)
NOT B1 0 / 1 02¬B (ignore A)
A0 0 / 1 12A (ignore B)
B0 1 / 0 12B (ignore A)

Three-Output (3 ones)

NameTruth TableOnesMeaning
OR0 1 / 1 13A ∨ B
NAND1 1 / 1 03¬(A ∧ B)
A→B1 0 / 1 13A implies B
B→A1 1 / 0 13B implies A

Properties and Patterns

Symmetry

Boolean functions exhibit beautiful mathematical symmetries:

Linearity

Linear functions can be expressed as:

f(A,B) = a ⊕ b·A ⊕ c·B  (where ⊕ is XOR/addition mod 2)

For n=2, the linear functions are:

Non-linear functions (like AND, OR) have non-zero interaction coefficients (c₁₂ ≠ 0).

Balance

A function is balanced if it has an equal number of 0 and 1 outputs.

For n=2:

Correlation Immunity

A function is correlation immune if its output doesn’t leak information about any subset of its inputs. This property is important in cryptography.


3D Visualization

The 3D visualization maps each boolean function to a point in 3D space based on its Walsh-Hadamard coefficients.

What You See

Axes Meaning

Interpretation

The 3D visualization reveals:

Controls


Source Code

The Boolean Solver is implemented as a comprehensive React + Three.js application. Below is the complete source code extracted from the conversation.

Core Algorithm Functions

// Shared math utilities - generalized to any n = 0..3

// Function names for all boolean functions
const NAMES = {
  0: ["FALSE", "TRUE"],
  1: ["FALSE", "NOT x1", "x1", "TRUE"],
  2: [
    "FALSE", "NOR", "¬A∧B", "¬A", "A∧¬B", "¬B", "XOR", "NAND",
    "AND", "XNOR", "B", "A→B", "A", "B→A", "OR", "TRUE",
  ],
};

// Get function name for given n and index
function getName(n, idx) {
  if (n <= 2) return NAMES[n][idx];
  return `table ${idx}`;
}

// Create input signal for variable at position varIdx
function inputSignal(n, varIdx) {
  let val = 0;
  for (let r = 0; r < 1 << n; r++) {
    const bit = (r >> (n - 1 - varIdx)) & 1;
    val |= bit << r;
  }
  return val;
}

// Fast Walsh-Hadamard Transform
function fwht(arr) {
  const a = arr.slice();
  const len8 = a.length;
  for (let len = 1; len < len8; len <<= 1) {
    for (let i = 0; i < len8; i += len << 1) {
      for (let j = i; j < i + len; j++) {
        const u = a[j], v = a[j + len];
        a[j] = u + v;
        a[j + len] = u - v;
      }
    }
  }
  return a.map((v) => v / len8);
}

// Compute Walsh coefficients for a given function
function computeWalsh(n, tableIndex) {
  const size = 1 << n;
  const pm = Array.from({ length: size }, (_, r) => 1 - 2 * ((tableIndex >> r) & 1));
  return fwht(pm);
}

// Create subset label for coefficients
function subsetLabel(n, idx) {
  if (idx === 0) return "c∅";
  const vars = [];
  for (let v = 0; v < n; v++) if ((idx >> (n - 1 - v)) & 1) vars.push(v + 1);
  return `c{${vars.join(",")}}`;
}

// Shannon split by first variable
function shannonSplit(n, tableIndex) {
  if (n === 0) return null;
  const half = 1 << (n - 1);
  const mask = (1 << half) - 1;
  const f0 = tableIndex & mask;
  const f1 = (tableIndex >> half) & mask;
  let relation;
  if (f0 === f1) relation = "top = bottom → x1 is irrelevant";
  else if (f0 === ((~f1) & mask)) relation = "bottom = invert(top) → XOR-with-x1 structure";
  else relation = "no simple copy/invert relation";
  return { f0, f1, relation, subN: n - 1 };
}

// Synthesize minimal-depth NAND circuit
function synthesizeNand(n, target) {
  if (n === 0) return null;
  const mask = (1 << (1 << n)) - 1;
  let found = {};
  // Start with input signals
  for (let v = 0; v < n; v++) found[inputSignal(n, v)] = { depth: 0, expr: `x${v + 1}` };
  
  if (target in found) return found[target];
  
  // Iterative synthesis
  for (let round = 0; round < 10 && !(target in found); round++) {
    const keys = Object.keys(found).map(Number);
    const additions = {};
    for (let i = 0; i < keys.length; i++) {
      for (let j = i; j < keys.length; j++) {
        const a = keys[i], b = keys[j];
        const val = (~(a & b)) & mask;
        if (!(val in found) && !(val in additions)) {
          const exprA = found[a].expr, exprB = found[b].expr;
          additions[val] = { 
            depth: Math.max(found[a].depth, found[b].depth) + 1, 
            expr: a === b ? `NAND(${exprA},${exprA})` : `NAND(${exprA},${exprB})` 
          };
        }
      }
    }
    found = { ...found, ...additions };
  }
  return found[target] || null;
}

// Count relevant variables
function countRelevant(n, tableIndex) {
  let count = 0;
  const size = 1 << n;
  for (let v = 0; v < n; v++) {
    const p = n - 1 - v;
    let relevant = false;
    for (let r = 0; r < size; r++) {
      const rp = r ^ (1 << p);
      if (((tableIndex >> r) & 1) !== ((tableIndex >> rp) & 1)) { 
        relevant = true; 
        break; 
      }
    }
    if (relevant) count++;
  }
  return count;
}

// Get x, y, z coordinates from Walsh coefficients
function xyz(n, tableIndex) {
  const w = computeWalsh(n, tableIndex);
  const get = (v) => {
    if (v >= n) return 0;
    const idx = 1 << (n - 1 - v);
    return w[idx];
  };
  return { x: get(0), y: get(1), z: get(2) };
}

React Component - Solver Page

// Main Solver component
function SolverPage({ n, tableIndex, setTableIndex, onView3D }) {
  const size = 1 << n;
  const toggleCell = (r) => setTableIndex((t) => t ^ (1 << r));
  const walsh = useMemo(() => computeWalsh(n, tableIndex), [n, tableIndex]);
  const shannon = useMemo(() => shannonSplit(n, tableIndex), [n, tableIndex]);
  const nand = useMemo(() => synthesizeNand(n, tableIndex), [n, tableIndex]);
  const fmt = (v) => (v > 0 ? "+" : "") + v.toFixed(2).replace(/\.00$/, "");
  const bitsOf = (r) => Array.from({ length: n }, (_, k) => (r >> (n - 1 - k)) & 1).join("");

  return (
    <div className="max-w-3xl mx-auto space-y-6">
      <header>
        <h1 className="text-sm tracking-[0.2em] text-slate-400 uppercase">
          Boolean Solver
        </h1>
        <p className="text-xs text-slate-500 mt-1">
          n={n} · complete for n=0,1,2,3  including the trivial cases
        </p>
      </header>

      {/* Truth Table Editor */}
      <div>
        <div className={`grid gap-1 ${
          size <= 2 ? "grid-cols-2 w-32" : 
          size <= 4 ? "grid-cols-2 w-32" : 
          size <= 8 ? "grid-cols-4 w-64" : "grid-cols-8 w-[34rem]"
        }`}>
          {Array.from({ length: size }, (_, r) => r).map((r) => {
            const on = (tableIndex >> r) & 1;
            return (
              <button
                key={r}
                onClick={() => toggleCell(r)}
                className={`aspect-square rounded border flex flex-col 
                  items-center justify-center text-[9px] transition-colors ${
                  on ? "bg-teal-500/30 border-teal-400 text-teal-200" : 
                       "bg-slate-800/40 border-slate-700 text-slate-500"
                }`}
              >
                <span>{n === 0 ? "—" : bitsOf(r)}</span>
                <span className="text-[12px] font-semibold">{on}</span>
              </button>
            );
          })}
        </div>
        <div className="mt-2 text-xl text-teal-300 font-semibold">
          {getName(n, tableIndex)}
        </div>
        <div className="text-[10px] text-slate-600">
          table index {tableIndex} of {1 << size}
        </div>
      </div>

      {/* Walsh-Hadamard Transform Display */}
      <section className="border border-slate-800 rounded-lg p-4 space-y-2">
        <div className="text-xs text-slate-400 uppercase tracking-wide">
          Fast Walsh-Hadamard transform
        </div>
        <div className={`grid gap-2 text-center ${
          size <= 4 ? "grid-cols-4" : size <= 8 ? "grid-cols-4" : "grid-cols-8"
        }`}>
          {walsh.map((v, i) => (
            <div key={i} className="bg-slate-900/60 rounded p-2">
              <div className="text-[9px] text-slate-500">{subsetLabel(n, i)}</div>
              <div className="text-sm text-teal-300">{fmt(v)}</div>
            </div>
          ))}
        </div>
      </section>

      {/* Shannon Split Display */}
      <section className="border border-slate-800 rounded-lg p-4 space-y-2">
        <div className="text-xs text-slate-400 uppercase tracking-wide">
          Shannon split by x1
        </div>
        {shannon ? (
          <>
            <div className="grid grid-cols-2 gap-3 text-sm">
              <div className="bg-slate-900/60 rounded p-2">
                <div className="text-[9px] text-slate-500">top (x1=0)</div>
                <div className="text-amber-300">{getName(shannon.subN, shannon.f0)}</div>
              </div>
              <div className="bg-slate-900/60 rounded p-2">
                <div className="text-[9px] text-slate-500">bottom (x1=1)</div>
                <div className="text-amber-300">{getName(shannon.subN, shannon.f1)}</div>
              </div>
            </div>
            <p className="text-xs text-slate-400">{shannon.relation}</p>
          </>
        ) : (
          <p className="text-xs text-slate-500">n=0 has no variables  nothing to split.</p>
        )}
      </section>

      {/* NAND Synthesis Display */}
      <section className="border border-slate-800 rounded-lg p-4 space-y-2">
        <div className="text-xs text-slate-400 uppercase tracking-wide">
          Minimal-depth NAND synthesis
        </div>
        {nand ? (
          <>
            <div className="text-xs text-slate-500">depth {nand.depth}</div>
            <div className="text-sm text-pink-300 break-words">{nand.expr}</div>
          </>
        ) : n === 0 ? (
          <p className="text-xs text-slate-500">
            n=0 has no inputs  the function is a bare constant, not a circuit.
          </p>
        ) : (
          <p className="text-xs text-slate-500">not found within search bound</p>
        )}
      </section>

      <button
        onClick={onView3D}
        className="flex items-center gap-2 text-xs px-4 py-2 rounded 
                  border border-teal-500/40 bg-teal-500/15 text-teal-200"
      >
        view in 3D 
      </button>
    </div>
  );
}

3D Visualization Component

// 3D visualization of all boolean functions
function View3DPage({ n, tableIndex, onBack }) {
  const mountRef = useRef(null);
  const liveRef = useRef({});
  const highlight = useMemo(() => xyz(n, tableIndex), [n, tableIndex]);
  const highlightT = useMemo(() => countRelevant(n, tableIndex), [n, tableIndex]);
  const [showDet, setShowDet] = useState(true);
  const [showQ, setShowQ] = useState(true);
  const [qCount, setQCount] = useState(60);
  const [seedTick, setSeedTick] = useState(0);
  const [minT, setMinT] = useState(0);

  // Quantum stand-in points (pseudo-random for visualization)
  const quantumPoints = useRef(randomQuantumSample(qCount, 0));
  const reseed = () => {
    quantumPoints.current = randomQuantumSample(qCount, Date.now());
    setSeedTick((t) => t + 1);
  };

  useEffect(() => {
    // Three.js setup
    const mount = mountRef.current;
    const width = mount.clientWidth, height = mount.clientHeight;
    const scene = new THREE.Scene();
    scene.background = new THREE.Color(0x0a0e16);
    
    const camera = new THREE.PerspectiveCamera(45, width / height, 0.1, 100);
    camera.position.set(6, 4.5, 7);
    camera.lookAt(0, 0, 0);
    
    const renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setSize(width, height);
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    mount.appendChild(renderer.domElement);

    const group = new THREE.Group();
    scene.add(group);

    // Axes
    const axisLen = SCALE * 1.35;
    const axisMat = new THREE.LineBasicMaterial({ color: 0x3a4a5c });
    [
      [new THREE.Vector3(-axisLen, 0, 0), new THREE.Vector3(axisLen, 0, 0)],
      [new THREE.Vector3(0, -axisLen, 0), new THREE.Vector3(0, axisLen, 0)],
      [new THREE.Vector3(0, 0, -axisLen), new THREE.Vector3(0, 0, axisLen)],
    ].forEach(([a, b]) => 
      group.add(new THREE.Line(
        new THREE.BufferGeometry().setFromPoints([a, b]), 
        axisMat
      ))
    );

    // Cube edges
    const cubeEdges = new THREE.EdgesGeometry(
      new THREE.BoxGeometry(SCALE * 2, SCALE * 2, SCALE * 2)
    );
    group.add(new THREE.LineSegments(
      cubeEdges, 
      new THREE.LineBasicMaterial({ color: 0x1c2733 })
    ));

    // Deterministic points (all boolean functions)
    const total = 1 << (1 << n);
    const detGroup = new THREE.Group();
    const sphereGeo = new THREE.SphereGeometry(n <= 1 ? 0.09 : 0.055, 10, 10);
    
    for (let i = 0; i < total; i++) {
      const p = xyz(n, i);
      const t = countRelevant(n, i);
      const mesh = new THREE.Mesh(
        sphereGeo, 
        new THREE.MeshBasicMaterial({ color: T_COLORS[t] })
      );
      mesh.position.set(p.x * SCALE, p.y * SCALE, p.z * SCALE);
      mesh.userData = { t };
      detGroup.add(mesh);
    }
    group.add(detGroup);

    // Quantum stand-in points
    const qGroup = new THREE.Group();
    const qSphereGeo = new THREE.SphereGeometry(0.045, 8, 8);
    const qMat = new THREE.MeshBasicMaterial({ color: 0xf472b6 });
    
    function rebuildQuantum() {
      qGroup.clear();
      quantumPoints.current.forEach((p) => {
        const mesh = new THREE.Mesh(qSphereGeo, qMat.clone());
        mesh.position.set(p.x * SCALE, p.y * SCALE, p.z * SCALE);
        mesh.userData = { t: p.t };
        qGroup.add(mesh);
      });
    }
    rebuildQuantum();
    group.add(qGroup);

    // Highlight marker for selected function
    const hGeo = new THREE.SphereGeometry(0.13, 16, 16);
    const hMat = new THREE.MeshBasicMaterial({ color: 0xfbbf24 });
    const hMesh = new THREE.Mesh(hGeo, hMat);
    hMesh.position.set(highlight.x * SCALE, highlight.y * SCALE, highlight.z * SCALE);
    group.add(hMesh);
    
    const ringGeo = new THREE.RingGeometry(0.18, 0.22, 24);
    const ringMat = new THREE.MeshBasicMaterial({ 
      color: 0xfbbf24, 
      side: THREE.DoubleSide, 
      transparent: true, 
      opacity: 0.6 
    });
    const ring = new THREE.Mesh(ringGeo, ringMat);
    ring.position.copy(hMesh.position);
    group.add(ring);

    // Animation and interaction
    let dragging = false, lastX = 0, lastY = 0;
    const onDown = (e) => { dragging = true; lastX = e.clientX; lastY = e.clientY; };
    const onUp = () => { dragging = false; };
    const onMove = (e) => {
      if (!dragging) return;
      const dx = e.clientX - lastX, dy = e.clientY - lastY;
      lastX = e.clientX; lastY = e.clientY;
      group.rotation.y += dx * 0.006;
      group.rotation.x = Math.max(-1.2, Math.min(1.2, group.rotation.x + dy * 0.006));
    };

    // Event listeners
    renderer.domElement.addEventListener("pointerdown", onDown);
    window.addEventListener("pointerup", onUp);
    renderer.domElement.addEventListener("pointermove", onMove);

    // Animation loop
    let raf;
    const clock = new THREE.Clock();
    function animate() {
      raf = requestAnimationFrame(animate);
      const t = clock.getElapsedTime();
      
      if (!dragging) group.rotation.y += 0.0015;
      ring.rotation.z = t * 0.6;
      ring.lookAt(camera.position);
      
      const pulse = 1 + 0.25 * Math.sin(t * 3);
      hMesh.scale.setScalar(pulse);
      
      // Animate deterministic points
      detGroup.children.forEach((child) => {
        const tVal = child.userData.t;
        const pulseD = 1 + 0.3 * Math.sin(t * (1 + tVal * 1.3)) * (tVal > 0 ? 1 : 0);
        child.scale.setScalar(pulseD);
        child.visible = liveRef.current.showDet && tVal >= liveRef.current.minT;
      });
      
      // Animate quantum points
      qGroup.children.forEach((child) => {
        const pulseQ = 1 + 0.3 * Math.sin(t * (1 + (child.userData.t || 0) * 1.3));
        child.scale.setScalar(pulseQ);
      });
      qGroup.visible = liveRef.current.showQ;
      
      renderer.render(scene, camera);
    }
    animate();

    // Resize handler
    function onResize() {
      const w = mount.clientWidth, h = mount.clientHeight;
      camera.aspect = w / h;
      camera.updateProjectionMatrix();
      renderer.setSize(w, h);
    }
    window.addEventListener("resize", onResize);

    return () => {
      cancelAnimationFrame(raf);
      window.removeEventListener("resize", onResize);
      window.removeEventListener("pointerup", onUp);
      renderer.domElement.removeEventListener("pointerdown", onDown);
      renderer.domElement.removeEventListener("pointermove", onMove);
      mount.removeChild(renderer.domElement);
      renderer.dispose();
    };
  }, [n, tableIndex, highlight.x, highlight.y, highlight.z]);

  return (
    <div className="relative w-full h-screen">
      <div ref={mountRef} className="absolute inset-0" />
      {/* UI Controls */}
      <div className="absolute top-0 left-0 p-4 md:p-6 space-y-3 pointer-events-none max-w-sm">
        <div className="pointer-events-auto flex items-center gap-2 flex-wrap">
          <button onClick={onBack} className="flex items-center gap-1.5 text-xs px-2.5 py-1.5 rounded border border-slate-600 bg-slate-800/60 text-slate-300">
             solver
          </button>
        </div>
        <p className="pointer-events-auto text-xs text-slate-500 leading-relaxed">
          X/Y/Z = influence of x1/x2/x3 · color+pulse = T (relevant-variable count).
          Gold ring marks the function currently open in the solver.
        </p>
        {/* Control buttons */}
        <div className="pointer-events-auto flex flex-wrap gap-2">
          <button onClick={() => setShowDet((v) => !v)} 
            className="flex items-center gap-1.5 text-[10px] px-2 py-1 rounded border border-teal-500/30 bg-teal-500/10 text-teal-300"
          >
            {showDet ? '👁' : '👁‍🗨'} deterministic
          </button>
          <button onClick={() => setShowQ((v) => !v)}
            className="flex items-center gap-1.5 text-[10px] px-2 py-1 rounded border border-pink-500/30 bg-pink-500/10 text-pink-300"
          >
            {showQ ? '👁' : '👁‍🗨'} quantum stand-in ({qCount})
          </button>
          <button onClick={reseed} className="flex items-center gap-1.5 text-[10px] px-2 py-1 rounded border border-slate-500/30 bg-slate-500/10 text-slate-300">
            🔀 re-measure
          </button>
        </div>
        <div className="pointer-events-auto">
          <label className="text-[10px] text-slate-500 uppercase tracking-wide">
            min T (relevant vars)  {minT}
          </label>
          <input type="range" min={0} max={n} step={1} value={Math.min(minT, n)}
            onChange={(e) => setMinT(Number(e.target.value))}
            className="w-full accent-teal-400" />
        </div>
        <div className="pointer-events-auto flex gap-2 text-[9px] text-slate-500 flex-wrap">
          {T_COLORS.slice(0, n + 1).map((c, i) => (
            <span key={i} className="flex items-center gap-1">
              <span className="inline-block w-2 h-2 rounded-full" 
                style={{ background: `#${c.toString(16).padStart(6, "0")}` }} />
              T={i}
            </span>
          ))}
        </div>
        <div className="pointer-events-auto text-xs bg-[#0f1520]/90 border border-amber-500/30 rounded p-2 space-y-0.5">
          <div className="text-amber-300 font-semibold">
            {getName(n, tableIndex)} · T={highlightT}
          </div>
          <div className="text-slate-400">
            x={highlight.x.toFixed(2)} y={highlight.y.toFixed(2)} z={highlight.z.toFixed(2)}
          </div>
        </div>
      </div>
      <div className="absolute bottom-4 right-4 flex items-center gap-1.5 text-[10px] text-slate-600">
        🔄 drag to rotate
      </div>
    </div>
  );
}

Complete App Shell

// Main unified application
export default function UnifiedApp() {
  const [n, setN] = useState(2);
  const [tableIndex, setTableIndex] = useState(6); // Start on XOR
  const [page, setPage] = useState("solver");

  return (
    <div className="min-h-screen bg-[#0a0e16] text-slate-200 font-mono">
      {/* Navigation */}
      <div className="sticky top-0 z-10 bg-[#0a0e16]/95 backdrop-blur border-b border-slate-800 px-4 md:px-8 py-3 flex flex-wrap items-center gap-4">
        <div className="flex gap-1.5">
          {["solver", "3d", "quantum", "trajectories"].map((p) => (
            <button key={p} onClick={() => setPage(p)}
              className={`text-xs px-3 py-1.5 rounded border transition-colors flex items-center gap-1.5 ${
                page === p ? "bg-teal-500/25 border-teal-400 text-teal-200" : "bg-slate-800/40 border-slate-700 text-slate-400"
              }`}
            >
              {p === "quantum" && <Atom size={12} />}
              {p === "trajectories" && <Orbit size={12} />}
              {p === "solver" ? "Solver" : p === "3d" ? "3D View" : p === "quantum" ? "Quantum" : "Trajectories"}
            </button>
          ))}
        </div>
        <div className="flex items-center gap-1.5 ml-auto">
          <span className="text-[10px] text-slate-500 uppercase tracking-wide mr-1">
            n =
          </span>
          {[0, 1, 2, 3].map((k) => (
            <button key={k} onClick={() => { setN(k); setTableIndex(0); }}
              className={`text-xs w-8 h-8 rounded border transition-colors ${
                n === k ? "bg-amber-500/25 border-amber-400 text-amber-200" : "border-slate-700 text-slate-400"
              }`}
            >
              {k}
            </button>
          ))}
        </div>
      </div>

      {/* Pages */}
      {page === "solver" && (
        <div className="p-4 md:p-8">
          <SolverPage n={n} tableIndex={tableIndex} setTableIndex={setTableIndex} onView3D={() => setPage("3d")} />
        </div>
      )}
      {page === "3d" && <View3DPage n={n} tableIndex={tableIndex} onBack={() => setPage("solver")} />}
      {page === "quantum" && <QuantumPage n={n} />}
      {page === "trajectories" && <TrajectoriesPage n={n} />}
    </div>
  );
}

Using the Boolean Solver

As a Standalone Tool

To use the Boolean Solver in your own project:

  1. Download the source from the conversation archive:

    unzip conversation-archive.zip archive/source/boolean-solver.jsx
    
  2. Import dependencies (React and Three.js):

    npm install react three @react-three/fiber @react-three/drei
    
  3. Integrate into your React app:

    import { BooleanSolver } from './boolean-solver';
    
    function App() {
      return <BooleanSolver />;
    }
    

As a Learning Tool

The Boolean Solver is designed for education. Use it to:

As a Research Tool

Researchers can use this tool to:


Performance Characteristics


The Boolean Solver is part of a family of related tools in the Badlucksbane Lab:


Physics Connection

Boolean logic is deeply connected to physics in several ways:

  1. Digital Physics — The universe is fundamentally discrete in some interpretations, with boolean logic at its core
  2. Quantum Computing — Qubits use boolean-like states (|0⟩ and |1⟩) with superposition
  3. Information Theory — Physical systems have information content measurable in bits
  4. Computational Physics — All physics simulations ultimately run on boolean-based digital computers
  5. Thermodynamics of Computation — There are fundamental physical limits to boolean operations (Landauer’s principle)

The Boolean Solver demonstrates that even simple boolean functions have rich mathematical structure, hinting at the depth of complexity that emerges from simple physical laws.


License

This code is provided for educational purposes under permissive terms. You are free to:

Attribution is appreciated but not required.


Download

Complete source code: previously linked to a personal working-directory archive (~/work/conversation-archive.zip) that was reachable through a symlink placed directly in the lab site’s web root. That symlink exposed the whole directory (including unrelated personal files like a resume) rather than just this archive, so it was removed; these links are disabled until the specific source files are copied into the site as proper page resources.

To extract:

# Extract the specific file
unzip conversation-archive.zip archive/source/boolean-solver.jsx

# Or extract all source files
unzip conversation-archive.zip "archive/source/*"


Boolean algebra is the calculus of thought. The Boolean Solver makes that calculus visible, interactive, and beautiful.