惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
DataBreaches.Net
GbyAI
GbyAI
aimingoo的专栏
aimingoo的专栏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
月光博客
月光博客
大猫的无限游戏
大猫的无限游戏
M
MIT News - Artificial intelligence
腾讯CDC
博客园 - Franky
Engineering at Meta
Engineering at Meta
C
Check Point Blog
T
The Blog of Author Tim Ferriss
有赞技术团队
有赞技术团队
Microsoft Azure Blog
Microsoft Azure Blog
MyScale Blog
MyScale Blog
I
InfoQ
Blog — PlanetScale
Blog — PlanetScale
P
Proofpoint News Feed
The GitHub Blog
The GitHub Blog
N
Netflix TechBlog - Medium
Last Week in AI
Last Week in AI
S
SegmentFault 最新的问题
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
WordPress大学
WordPress大学

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
How I Built a 24 Game Solver: Brute-Force Meets Elegance ...
杜涛 · 2026-06-13 · via DEV Community

杜涛

The 24 Game is deceptively simple: given four numbers, combine them with +, -, ×, ÷ to make exactly 24. Sounds easy, right? Try solving 1, 5, 5, 5 — it stumps most people.

I built a complete solver for my math puzzle platform, and the algorithm turned out to be a great exercise in combinatorics, expression trees, and floating-point traps. Let me walk you through it.


The Problem Space

Four numbers, four operators, and parentheses. How many possibilities?

  • Permutations of 4 numbers: up to 24 (4!)
  • Operator combinations: 4³ = 64 (three slots, four choices each)
  • Parenthesization patterns: 5 (the Catalan number C₃)

Total: 24 × 64 × 5 = 7,680 evaluations. Trivial for modern hardware.

The key insight is that we need to enumerate all five binary tree structures for combining four operands — these correspond to the five ways to fully parenthesize a sequence of four items.


The Five Expression Patterns

For numbers a, b, c, d and operators op1, op2, op3:

Pattern 1: ((a op1 b) op2 c) op3 d
Pattern 2: (a op1 (b op2 c)) op3 d
Pattern 3: (a op1 b) op2 (c op3 d)
Pattern 4: a op1 ((b op2 c) op3 d)
Pattern 5: a op1 (b op2 (c op3 d))

These five patterns cover every possible way to combine four numbers with binary operators. No expression is left unexplored.


The Algorithm in TypeScript

Step 1: Generate Permutations (with deduplication)

When input contains duplicates (like 5, 5, 5, 1), many permutations are identical. We use a Set to filter:

function permutations(arr: number[]): number[][] {
  if (arr.length <= 1) return [arr];

  const result: number[][] = [];
  const seen = new Set<string>();

  for (let i = 0; i < arr.length; i++) {
    const rest = [...arr.slice(0, i), ...arr.slice(i + 1)];
    for (const perm of permutations(rest)) {
      const newPerm = [arr[i], ...perm];
      const key = newPerm.join(',');
      if (!seen.has(key)) {
        seen.add(key);
        result.push(newPerm);
      }
    }
  }
  return result;
}

For 5, 5, 5, 1, this reduces 24 permutations down to just 4.

Step 2: Evaluate Each Pattern

The core loop iterates over all permutations × operators × patterns:

const operators = ['+', '-', '*', '/'];

function operate(a: number, b: number, op: string): number {
  switch (op) {
    case '+': return a + b;
    case '-': return a - b;
    case '*': return a * b;
    case '/': return b !== 0 ? a / b : Infinity;
    default: return Infinity;
  }
}

For each pattern, we evaluate step by step, short-circuiting on division by zero or invalid results:

// Pattern 3: (a op1 b) op2 (c op3 d)
try {
  const r1 = operate(a, b, op1);
  if (!isValidNum(r1)) throw new Error();

  const r2 = operate(c, d, op3);
  if (!isValidNum(r2)) throw new Error();

  const r3 = operate(r1, r2, op2);
  if (!isValidNum(r3)) throw new Error();

  if (Math.abs(r3 - 24) < 0.0001) {
    // Found a solution!
  }
} catch {}

Step 3: Handle Floating-Point Precision

This is the tricky part. When 8 / (3 - 8/3) = 24, the intermediate results involve fractions. Direct equality check (r3 === 24) will fail due to floating-point errors.

Solution: use an epsilon comparison:

if (Math.abs(r3 - 24) < 0.0001) {
  // This is a valid solution
}

This tiny tolerance (0.0001) handles all the edge cases while avoiding false positives.


Putting It All Together

export function solve24(numbers: number[]): Solution[] {
  const solutions: Solution[] = [];
  const seen = new Set<string>();
  const perms = permutations(numbers);

  for (const [a, b, c, d] of perms) {
    for (const op1 of operators) {
      for (const op2 of operators) {
        for (const op3 of operators) {
          // Evaluate all 5 patterns...
          // (full implementation above)
        }
      }
    }
  }

  return solutions.slice(0, 10); // Return top 10 solutions
}

The full solver runs in under 1ms for any input — brute force is perfectly fine here.


Tricky Examples

Input Solution
1, 5, 5, 5 5 × (5 - 1/5) = 24
3, 3, 8, 8 8 / (3 - 8/3) = 24
1, 3, 4, 6 6 / (1 - 3/4) = 24

These are the puzzles that make people give up — and exactly why having a solver is satisfying.


Try It Live

I integrated this solver into my math puzzle platform. You can play the 24 Game with a built-in hint system that uses this exact algorithm:

👉 Play 24 Game on MathPuzzleHub

The solver powers the "Show Solution" button — it finds all valid expressions and displays them step by step.


Performance Notes

  • Worst case (4 distinct numbers like 1, 2, 3, 4): ~7,680 evaluations, still under 1ms
  • Best case (all same like 6, 6, 6, 6): only 1 unique permutation, 320 evaluations
  • Memory: minimal — just storing up to 10 solution strings

If you wanted to scale this to 5 or 6 numbers, you'd want to switch from brute force to a recursive reduction approach (pick any two numbers, combine them, recurse on the smaller set). But for the classic 4-number game, brute force is elegant and fast.


Key Takeaways

  1. Brute force is underrated. 7,680 evaluations is nothing. Don't over-engineer.
  2. Five parenthesization patterns cover all binary expression trees for 4 operands — this comes from Catalan numbers.
  3. Floating-point epsilon comparison is essential. === 24 will miss valid solutions involving division.
  4. Deduplication matters both for performance (fewer permutations) and UX (no duplicate solutions shown).

Happy solving! 🧮


Built with TypeScript and Next.js. Check out more math games at MathPuzzleHub.