Initial Commit
This commit is contained in:
163
lib/problems/generators/fraction-problems.ts
Normal file
163
lib/problems/generators/fraction-problems.ts
Normal file
@@ -0,0 +1,163 @@
|
||||
import type { MathProblem, Difficulty } from "../types";
|
||||
import { randomInt, randomChoice } from "@/lib/utils";
|
||||
import * as frac from "@/lib/math/fractions";
|
||||
|
||||
let counter = 0;
|
||||
function nextId() {
|
||||
return `fp-${++counter}-${Date.now()}`;
|
||||
}
|
||||
|
||||
export function generateFractionAddSubtract(difficulty: Difficulty): MathProblem {
|
||||
const operation = randomChoice(["add", "subtract"] as const);
|
||||
const op = operation === "add" ? "+" : "-";
|
||||
|
||||
let n1: number, d1: number, n2: number, d2: number;
|
||||
|
||||
if (difficulty === 1) {
|
||||
// Common denominators
|
||||
d1 = randomChoice([2, 3, 4, 5, 6, 8, 10, 12]);
|
||||
d2 = d1;
|
||||
n1 = randomInt(1, d1 - 1);
|
||||
n2 = operation === "subtract" ? randomInt(1, n1) : randomInt(1, d1 - n1);
|
||||
} else if (difficulty === 2) {
|
||||
// One denominator is a multiple of the other
|
||||
d1 = randomChoice([2, 3, 4, 5, 6]);
|
||||
const multiplier = randomChoice([2, 3]);
|
||||
d2 = d1 * multiplier;
|
||||
n1 = randomInt(1, d1 - 1);
|
||||
n2 = randomInt(1, d2 - 1);
|
||||
} else {
|
||||
// Unlike denominators
|
||||
d1 = randomChoice([3, 4, 5, 7, 8, 9]);
|
||||
d2 = randomChoice([3, 4, 5, 7, 8, 9].filter((d) => d !== d1));
|
||||
n1 = randomInt(1, d1 - 1);
|
||||
n2 = randomInt(1, d2 - 1);
|
||||
}
|
||||
|
||||
const [ansNum, ansDen] = operation === "add"
|
||||
? frac.add(n1, d1, n2, d2)
|
||||
: frac.subtract(n1, d1, n2, d2);
|
||||
|
||||
const prompt = `\\frac{${n1}}{${d1}} ${op} \\frac{${n2}}{${d2}}`;
|
||||
|
||||
const commonDen = frac.lcm(d1, d2);
|
||||
const steps = d1 === d2
|
||||
? [
|
||||
{ explanation: "Denominators are the same, so just " + (operation === "add" ? "add" : "subtract") + " the numerators" },
|
||||
{ explanation: `${n1} ${op} ${n2} = ${operation === "add" ? n1 + n2 : n1 - n2}`, math: `\\frac{${operation === "add" ? n1 + n2 : n1 - n2}}{${d1}}` },
|
||||
]
|
||||
: [
|
||||
{ explanation: `Find the common denominator: LCM(${d1}, ${d2}) = ${commonDen}` },
|
||||
{ explanation: `Convert: ${n1}×${commonDen / d1}/${d1}×${commonDen / d1} and ${n2}×${commonDen / d2}/${d2}×${commonDen / d2}` },
|
||||
{ explanation: `${op === "+" ? "Add" : "Subtract"} numerators`, math: `\\frac{${ansNum}}{${ansDen}}` },
|
||||
];
|
||||
|
||||
return {
|
||||
id: nextId(),
|
||||
prompt,
|
||||
answer: { kind: "fraction", numerator: ansNum, denominator: ansDen },
|
||||
hints: [
|
||||
d1 === d2 ? "The denominators are already the same!" : "Find a common denominator first",
|
||||
d1 !== d2 ? `Try using the Butterfly Method: cross multiply` : `Just ${operation} the numerators`,
|
||||
],
|
||||
steps,
|
||||
};
|
||||
}
|
||||
|
||||
export function generateFractionMultiply(difficulty: Difficulty): MathProblem {
|
||||
const denChoices = difficulty === 1 ? [2, 3, 4, 5] : difficulty === 2 ? [2, 3, 4, 5, 6, 7, 8] : [3, 5, 7, 9, 11, 12, 15];
|
||||
const d1 = randomChoice(denChoices);
|
||||
const d2 = randomChoice(denChoices);
|
||||
const n1 = randomInt(1, d1 - 1);
|
||||
const n2 = randomInt(1, d2 - 1);
|
||||
|
||||
const [ansNum, ansDen] = frac.multiply(n1, d1, n2, d2);
|
||||
|
||||
return {
|
||||
id: nextId(),
|
||||
prompt: `\\frac{${n1}}{${d1}} \\times \\frac{${n2}}{${d2}}`,
|
||||
answer: { kind: "fraction", numerator: ansNum, denominator: ansDen },
|
||||
hints: [
|
||||
"Multiply numerator × numerator",
|
||||
"Multiply denominator × denominator",
|
||||
"Simplify if possible",
|
||||
],
|
||||
steps: [
|
||||
{ explanation: `Multiply numerators: ${n1} × ${n2} = ${n1 * n2}` },
|
||||
{ explanation: `Multiply denominators: ${d1} × ${d2} = ${d1 * d2}` },
|
||||
{ explanation: "Simplify", math: `\\frac{${ansNum}}{${ansDen}}` },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function generateFractionDivide(difficulty: Difficulty): MathProblem {
|
||||
const denChoices = difficulty === 1 ? [2, 3, 4, 5] : difficulty === 2 ? [2, 3, 4, 5, 6, 7, 8] : [3, 5, 7, 9, 11, 14, 15];
|
||||
const d1 = randomChoice(denChoices);
|
||||
const d2 = randomChoice(denChoices);
|
||||
const n1 = randomInt(1, d1 - 1);
|
||||
const n2 = randomInt(1, d2 - 1);
|
||||
|
||||
const [ansNum, ansDen] = frac.divide(n1, d1, n2, d2);
|
||||
|
||||
return {
|
||||
id: nextId(),
|
||||
prompt: `\\frac{${n1}}{${d1}} \\div \\frac{${n2}}{${d2}}`,
|
||||
answer: { kind: "fraction", numerator: ansNum, denominator: ansDen },
|
||||
hints: [
|
||||
"Keep the first fraction the same",
|
||||
"Flip the second fraction (reciprocal)",
|
||||
"Then multiply",
|
||||
],
|
||||
steps: [
|
||||
{ explanation: `Keep ${n1}/${d1}, flip ${n2}/${d2} to ${d2}/${n2}` },
|
||||
{ explanation: `Multiply: ${n1}×${d2} / ${d1}×${n2}` },
|
||||
{ explanation: "Simplify", math: `\\frac{${ansNum}}{${ansDen}}` },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function generateFractionOfQuantity(difficulty: Difficulty): MathProblem {
|
||||
const denChoices = difficulty === 1 ? [2, 4, 5, 10] : difficulty === 2 ? [3, 4, 5, 6, 8] : [7, 8, 9, 12, 15];
|
||||
const den = randomChoice(denChoices);
|
||||
const num = randomInt(1, den - 1);
|
||||
const multiplier = randomChoice(difficulty === 1 ? [2, 4, 5, 10] : [3, 6, 7, 8, 9, 12]);
|
||||
const quantity = den * multiplier;
|
||||
const answer = num * multiplier;
|
||||
|
||||
return {
|
||||
id: nextId(),
|
||||
prompt: `\\frac{${num}}{${den}} \\text{ of } ${quantity}`,
|
||||
answer: { kind: "integer", value: answer },
|
||||
hints: [
|
||||
`Divide ${quantity} by ${den} first`,
|
||||
`Then multiply by ${num}`,
|
||||
],
|
||||
steps: [
|
||||
{ explanation: `Divide the quantity by the denominator: ${quantity} ÷ ${den} = ${quantity / den}` },
|
||||
{ explanation: `Multiply by the numerator: ${quantity / den} × ${num} = ${answer}` },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function generateWholeFromFraction(difficulty: Difficulty): MathProblem {
|
||||
const denChoices = difficulty === 1 ? [2, 3, 4, 5] : difficulty === 2 ? [3, 5, 6, 8] : [7, 8, 9, 12];
|
||||
const den = randomChoice(denChoices);
|
||||
const num = randomInt(1, den - 1);
|
||||
const whole = den * randomChoice(difficulty === 1 ? [2, 3, 4, 5] : [3, 5, 6, 7, 8, 10]);
|
||||
const part = (num / den) * whole;
|
||||
|
||||
return {
|
||||
id: nextId(),
|
||||
prompt: `\\frac{${num}}{${den}} \\text{ of a number is } ${part}\\text{. Find the number.}`,
|
||||
answer: { kind: "integer", value: whole },
|
||||
hints: [
|
||||
`If ${num}/${den} of the number is ${part}...`,
|
||||
`Find 1/${den} first by dividing ${part} by ${num}`,
|
||||
`Then multiply by ${den} to get the whole`,
|
||||
],
|
||||
steps: [
|
||||
{ explanation: `1/${den} of the number = ${part} ÷ ${num} = ${part / num}` },
|
||||
{ explanation: `The whole number = ${part / num} × ${den} = ${whole}` },
|
||||
],
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user