import type { MathProblem, Difficulty } from "../types"; import { randomInt } from "@/lib/utils"; let counter = 0; function nextId() { return `ns-${++counter}-${Date.now()}`; } export function generateBinaryToDenary(difficulty: Difficulty): MathProblem { const bits = difficulty === 1 ? randomInt(3, 4) : difficulty === 2 ? randomInt(5, 6) : randomInt(7, 8); // ensure a leading 1 so the length is meaningful let binary = "1"; for (let i = 1; i < bits; i++) binary += Math.random() < 0.5 ? "0" : "1"; const len = binary.length; let value = 0; const parts: string[] = []; for (let i = 0; i < len; i++) { const exp = len - 1 - i; const digit = parseInt(binary[i], 10); const place = Math.pow(2, exp); if (digit === 1) parts.push(`${place}`); value += digit * place; } return { id: nextId(), prompt: `${binary}_{2} = ?_{10}`, answer: { kind: "integer", value }, hints: [ "Each column is a power of 2, doubling from the right: 1, 2, 4, 8, 16 …", "Add up the place values wherever there is a 1.", `${parts.join(" + ")} = ${value}`, ], steps: [ { explanation: "Label each column with its power of 2, starting at 1 on the right." }, { explanation: `Add the place values under each 1: ${parts.join(" + ")}` }, { explanation: `${binary} in binary = ${value} in denary.` }, ], }; } export function generateQuaternaryToDenary(difficulty: Difficulty): MathProblem { const digits = difficulty === 1 ? randomInt(2, 3) : difficulty === 2 ? randomInt(3, 4) : randomInt(4, 5); let quaternary = `${randomInt(1, 3)}`; // leading non-zero digit for (let i = 1; i < digits; i++) quaternary += `${randomInt(0, 3)}`; const len = quaternary.length; let value = 0; const parts: string[] = []; for (let i = 0; i < len; i++) { const exp = len - 1 - i; const digit = parseInt(quaternary[i], 10); const place = Math.pow(4, exp); if (digit !== 0) parts.push(`${digit}×${place}`); value += digit * place; } return { id: nextId(), prompt: `${quaternary}_{4} = ?_{10}`, answer: { kind: "integer", value }, hints: [ "Each column is a power of 4, from the right: 1, 4, 16, 64 …", "Multiply each digit by its place value and add them up.", `${parts.join(" + ")} = ${value}`, ], steps: [ { explanation: "Label each column with its power of 4, starting at 1 on the right." }, { explanation: `Add the products: ${parts.join(" + ")}` }, { explanation: `${quaternary} in base 4 = ${value} in denary.` }, ], }; } export function generateDigitValue(difficulty: Difficulty): MathProblem { const digits = difficulty === 1 ? randomInt(3, 4) : difficulty === 2 ? 5 : 6; const min = Math.pow(10, digits - 1); const max = Math.pow(10, digits) - 1; const n = randomInt(min, max); const str = `${n}`; // pick a non-zero digit position const nonZeroPositions = str.split("").map((d, i) => ({ d, i })).filter((x) => x.d !== "0"); const pick = nonZeroPositions[randomInt(0, nonZeroPositions.length - 1)]; const exp = str.length - 1 - pick.i; const place = Math.pow(10, exp); const value = parseInt(pick.d, 10) * place; return { id: nextId(), prompt: `\\text{In } ${n} \\text{, what is the value of the digit } ${pick.d}\\text{?}`, answer: { kind: "integer", value }, hints: [ "Find which column the digit sits in.", `That column is worth 10^${exp} = ${place}.`, `${pick.d} × ${place} = ${value}`, ], steps: [ { explanation: `The digit ${pick.d} is in the 10^${exp} (${place}) column.` }, { explanation: `Its value is ${pick.d} × ${place} = ${value}.` }, ], }; }