diff --git a/js_pkg/.gitignore b/js_pkg/.gitignore new file mode 100644 index 0000000..40b878d --- /dev/null +++ b/js_pkg/.gitignore @@ -0,0 +1 @@ +node_modules/ \ No newline at end of file diff --git a/js_pkg/generators/basic_math.js b/js_pkg/generators/basic_math.js index 31d9682..b73cfd2 100644 --- a/js_pkg/generators/basic_math.js +++ b/js_pkg/generators/basic_math.js @@ -1,13 +1,14 @@ -import {randint, randomchoice, calculate_gcd} from '../utils.js'; +import { evaluate } from "mathjs"; +import { calculate_gcd, randint, randomchoice } from "../utils.js"; -export function absolute_difference(max_a=100, max_b=100) { +export function absolute_difference(max_a = 100, max_b = 100) { const a = randint(-1 * max_a, max_a); const b = randint(-1 * max_b, max_b); const absDiff = Math.abs(a - b); return [`$|${a}-${b}|$`, `$${absDiff}$`]; } -export function addition(max_sum=99, max_addend=50) { +export function addition(max_sum = 99, max_addend = 50) { if (max_addend > max_sum) max_addend = max_sum; const a = randint(0, max_addend); const b = randint(0, max_addend); @@ -15,10 +16,10 @@ export function addition(max_sum=99, max_addend=50) { const problem = `$${a}+${b}=$`; const solution = `$${c}$`; - return [problem, solution] + return [problem, solution]; } -export function compare_fractions(max_val=10) { +export function compare_fractions(max_val = 10) { const a = randint(1, max_val); let b = randint(1, max_val); const c = randint(1, max_val); @@ -32,25 +33,25 @@ export function compare_fractions(max_val=10) { let solution; if (first > second) { - solution = '>'; + solution = ">"; } else if (first < second) { - solution = '<'; + solution = "<"; } else { - solution = '='; + solution = "="; } const problem = `Which symbol represents the comparison between $\\frac{${a}}{${b}}$ and $\\frac{${c}}{${d}}$?`; return [problem, solution]; } -export function cube_root(min_no=1, max_no=1000) { +export function cube_root(min_no = 1, max_no = 1000) { const a = randint(min_no, max_no); const b = a ** (1 / 3); return [`$\\sqrt[3]{${a}}=$`, `$${b}$`]; } -export function divide_fractions(max_val=10) { +export function divide_fractions(max_val = 10) { const a = randint(1, max_val); let b = randint(1, max_val); while (a == b) b = randint(1, max_val); @@ -61,15 +62,18 @@ export function divide_fractions(max_val=10) { const tmp_n = a * d; const tmp_d = b * c; - + const gcd = calculate_gcd(tmp_n, tmp_d); const sol_numerator = Math.floor(tmp_n / gcd); const sol_denominator = Math.floor(tmp_d / gcd); - return [`$\\frac{${a}}{${b}}\\div\\frac{${c}}{${d}}=$`, `$\\frac{${sol_numerator}}{${sol_denominator}}$`]; + return [ + `$\\frac{${a}}{${b}}\\div\\frac{${c}}{${d}}=$`, + `$\\frac{${sol_numerator}}{${sol_denominator}}$`, + ]; } -export function division(max_a=25, max_b=25) { +export function division(max_a = 25, max_b = 25) { a = randint(1, max_a); b = randint(1, max_b); @@ -80,27 +84,79 @@ export function division(max_a=25, max_b=25) { return [`$${divisor}}\\div${dividend}=$`, `$${quotient}$`]; } -export function exponentiation(max_base=10, max_expo=10) { +export function exponentiation(max_base = 10, max_expo = 10) { const base = randint(1, max_base); const expo = randint(1, max_expo); const sol = Math.pow(base, expo); - + return [`$${base}^{${expo}}=$`, `$${sol}$`]; } -export function factorial(max_input=10) { - const a = randint(0, max_input); - let n = a; - let b = 1; - while (a != 1 && n > 0) { - b *= n; - n -= 1; +export function factorial( + maxInput = 10, + hasLatexOutput = true, + isFraction = false, + isExpression = false +) { + const operations = ["+", "-"]; + let a = ""; + let operation = operations[randint(0, operations.length - 1)]; + if (isFraction) { + let numerator, denominator; + if (isExpression) { + numerator = randint(2, maxInput); + while (true) { + let left = randint(0, maxInput); + let right = randint(0, maxInput); + if ( + numerator > left + right && + numerator > left - right && + left > right + ) { + denominator = + "(" + + left.toString() + + operation + + right.toString() + + ")!"; + break; + } + } + a = numerator.toString() + "!" + "/" + denominator; + } else { + while (true) { + numerator = randint(0, maxInput); + denominator = randint(0, maxInput); + if (numerator > denominator) { + a = numerator.toString() + "/" + denominator.toString(); + break; + } + } + } + } else { + if (isExpression) { + while (true) { + let left = randint(0, maxInput); + let right = randint(0, maxInput).toString(); + if (left > right) { + a = + "(" + + left.toString() + + operation + + right.toString() + + ")!"; + break; + } + } + } else { + a = randint(0, maxInput).toString() + "!"; + } } - - return [`$${a}!=$`, `$${b}$`]; + const b = evaluate(a); + return hasLatexOutput ? [`$${a}=$`, `$${b}$`] : [`${a}`, `${b}`]; } -export function fraction_multiplication(max_val=10) { +export function fraction_multiplication(max_val = 10) { const a = randint(1, max_val); let b = randint(1, max_val); const c = randint(1, max_val); @@ -115,13 +171,16 @@ export function fraction_multiplication(max_val=10) { const gcd = calculate_gcd(tmp_n, tmp_d); const problem = `$\\frac{${a}}{${b}}\\cdot\\frac{${c}}{${d}}=$`; - const solution = (tmp_d == 1 || tmp_d == gcd) ? - `$\\frac{${tmp_n}}{${gcd}}$` : - `$\\frac{${Math.floor(tmp_n / gcd)}}{${Math.floor(tmp_d / gcd)}}$`; + const solution = + tmp_d == 1 || tmp_d == gcd + ? `$\\frac{${tmp_n}}{${gcd}}$` + : `$\\frac{${Math.floor(tmp_n / gcd)}}{${Math.floor( + tmp_d / gcd + )}}$`; return [problem, solution]; } -export function fraction_to_decimal(max_res=99, max_divid=99) { +export function fraction_to_decimal(max_res = 99, max_divid = 99) { const a = randint(1, max_res); const b = randint(1, Math.min(max_res, max_divid)); const c = Math.round(a / b, 2); @@ -129,7 +188,7 @@ export function fraction_to_decimal(max_res=99, max_divid=99) { return [`$\\frac{${a}}{${b}}=$`, `$${c}$`]; } -export function greatest_common_divisor(numbers_count=2, max_num=10**3) { +export function greatest_common_divisor(numbers_count = 2, max_num = 10 ** 3) { numbers_count = Math.max(numbers_count, 2); let numbers = []; for (let i = 0; i < numbers_count; i++) { @@ -137,37 +196,40 @@ export function greatest_common_divisor(numbers_count=2, max_num=10**3) { } let greatest_common_divisor = calculate_gcd(numbers[0], numbers[1]); for (let i = 0; i < numbers_count; i++) { - greatest_common_divisor = calculate_gcd(greatest_common_divisor, numbers[i]); + greatest_common_divisor = calculate_gcd( + greatest_common_divisor, + numbers[i] + ); } - return [`$GCD(${numbers.join(', ')})=$`, `$${greatest_common_divisor}$`]; + return [`$GCD(${numbers.join(", ")})=$`, `$${greatest_common_divisor}$`]; } -export function is_composite(max_num=250) { +export function is_composite(max_num = 250) { const a = randint(2, max_num); const problem = `Is $${a}$ composite?`; - if (a == 0 || a == 1) return [problem, 'No']; + if (a == 0 || a == 1) return [problem, "No"]; for (let i = 2; i < a; i++) { - if (a % i == 0) return [problem, 'Yes']; + if (a % i == 0) return [problem, "Yes"]; } - const solution = 'No'; + const solution = "No"; return [problem, solution]; } -export function is_prime(max_num=100) { +export function is_prime(max_num = 100) { const a = randint(2, max_num); const problem = `Is $${a}$ prime?`; - if (a == 2) return [problem, 'Yes']; - if (a % 2 == 0) return [problem, 'No']; + if (a == 2) return [problem, "Yes"]; + if (a % 2 == 0) return [problem, "No"]; for (let i = 3; i < Math.floor(a / 2) + 1; i += 2) { - if (a % i == 0) return [problem, 'No']; + if (a % i == 0) return [problem, "No"]; } - const solution = 'Yes'; + const solution = "Yes"; return [problem, solution]; } -export function multiplication(max_multi=12) { +export function multiplication(max_multi = 12) { const a = randint(0, max_multi); const b = randint(0, max_multi); const c = a * b; @@ -175,26 +237,37 @@ export function multiplication(max_multi=12) { return [`$${a}\\cdot${b}=$`, `$${c}$`]; } -export function percentage_difference(max_value=200, min_value=0) { +export function percentage_difference(max_value = 200, min_value = 0) { const value_a = randint(min_value, max_value); const value_b = randint(min_value, max_value); - let difference = Math.round(2 * (Math.abs(value_a - value_b) / Math.abs(value_a + value_b)) * 100); - - return [`What is the percentage difference between $${value_a}$ and $${value_b}$?`, `$${difference}$%`]; + let difference = Math.round( + 2 * (Math.abs(value_a - value_b) / Math.abs(value_a + value_b)) * 100 + ); + + return [ + `What is the percentage difference between $${value_a}$ and $${value_b}$?`, + `$${difference}$%`, + ]; } -export function percentage_error(max_value=100, min_value=-100) { +export function percentage_error(max_value = 100, min_value = -100) { let observed_value = randint(min_value, max_value); const exact_value = randint(min_value, max_value); if (observed_value * exact_value < 0) observed_value = -observed_value; - const error = Math.round(Math.abs(observed_value - exact_value) / Math.abs(exact_value) * 100, 2); + const error = Math.round( + (Math.abs(observed_value - exact_value) / Math.abs(exact_value)) * 100, + 2 + ); - return [`Find the percentage error when observed value equals $${observed_value}$ and exact value equals $${exact_value}$.`, `$${error}$%`]; + return [ + `Find the percentage error when observed value equals $${observed_value}$ and exact value equals $${exact_value}$.`, + `$${error}$%`, + ]; } -export function power_of_powers(max_base=50, max_power=10) { +export function power_of_powers(max_base = 50, max_power = 10) { const base = randint(1, max_base); const power_a = randint(1, max_power); const power_b = randint(1, max_power); @@ -203,14 +276,14 @@ export function power_of_powers(max_base=50, max_power=10) { return [`$${base}^{${power_a}^{${power_b}}}=$`, `$${base}^{${power_ab}}$`]; } -export function square(min_no=1, max_no=12) { +export function square(min_no = 1, max_no = 12) { const b = randint(min_no, max_no); const a = b * b; return [`$\\sqrt{${a}}=$`, `$${b}$`]; } -export function simplify_square_root(max_variable=100) { +export function simplify_square_root(max_variable = 100) { const y = randint(1, max_variable); let x = y; let factors = {}; @@ -227,7 +300,7 @@ export function simplify_square_root(max_variable=100) { let a = 1; let b = 1; for (let i = 0; i < factors.length; i++) { - if (factors[i] & 1 == 0) { + if (factors[i] & (1 == 0)) { a *= i * Math.floor(factors[i], 2); } else { a *= Math.pow(i, Math.floor(factors[i] - 1, 2)); @@ -238,7 +311,7 @@ export function simplify_square_root(max_variable=100) { return [`$\\sqrt{${y}}=$`, `$${a}\\sqrt{${b}}$`]; } -export function subtraction(max_minuend=99, max_diff=99) { +export function subtraction(max_minuend = 99, max_diff = 99) { const a = randint(0, max_minuend); const b = randint(Math.max(0, a - max_diff), a); const c = a - b; diff --git a/js_pkg/package-lock.json b/js_pkg/package-lock.json new file mode 100644 index 0000000..ebf127b --- /dev/null +++ b/js_pkg/package-lock.json @@ -0,0 +1,182 @@ +{ + "name": "mathgenerator", + "version": "1.4.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "mathgenerator", + "version": "1.4.1", + "license": "ISC", + "dependencies": { + "mathjs": "^11.5.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", + "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", + "dependencies": { + "regenerator-runtime": "^0.13.11" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/complex.js": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz", + "integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + }, + "node_modules/escape-latex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz", + "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==" + }, + "node_modules/fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==", + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://www.patreon.com/infusion" + } + }, + "node_modules/javascript-natural-sort": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==" + }, + "node_modules/mathjs": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-11.5.0.tgz", + "integrity": "sha512-vJ/+SqWtxjW6/aeDRt8xL3TlOVKqwN15BIyTGVqGbIWuiqgY4SxZ0yLuna82YH9CB757iFP7uJ4m3KvVBX7Qcg==", + "dependencies": { + "@babel/runtime": "^7.20.6", + "complex.js": "^2.1.1", + "decimal.js": "^10.4.3", + "escape-latex": "^1.2.0", + "fraction.js": "^4.2.0", + "javascript-natural-sort": "^0.7.1", + "seedrandom": "^3.0.5", + "tiny-emitter": "^2.1.0", + "typed-function": "^4.1.0" + }, + "bin": { + "mathjs": "bin/cli.js" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "node_modules/seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" + }, + "node_modules/tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + }, + "node_modules/typed-function": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.1.0.tgz", + "integrity": "sha512-DGwUl6cioBW5gw2L+6SMupGwH/kZOqivy17E4nsh1JI9fKF87orMmlQx3KISQPmg3sfnOUGlwVkroosvgddrlg==", + "engines": { + "node": ">= 14" + } + } + }, + "dependencies": { + "@babel/runtime": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.7.tgz", + "integrity": "sha512-UF0tvkUtxwAgZ5W/KrkHf0Rn0fdnLDU9ScxBrEVNUprE/MzirjK4MJUX1/BVDv00Sv8cljtukVK1aky++X1SjQ==", + "requires": { + "regenerator-runtime": "^0.13.11" + } + }, + "complex.js": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz", + "integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==" + }, + "decimal.js": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz", + "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==" + }, + "escape-latex": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz", + "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==" + }, + "fraction.js": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz", + "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==" + }, + "javascript-natural-sort": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz", + "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==" + }, + "mathjs": { + "version": "11.5.0", + "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-11.5.0.tgz", + "integrity": "sha512-vJ/+SqWtxjW6/aeDRt8xL3TlOVKqwN15BIyTGVqGbIWuiqgY4SxZ0yLuna82YH9CB757iFP7uJ4m3KvVBX7Qcg==", + "requires": { + "@babel/runtime": "^7.20.6", + "complex.js": "^2.1.1", + "decimal.js": "^10.4.3", + "escape-latex": "^1.2.0", + "fraction.js": "^4.2.0", + "javascript-natural-sort": "^0.7.1", + "seedrandom": "^3.0.5", + "tiny-emitter": "^2.1.0", + "typed-function": "^4.1.0" + } + }, + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + }, + "seedrandom": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz", + "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==" + }, + "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + }, + "typed-function": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.1.0.tgz", + "integrity": "sha512-DGwUl6cioBW5gw2L+6SMupGwH/kZOqivy17E4nsh1JI9fKF87orMmlQx3KISQPmg3sfnOUGlwVkroosvgddrlg==" + } + } +} diff --git a/js_pkg/package.json b/js_pkg/package.json index 2a371ca..b65f0e1 100644 --- a/js_pkg/package.json +++ b/js_pkg/package.json @@ -16,5 +16,8 @@ "bugs": { "url": "https://github.com/lukew3/mathgenerator/issues" }, - "homepage": "https://github.com/lukew3/mathgenerator#readme" + "homepage": "https://github.com/lukew3/mathgenerator#readme", + "dependencies": { + "mathjs": "^11.5.0" + } }