Files
cabrits-math/lib/problems/generators/number-properties-problems.ts
2026-07-05 11:12:45 -04:00

137 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import type { MathProblem, Difficulty } from "../types";
import { randomInt, randomChoice } from "@/lib/utils";
let counter = 0;
function nextId() {
return `np-${++counter}-${Date.now()}`;
}
export function generateIdentityInverse(difficulty: Difficulty): MathProblem {
const kind = randomChoice(
difficulty === 1
? (["identity-add", "zero", "inverse-add"] as const)
: (["identity-add", "identity-mul", "zero", "inverse-add"] as const),
);
if (kind === "identity-add") {
const n = randomInt(-20, 20);
return {
id: nextId(),
prompt: `${n} + 0`,
answer: { kind: "integer", value: n },
hints: ["0 is the identity for addition.", "Adding 0 changes nothing."],
steps: [{ explanation: "Adding the identity 0 leaves the number unchanged.", math: `${n} + 0 = ${n}` }],
};
}
if (kind === "identity-mul") {
const n = randomInt(-20, 20);
return {
id: nextId(),
prompt: `${n} \\times 1`,
answer: { kind: "integer", value: n },
hints: ["1 is the identity for multiplication.", "Multiplying by 1 changes nothing."],
steps: [{ explanation: "Multiplying by the identity 1 leaves the number unchanged.", math: `${n} \\times 1 = ${n}` }],
};
}
if (kind === "zero") {
const n = randomInt(1, 30);
return {
id: nextId(),
prompt: `${n} \\times 0`,
answer: { kind: "integer", value: 0 },
hints: ["Anything multiplied by zero is zero."],
steps: [{ explanation: "Any number times zero is zero.", math: `${n} \\times 0 = 0` }],
};
}
// inverse-add: additive inverse
const n = randomInt(-20, 20) || 5;
return {
id: nextId(),
prompt: `\\text{The additive inverse of } ${n} \\text{ is?}`,
answer: { kind: "integer", value: -n },
hints: ["The additive inverse adds up to 0.", "Flip the sign."],
steps: [{ explanation: "The additive inverse flips the sign so the sum is 0.", math: `${n} + (${-n}) = 0` }],
};
}
export function generateExponentEvaluate(difficulty: Difficulty): MathProblem {
if (difficulty === 3) {
// index law: find the resulting exponent
const base = randomInt(2, 6);
const op = randomChoice(["\\times", "\\div"] as const);
if (op === "\\times") {
const m = randomInt(1, 5);
const n = randomInt(1, 5);
return {
id: nextId(),
prompt: `${base}^{${m}} \\times ${base}^{${n}} = ${base}^{x}`,
answer: { kind: "integer", value: m + n },
hints: ["Same base, multiplying → add the powers.", `${m} + ${n} = ?`],
steps: [{ explanation: "When multiplying powers of the same base, add the exponents.", math: `${base}^{${m}} \\times ${base}^{${n}} = ${base}^{${m + n}}` }],
};
}
const m = randomInt(3, 7);
const n = randomInt(1, m - 1);
return {
id: nextId(),
prompt: `${base}^{${m}} \\div ${base}^{${n}} = ${base}^{x}`,
answer: { kind: "integer", value: m - n },
hints: ["Same base, dividing → subtract the powers.", `${m} - ${n} = ?`],
steps: [{ explanation: "When dividing powers of the same base, subtract the exponents.", math: `${base}^{${m}} \\div ${base}^{${n}} = ${base}^{${m - n}}` }],
};
}
if (difficulty === 2 && Math.random() < 0.5) {
// difference of two powers, e.g. 2^3 - 2^1
const base = randomInt(2, 4);
const a = randomInt(2, 3);
const b = 1;
const value = Math.pow(base, a) - Math.pow(base, b);
return {
id: nextId(),
prompt: `${base}^{${a}} - ${base}^{${b}}`,
answer: { kind: "integer", value },
hints: [`${base}^${a} = ${Math.pow(base, a)}`, `${base}^${b} = ${Math.pow(base, b)}`],
steps: [{ explanation: "Work out each power, then subtract.", math: `${Math.pow(base, a)} - ${Math.pow(base, b)} = ${value}` }],
};
}
// evaluate a single power (includes n^0 and n^1)
const base = randomInt(2, difficulty === 1 ? 6 : 9);
const exp = difficulty === 1 ? randomChoice([0, 1, 2, 2, 3]) : randomChoice([0, 1, 2, 3]);
const value = Math.pow(base, exp);
const note = exp === 0 ? "Any number to the power 0 is 1." : exp === 1 ? "Any number to the power 1 is itself." : `Multiply ${base} by itself ${exp} times.`;
return {
id: nextId(),
prompt: `${base}^{${exp}}`,
answer: { kind: "integer", value },
hints: [note],
steps: [{ explanation: note, math: `${base}^{${exp}} = ${value}` }],
};
}
export function generateDistributive(difficulty: Difficulty): MathProblem {
const a = randomInt(2, difficulty === 1 ? 6 : 9);
const b = randomInt(1, difficulty === 1 ? 6 : 9);
const c = randomInt(1, difficulty === 1 ? 6 : 9);
const value = a * (b + c);
return {
id: nextId(),
prompt: `${a} \\times (${b} + ${c})`,
answer: { kind: "integer", value },
hints: [
"Add inside the bracket first, then multiply.",
"Or multiply the outside number by each number inside.",
`${a} × ${b} + ${a} × ${c}`,
],
steps: [
{ explanation: `Add inside the bracket: ${b} + ${c} = ${b + c}` },
{ explanation: `Multiply: ${a} × ${b + c} = ${value}` },
{ explanation: `Check by distributing: ${a * b} + ${a * c} = ${value}` },
],
};
}