{"id":20660995,"url":"https://github.com/liatemplates/algebrite","last_synced_at":"2026-04-17T23:34:49.490Z","repository":{"id":107256827,"uuid":"123974680","full_name":"LiaTemplates/Algebrite","owner":"LiaTemplates","description":"Template for the Algebrite JavaScript Computer-Algebra-System (CAS)  ","archived":false,"fork":false,"pushed_at":"2023-01-10T14:40:47.000Z","size":682,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-17T12:16:34.446Z","etag":null,"topics":["algebra","algebrite","cas","liascript","liascript-template","math","tutorials"],"latest_commit_sha":null,"homepage":"https://liascript.github.io/course/?https://raw.githubusercontent.com/liaTemplates/algebrite/master/README.md","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/LiaTemplates.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-03-05T20:28:35.000Z","updated_at":"2022-02-22T10:39:21.000Z","dependencies_parsed_at":null,"dependency_job_id":"9b451e7a-4222-4c7c-bb68-231fca10c6e4","html_url":"https://github.com/LiaTemplates/Algebrite","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LiaTemplates%2FAlgebrite","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LiaTemplates%2FAlgebrite/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LiaTemplates%2FAlgebrite/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/LiaTemplates%2FAlgebrite/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/LiaTemplates","download_url":"https://codeload.github.com/LiaTemplates/Algebrite/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242788095,"owners_count":20185215,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["algebra","algebrite","cas","liascript","liascript-template","math","tutorials"],"created_at":"2024-11-16T19:06:45.319Z","updated_at":"2026-04-17T23:34:49.483Z","avatar_url":"https://github.com/LiaTemplates.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!--\nauthor:   André Dietrich\n\nemail:    andre.dietrich@ovgu.de\n\nversion:  0.6.3\n\nlanguage: en\n\nedit:     true\n\nnarrator: US English Female\n\nlogo:     https://live.staticflickr.com/7327/11125348744_2a75b75427_b.jpg\n\ncomment:  Template for the Algebrite JavaScript Computer-Algebra-System (CAS).\n\nscript:   dist/index.js\n\nattribute: [Algebrite](http://algebrite.org/)\n           by [Davide Della Casa](http://davidedc.com/)\n           is licensed under [MIT](https://opensource.org/licenses/MIT)\n\n@onload\nwindow.inputClean = function(input) {\n  const commas = [\",\", \"‚\", \"﹐\", \"，\", \"､\"];\n  for(let i=0; i\u003ccommas.length; i++) {\n    input = input.replace(new RegExp(\"\\\\\" + commas[i], \"g\"), \".\");\n    input = input.replace(/(\\d+(?:\\.\\d+)?)\\s*%/g, (_, num) =\u003e (parseFloat(num) / 100).toString());\n  }\n\n  input = input.replace(/\\\\/g, \"/\");\n\n  return input;\n}\n\nwindow.normalizeInputToArray = function(raw) {\n  // Always start from a string\n  let input = String(raw ?? \"\").trim();\n\n  // If it might be JSON text, first make it JSON-safe (turn \\frac -\u003e \\\\frac etc.)\n  const looksLikeJson = /^[\\[\\{\"]/.test(input);\n  if (looksLikeJson) input = input.replace(/\\\\/g, \"\\\\\\\\\");\n\n  // Try JSON parsing only when it looks like JSON\n  if (looksLikeJson) {\n    try {\n      const parsed = JSON.parse(input);\n\n      // JSON string -\u003e wrap into array\n      if (typeof parsed === \"string\") return [parsed.trim()];\n\n      // JSON array -\u003e normalize items to strings\n      if (Array.isArray(parsed)) return parsed.map(x =\u003e String(x).trim());\n\n      // Anything else (object/number/etc.) -\u003e stringify-ish fallback\n      return [String(parsed).trim()];\n    } catch (e) {\n      // fall through to plain-string handling\n    }\n  }\n\n  // Plain string input (e.g. \\frac{12}{1}) -\u003e just wrap\n  // If you want to also \"fix\" \\frac into \\\\frac for storage/transport, apply escape here too:\n  // input = window.escapeNonJsonBackslashes(input);\n  return [input.trim()];\n}\n\n// Usage:\nconst inputArr = normalizeInputToArray(String.raw`@input`);\n\n@end\n\n@Algebrite.eval: \u003cscript\u003e window.Algebrite.run(`@input`) \u003c/script\u003e\n\n@Algebrite.check: \u003cscript\u003e\n  let input = window.normalizeInputToArray(String.raw`@input`);\n\n  window.console.warn(\"Parsed input:\", input);\n\n  if (input.length == 0) {\n    send.lia(\"No input provided\",[],false);\n  }\n\n  input = input.map(item =\u003e window.latexToMath(item));\n\n  let output = \"@0\".trim();\n\n  if(output.startsWith(\"[\") \u0026\u0026 output.endsWith(\"]\")) {\n    output = output.slice(1, -1).split(\";\").map(item =\u003e item.trim());\n  } else {\n    output = [output];\n  }\n\n  let rslt = true;\n  for (let i=0; i\u003cinput.length; i++) {\n    if (input[i] == \"\") {\n        rslt = false;\n        break;\n    }\n    try {\n      let expression = `(${input[i]}) - (${output[i]}) == 0`;\n      expression = window.inputClean(expression);\n      let result = window.Algebrite.simplify(expression);\n\n      window.console.warn(\"Result:\", result);\n      if (!result.q.a || result.q.a.value != 1n ) {\n        rslt = false;\n        break;\n      }\n    } catch(e) {\n      rslt = false;\n      break;\n    }\n    rslt;\n  }\n  \u003c/script\u003e\n\n@Algebrite.check_expression: \u003cscript\u003e\n  let input = window.normalizeInputToArray(String.raw`@input`)[0];\n\n  input = window.latexToMath(input);\n\n  if (input.length == 0) {\n    send.lia(\"No input provided\",[],false);\n  } else {\n    try {\n      let solution = window.inputClean(\"@0\");\n      solution = solution.split(\"=\");\n      solution = solution[0] + \"-\" + solution[1];\n\n      let expression = window.inputClean(\"@input\");\n      expression = expression.split(\"=\");\n\n      expression = expression[0] + \"-\" + expression[1];\n\n      let result = window.Algebrite.run(`${solution} - (${expression})`);\n\n      result == \"0\";\n    } catch(e) {\n      false;\n    }\n  }\n  \u003c/script\u003e\n\n@Algebrite.check2: \u003cscript\u003e\n  let input = window.normalizeInputToArray(String.raw`@input`);\n\n  if (input.length == 0) {\n    send.lia(\"No input provided\",[],false);\n  }\n\n  input = input.map(item =\u003e window.latexToMath(item));\n\n  let lowerBounds = \"@0\".trim();\n  let upperBounds = \"@1\".trim();\n\n  if(lowerBounds.startsWith(\"[\") \u0026\u0026 lowerBounds.endsWith(\"]\")) {\n    lowerBounds = lowerBounds.slice(1, -1).split(\";\").map(item =\u003e item.trim());\n  } else {\n    lowerBounds = [lowerBounds];\n  }\n\n  if(upperBounds.startsWith(\"[\") \u0026\u0026 upperBounds.endsWith(\"]\")) {\n    upperBounds = upperBounds.slice(1, -1).split(\";\").map(item =\u003e item.trim());\n  } else {\n    upperBounds = [upperBounds];\n  }\n\n  let rslt = true;\n  for (let i=0; i\u003cinput.length; i++) {\n    if (input[i] == \"\") {\n        rslt = false;\n        break;\n    }\n    try {\n      let expression = `abs((${input[i]}) - (${lowerBounds[i]})) \u003c ${upperBounds[i]}`;\n      expression = window.inputClean(expression);\n      let result = window.Algebrite.simplify(expression);\n\n      window.console.warn(\"Result:\", result);\n      if (!result.q.a || result.q.a.value != 1n ) {\n        rslt = false;\n        break;\n      }\n    } catch(e) {\n      rslt = false;\n      break;\n    }\n    rslt;\n  }\n  \u003c/script\u003e\n\n@Algebrite.check_margin: \u003cscript\u003e\n  let input = window.normalizeInputToArray(String.raw`@input`)[0];\n\n  input = window.latexToMath(input);\n\n  if (input.length == 0) {\n    send.lia(\"No input provided\",[],false);\n  } else {\n    try {\n      let expression = window.inputClean(window.latexToMath(input));\n      expression = `and((@0) \u003c= (${expression}), (${expression}) \u003c= (@1))`;\n      let result = window.Algebrite.simplify(expression);\n      result == \"1\";\n    } catch(e) {\n      false;\n    }\n  }\n  \u003c/script\u003e\n\n--\u003e\n\n# Algebrite - Template\n\n\n\n                         --{{0}}--\nTemplate for the Algebrite JavaScript Computer-Algebra-System (CAS)\nhttps://algebrite.org to be used in [LiaScript](https://LiaScript.github.io) to\nmake Markdown code-blocks executable.\n\n__Try it on LiaScript:__\n\nhttps://liascript.github.io/course/?https://raw.githubusercontent.com/liaTemplates/algebrite/master/README.md\n\n__See the project on Github:__\n\nhttps://github.com/liaTemplates/algebrite\n\n                         --{{1}}--\nLike with other LiaScript templates, there are three ways to integrate\nAlgebrite, but the easiest way is to copy the defintion from\n[Sec. Implementation](#implementation).\n\n                           {{1}}\n1. Load the latest macros via (this might cause breaking changes)\n\n   `import: https://raw.githubusercontent.com/liaTemplates/algebrite/master/README.md`\n\n   or the current version 0.6.3 via:\n\n   `import: https://raw.githubusercontent.com/LiaTemplates/algebrite/0.6.3/README.md`\n\n2. __Copy the definitions into your Project__\n\n3. Clone this repository on GitHub\n\n\n## More Information\n\nAlgebrite is...\n\n* __lightweight__:    made to be simple to comprehend and extend, it only\n                      depends on [BigInteger.js by Peter Olson](https://github.com/peterolson/BigInteger.js).\n* __self-contained__: doesn't need connection to servers or another \"backend\" CAS\n* __a library__:      beyond use as an interactive tool, Algebrite can be\n                      embedded in your applications and extended with custom\n                      functions.\n* __free__:           MIT-Licenced\n\nFunction reference: http://algebrite.org/docs/latest-stable/reference.html\n\n\n## `@Algebrite.eval`\n\nThese examples are taken from the website http://algebrite.org double-click onto\nthe listing to edit it.\n\n``` Maxima\n(3 * x - 5x)^3 * (x + x)\n\n60!\n```\n@Algebrite.eval\n\nThe following example might take a few seconds ...\n\n```Maxima\nf=sin(t)^4-2*cos(t/2)^3*sin(t)\n\nf=circexp(f)\n\ndefint(f,t,0,2*pi)\n```\n@Algebrite.eval\n\n## Quizzes\n\n### `@Algebrite.check`\n\n                         --{{0}}--\nUsing the `@Algebrite.check` macro, you can combine this with quizzes, to compare the result of an expression with a given value with different expressions. You can for \n\n\n```\n6 + 6 \n\n[[12]]\n@Algebrite.check(12)\n```\n\n                          --{{1}}--\nTry out different results like `12,0`, `3*4`, etc.\n\n    {{1}}\n\u003cdiv\u003e\n\n6 + 6\n\n[[12]]\n@Algebrite.check(12)\n\n----\n\n\u003c/div\u003e\n\n\n\n                         --{{2}}--\nThe same can be done with more complex expressions, try different expressions of `x ^ 2 - 1` like `-1 + x * x`.\n\n\n    {{2}}\n\u003cdiv\u003e\n\n```\n[[x ^ 2 - 1]]\n@Algebrite.check(x^2-1)\n```\n\n----\n\n[[x ^ 2 - 1]]\n@Algebrite.check(x^2-1)\n\n\u003c/div\u003e\n\n\n    {{3}}\n$x=\\;$ [[ 2/5 ]] $\\;\\;\\wedge\\;\\; y=$  [[ 5/7 ]] $\\;\\;\\wedge\\;\\; z=$  [[ 3/4 ]]\n@Algebrite.check([ 2/5; 5/7; 3/4 ])\n\n### `@Algebrite.check2`\n\n                         --{{0}}--\nIf your result might need to cope with some rounding errors, you can use the\n`@Algebrite.check2` macro, which allows you to define a tolerance value as the second parameter.\n\n\u003cdiv\u003e\n\n```\n[[1/3]]\n@Algebrite.check2(1/3,0.01)\n```\n\n----\n\n[[1/3]]\n@Algebrite.check2(1/3,0.01)\n\n\u003c/div\u003e\n\n                        --{{1}}--\nIf you need more inputs, you can also provide lists of values as input and output:\n\n    {{1}}\n```\n$a=$ [[ 1/3 ]]\\\n$b=$ [[ 2/3 ]]\\\n$c=$ [[ 3/3 ]]\n@Algebrite.check2([ 1/3 ; 2/3 ; 3/3 ], [0.01 ; 0.01 ; 0.01])\n```\n\n    {{1}}\n$a=$ [[ 1/3 ]]\\\n$b=$ [[ 2/3 ]]\\\n$c=$ [[ 3/3 ]]\n@Algebrite.check2([ 1/3 ; 2/3 ; 3/3 ], [0.01 ; 0.01 ; 0.01])\n\n\n\n### `@Algebrite.check_margin`\n\n                         --{{0}}--\nThe `@Algebrite.check_margin` macro allows you to check if a value is within a certain range. This is useful for checking if a result is within a certain margin of error, while the first parameter defines the lower bound and the second parameter defines the upper bound.\n\n\n```\n-\u003e [[ 1.5 ]] $km$\n@Algebrite.check_margin(1.4, 1.6)\n```\n\n-\u003e [[ 1.5 ]] $km$\n@Algebrite.check_margin(1.4, 1.6)\n\n### `@Algebrite.check_expression`\n\n                          --{{0}}--\nTo check if an expression is equal to another expression, you can use the `@Algebrite.check_expression` macro.\n\n```\n[[x ^ 2 - 1 = 2x]]\n@Algebrite.check_expression(x^2-1-2x=0)\n```\n\n----\n\n[[x ^ 2 - 1 = 2x]]\n@Algebrite.check_expression(x^2-1-2x=0)\n\n\n## Implementation\n\n                         --{{0}}--\nCompared to other macros, using Algebrite is actually quite simple. The two\nlines below are sufficient, the first one\n\n\n``` html\nscript:   dist/index.js\n\n@onload\nwindow.inputClean = function(input) {\n  const commas = [\",\", \"‚\", \"﹐\", \"，\", \"､\"];\n  for(let i=0; i\u003ccommas.length; i++) {\n    input = input.replace(new RegExp(\"\\\\\" + commas[i], \"g\"), \".\");\n    input = input.replace(/(\\d+(?:\\.\\d+)?)\\s*%/g, (_, num) =\u003e (parseFloat(num) / 100).toString());\n  }\n\n  input = input.replace(/\\\\/g, \"/\");\n\n  return input;\n}\n@end\n\n@Algebrite.eval: \u003cscript\u003e window.Algebrite.run(`@input`) \u003c/script\u003e\n\n@Algebrite.check: \u003cscript\u003e\n  let input = `@input`;\n  \n  try {\n    const json = JSON.parse(input);\n    if (typeof json === \"string\") {\n      input = [json.trim()];\n    } else {\n      input = json.map(item =\u003e item.trim());\n    }\n  } catch (e) {\n    input = [input.trim()];\n  }\n\n  if (input.length == 0) {\n    send.lia(\"No input provided\",[],false);\n  }\n\n  input = input.map(item =\u003e window.latexToMath(item));\n\n  let output = \"@0\".trim();\n\n  if(output.startsWith(\"[\") \u0026\u0026 output.endsWith(\"]\")) {\n    output = output.slice(1, -1).split(\";\").map(item =\u003e item.trim());\n  } else {\n    output = [output];\n  }\n\n  let rslt = true;\n  for (let i=0; i\u003cinput.length; i++) {\n    if (input[i] == \"\") {\n        rslt = false;\n        break;\n    }\n    try {\n      let expression = `(${input[i]}) - (${output[i]}) == 0`;\n      expression = window.inputClean(expression);\n      let result = window.Algebrite.simplify(expression);\n\n      window.console.warn(\"Result:\", result);\n      if (!result.q.a || result.q.a.value != 1n ) {\n        rslt = false;\n        break;\n      }\n    } catch(e) {\n      rslt = false;\n      break;\n    }\n    rslt;\n  }\n  \u003c/script\u003e\n\n@Algebrite.check_expression: \u003cscript\u003e\n  let input = `@input`;\n  \n  try {\n    const json = JSON.parse(input);\n    if (Array.isArray(json)) {\n      input = json[0];\n    } \n  } catch (e) {}\n  input = input.trim();\n  input = window.latexToMath(input);\n\n  if (input.length == 0) {\n    send.lia(\"No input provided\",[],false);\n  } else {\n    try {\n      let solution = window.inputClean(\"@0\");\n      solution = solution.split(\"=\");\n      solution = solution[0] + \"-\" + solution[1];\n\n      let expression = window.inputClean(\"@input\");\n      expression = expression.split(\"=\");\n\n      expression = expression[0] + \"-\" + expression[1];\n\n      let result = window.Algebrite.run(`${solution} - (${expression})`);\n\n      result == \"0\";\n    } catch(e) {\n      false;\n    }\n  }\n  \u003c/script\u003e\n\n@Algebrite.check2: \u003cscript\u003e\n  let input = `@input`;\n  \n  try {\n    const json = JSON.parse(input);\n    if (typeof json === \"string\") {\n      input = [json.trim()];\n    } else {\n      input = json.map(item =\u003e item.trim());\n    }\n  } catch (e) {\n    input = [input.trim()];\n  }\n\n  if (input.length == 0) {\n    send.lia(\"No input provided\",[],false);\n  }\n\n  input = input.map(item =\u003e window.latexToMath(item));\n\n  let lowerBounds = \"@0\".trim();\n  let upperBounds = \"@1\".trim();\n\n  if(lowerBounds.startsWith(\"[\") \u0026\u0026 lowerBounds.endsWith(\"]\")) {\n    lowerBounds = lowerBounds.slice(1, -1).split(\";\").map(item =\u003e item.trim());\n  } else {\n    lowerBounds = [lowerBounds];\n  }\n\n  if(upperBounds.startsWith(\"[\") \u0026\u0026 upperBounds.endsWith(\"]\")) {\n    upperBounds = upperBounds.slice(1, -1).split(\";\").map(item =\u003e item.trim());\n  } else {\n    upperBounds = [upperBounds];\n  }\n\n  let rslt = true;\n  for (let i=0; i\u003cinput.length; i++) {\n    if (input[i] == \"\") {\n        rslt = false;\n        break;\n    }\n    try {\n      let expression = `abs((${input[i]}) - (${lowerBounds[i]})) \u003c ${upperBounds[i]}`;\n      expression = window.inputClean(expression);\n      let result = window.Algebrite.simplify(expression);\n\n      window.console.warn(\"Result:\", result);\n      if (!result.q.a || result.q.a.value != 1n ) {\n        rslt = false;\n        break;\n      }\n    } catch(e) {\n      rslt = false;\n      break;\n    }\n    rslt;\n  }\n  \u003c/script\u003e\n\n@Algebrite.check_margin: \u003cscript\u003e\n  let input = `@input`; \n  try {\n    const json = JSON.parse(input);\n    if (Array.isArray(json)) {\n      input = json[0];\n    } \n  } catch (e) {}\n\n  input = input.trim();\n\n  if (input.length == 0) {\n    send.lia(\"No input provided\",[],false);\n  } else {\n    try {\n      let expression = window.inputClean(window.latexToMath(input));\n      expression = `and((@0) \u003c= (${expression}), (${expression}) \u003c= (@1))`;\n      let result = window.Algebrite.simplify(expression);\n      result == \"1\";\n    } catch(e) {\n      false;\n    }\n  }\n  \u003c/script\u003e\n```\n\n                         --{{1}}--\nIf you want to minimize loading effort in your LiaScript project, you can also\ncopy this code and paste it into your main comment header, see the code in the\nraw file of this document.\n\n{{1}} https://raw.githubusercontent.com/liaTemplates/algebrite/master/README.md\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliatemplates%2Falgebrite","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fliatemplates%2Falgebrite","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fliatemplates%2Falgebrite/lists"}