Initial Commit
This commit is contained in:
110
lib/problems/generators/ratio-problems.ts
Normal file
110
lib/problems/generators/ratio-problems.ts
Normal file
@@ -0,0 +1,110 @@
|
||||
import type { MathProblem, Difficulty } from "../types";
|
||||
import { randomInt, randomChoice } from "@/lib/utils";
|
||||
import { simplifyRatio, divideInRatio } from "@/lib/math/ratios";
|
||||
|
||||
let counter = 0;
|
||||
function nextId() {
|
||||
return `rp-${++counter}-${Date.now()}`;
|
||||
}
|
||||
|
||||
export function generateSimplifyRatio(difficulty: Difficulty): MathProblem {
|
||||
const gcd = randomChoice(difficulty === 1 ? [2, 3, 4, 5] : difficulty === 2 ? [3, 4, 5, 6, 7] : [4, 6, 8, 9, 12]);
|
||||
const a = randomInt(1, difficulty === 1 ? 5 : 10) * gcd;
|
||||
const b = randomInt(1, difficulty === 1 ? 5 : 10) * gcd;
|
||||
|
||||
const simplified = simplifyRatio([a, b]);
|
||||
|
||||
return {
|
||||
id: nextId(),
|
||||
prompt: `\\text{Simplify the ratio } ${a}:${b}`,
|
||||
answer: { kind: "ratio", parts: simplified },
|
||||
hints: [
|
||||
`Find the GCD of ${a} and ${b}`,
|
||||
`The GCD is ${gcd}`,
|
||||
`Divide both parts by ${gcd}`,
|
||||
],
|
||||
steps: [
|
||||
{ explanation: `GCD of ${a} and ${b} is ${gcd}` },
|
||||
{ explanation: `${a} ÷ ${gcd} = ${simplified[0]}, ${b} ÷ ${gcd} = ${simplified[1]}` },
|
||||
{ explanation: `Simplified: ${simplified.join(":")}` },
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function generateDivideInRatio(difficulty: Difficulty): MathProblem {
|
||||
const numParts = difficulty === 3 ? 3 : 2;
|
||||
const parts: number[] = [];
|
||||
for (let i = 0; i < numParts; i++) {
|
||||
parts.push(randomInt(1, difficulty === 1 ? 5 : 9));
|
||||
}
|
||||
|
||||
const sum = parts.reduce((a, b) => a + b, 0);
|
||||
const multiplier = randomChoice(difficulty === 1 ? [2, 3, 4, 5] : [3, 4, 5, 6, 7, 8]);
|
||||
const total = sum * multiplier;
|
||||
|
||||
const values = divideInRatio(total, parts);
|
||||
const intValues = values.map(Math.round);
|
||||
|
||||
const names = ["first share", "second share", "third share"];
|
||||
|
||||
return {
|
||||
id: nextId(),
|
||||
prompt: `\\text{Share } ${total} \\text{ in the ratio } ${parts.join(":")}`,
|
||||
answer: { kind: "ratio", parts: intValues },
|
||||
hints: [
|
||||
`Total parts: ${parts.join(" + ")} = ${sum}`,
|
||||
`One part = ${total} ÷ ${sum} = ${multiplier}`,
|
||||
`Multiply each ratio number by ${multiplier}`,
|
||||
],
|
||||
steps: [
|
||||
{ explanation: `Total parts = ${parts.join(" + ")} = ${sum}` },
|
||||
{ explanation: `One part = ${total} ÷ ${sum} = ${multiplier}` },
|
||||
...parts.map((p, i) => ({
|
||||
explanation: `${names[i]}: ${p} × ${multiplier} = ${intValues[i]}`,
|
||||
})),
|
||||
],
|
||||
};
|
||||
}
|
||||
|
||||
export function generateRatioWordProblem(difficulty: Difficulty): MathProblem {
|
||||
const a = randomInt(2, 7);
|
||||
const b = randomInt(2, 7);
|
||||
const diff = Math.abs(a - b);
|
||||
|
||||
if (diff === 0) {
|
||||
return generateDivideInRatio(difficulty);
|
||||
}
|
||||
|
||||
const contexts = [
|
||||
{ item: "sweets", nameA: "Josh", nameB: "Nathan" },
|
||||
{ item: "marbles", nameA: "Amy", nameB: "Ben" },
|
||||
{ item: "stickers", nameA: "Karen", nameB: "Natasha" },
|
||||
];
|
||||
const ctx = randomChoice(contexts);
|
||||
|
||||
const onePart = randomChoice(difficulty === 1 ? [5, 10, 12] : [6, 8, 9, 15, 20]);
|
||||
const extraAmount = diff * onePart;
|
||||
const totalParts = a + b;
|
||||
const total = totalParts * onePart;
|
||||
|
||||
const bigger = a > b ? ctx.nameA : ctx.nameB;
|
||||
const biggerRatio = Math.max(a, b);
|
||||
const smallerRatio = Math.min(a, b);
|
||||
|
||||
return {
|
||||
id: nextId(),
|
||||
prompt: `\\text{${ctx.item.charAt(0).toUpperCase() + ctx.item.slice(1)} were shared between ${ctx.nameA} and ${ctx.nameB} in the ratio ${a}:${b}. If ${bigger} received ${extraAmount} more ${ctx.item}, find the total shared.}`,
|
||||
answer: { kind: "integer", value: total },
|
||||
hints: [
|
||||
`The difference in ratio parts is ${biggerRatio} - ${smallerRatio} = ${diff}`,
|
||||
`${diff} parts = ${extraAmount}, so 1 part = ${onePart}`,
|
||||
`Total parts = ${a} + ${b} = ${totalParts}`,
|
||||
],
|
||||
steps: [
|
||||
{ explanation: `Difference in parts: ${biggerRatio} - ${smallerRatio} = ${diff}` },
|
||||
{ explanation: `${diff} parts = ${extraAmount}, so 1 part = ${extraAmount} ÷ ${diff} = ${onePart}` },
|
||||
{ explanation: `Total parts: ${a} + ${b} = ${totalParts}` },
|
||||
{ explanation: `Total ${ctx.item}: ${totalParts} × ${onePart} = ${total}` },
|
||||
],
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user