// Numbas version: finer_feedback_settings {"name": "Demo variable number of gaps", "extensions": [], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "question_groups": [{"pickingStrategy": "all-ordered", "questions": [{"name": "Demo variable number of gaps", "tags": ["demo", "variable number of gaps"], "metadata": {"description": "

In this demo question, you can see either 2 or 3 gaps depending on the variable \\(m\\), and the marking algorithm doesn't penalise for the empty third gap in cases when it is not shown.

\n

Reason to use it: for vectors or matrices containing only numbers, one can easily use matrix entry to account for a random size of an answer. But this does not work for mathematical expressions. There we have to give each entry of the vector as a separate gap, which then becomes a problem when the size varies. This solves that problem. For this reason I've included two parts: one very simple one that just shows the phenomenon of variable number of gaps, and one which is more like why I  needed it.

\n

Note that to resolve the fact that when \\(m=2\\), the point for the third gap cannot be earned, I have made it so that the student only gets 0 or all points, when all shown gaps are correctly filled in.

\n

Note the use of Ax[m-1] in the third gap \"correct answer\" of part b): if you use Ax[2], then it will throw an error when m=2, as then Ax won't have the correct size. So even though the marking algorithm will ignore it, the question would still not work.

\n

Bonus demo if you look in the variables: A way to automatically generate the correct latex code for \\(\\var{latexAx}\\), since it's a variable size. I would usually  need that in the \"Advice\", i.e. solutions, rather than the question text.

", "licence": "Creative Commons Attribution 4.0 International"}, "statement": "

In this demo question, you can see either 2 or 3 gaps depending on the variable \\(m\\), and the marking algorithm doesn't penalise for the empty third gap in cases when it is not shown.

\n

Reason to use it: for vectors or matrices containing only numbers, one can easily use matrix entry to account for a random size of an answer. But this does not work for mathematical expressions. There we have to give each entry of the vector as a separate gap, which then becomes a problem when the size varies. This solves that problem. For this reason I've included two parts: one very simple one that just shows the phenomenon of variable number of gaps, and one which is more like why I  needed it.

\n

Note that to resolve the fact that when \\(m=2\\), the point for the third gap cannot be earned, I have made it so that the student only gets 0 or all points, when all shown gaps are correctly filled in.

", "advice": "

\n

", "rulesets": {}, "extensions": [], "variables": {"A": {"name": "A", "group": "Ungrouped variables", "definition": "matrix(repeat([1,-1,1],m))", "description": "", "templateType": "anything"}, "m": {"name": "m", "group": "Ungrouped variables", "definition": "random(2..3)", "description": "", "templateType": "anything"}, "n": {"name": "n", "group": "Ungrouped variables", "definition": "3", "description": "", "templateType": "anything"}, "x": {"name": "x", "group": "Ungrouped variables", "definition": "map('x_{k}',k,1..n)", "description": "

general vector x.  ['x_1','x_2','x_3'] As list because vector can only take numbers as entries.

", "templateType": "anything"}, "latexAx": {"name": "latexAx", "group": "Ungrouped variables", "definition": "latex('\\\\begin{pmatrix}'+ concatstrings(halfrawAx) +'\\\\end{'+'pmatrix}')", "description": "

Ax as needed for latex string

", "templateType": "anything"}, "rawAx": {"name": "rawAx", "group": "Ungrouped variables", "definition": "map('{A[k][l]}*'+x[{l}]+symbols2(m,n)[k][l],[k,l],product(0..m-1,0..n-1))", "description": "", "templateType": "anything"}, "halfrawAx": {"name": "halfrawAx", "group": "Ungrouped variables", "definition": "map(string(simplify(expression(concatstrings(rawAx[(n*k)..(n*k+n)])),\"all\"))+symbols3(m)[k],k,0..m-1)", "description": "", "templateType": "anything"}, "Ax": {"name": "Ax", "group": "Ungrouped variables", "definition": "map(simplify(expression(concatstrings(rawAx[(n*k)..(n*k+n)])),[\"all\",\"!noleadingminus\"]),k,0..m-1)", "description": "

Ax as list, can be used as expected answer.

", "templateType": "anything"}, "xalt": {"name": "xalt", "group": "Ungrouped variables", "definition": "map('x{k}',k,1..n)", "description": "

alternative way of writing the variables in mathematical expression for part b

", "templateType": "anything"}, "rawAxalt": {"name": "rawAxalt", "group": "Ungrouped variables", "definition": "map('{A[k][l]}*'+xalt[{l}]+symbols2(m,n)[k][l],[k,l],product(0..m-1,0..n-1))", "description": "

alternative way of writing the variables in mathematical expression for part b

", "templateType": "anything"}, "Axalt": {"name": "Axalt", "group": "Ungrouped variables", "definition": "map(simplify(expression(concatstrings(rawAxalt[(n*k)..(n*k+n)])),[\"all\",\"!noleadingminus\"]),k,0..m-1)", "description": "

alternative way of writing the variables in mathematical expression for part b

", "templateType": "anything"}}, "variablesTest": {"condition": "", "maxRuns": "100"}, "ungrouped_variables": ["A", "m", "n", "x", "rawAx", "halfrawAx", "latexAx", "Ax", "xalt", "rawAxalt", "Axalt"], "variable_groups": [], "functions": {"concatstrings": {"parameters": [["input", "list"]], "type": "string", "language": "javascript", "definition": "var output = '';\nvar i;\nfor (i = 0; i < input.length; i++) {\n output += input[i];\n} \nreturn output;"}, "symbols2": {"parameters": [["m", "number"], ["n", "number"]], "type": "list", "language": "jme", "definition": "repeat(repeat('+',n-1)+[''],m-1)+[repeat('+',n-1)+['']]"}, "symbols3": {"parameters": [["m", "number"]], "type": "list", "language": "jme", "definition": "repeat('\\\\\\\\',m-1)+['']"}}, "preamble": {"js": "", "css": ""}, "parts": [{"type": "gapfill", "useCustomName": false, "customName": "", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "mygaps (Pick the correct number of gaps depending on the variable m):\n gaps[0..m]\n\nmystudentAnswer (Pick the correct number of gaps in student answer):\n studentAnswer[0..m]\n\nmarked_original_order (Mark the gaps in the original order, mainly to establish if every gap has a valid answer):\n map(\n mark_part(gap[\"path\"],studentAnswer),\n [gap,studentAnswer],\n zip(mygaps,mystudentAnswer)\n )\n\n\ngap_order:\n if(settings[\"sortAnswers\"],\n sort_destinations(interpreted_answers)\n ,\n list(0..len(mygaps)-1)\n )\n\ngap_feedback (Feedback on each of the gaps):\n map(\n let(result,submit_part(mygaps[gap_number][\"path\"],answer),\n feedback(translate('part.gapfill.feedback header',[\"index\":index]));\n concat_feedback(result[\"feedback\"], result[\"marks\"]/marks);\n result\n ),\n [gap_number,answer,index],\n zip(gap_order,mystudentAnswer,list(1..len(mygaps)))\n )\n\ngap_correct:\n map(result[\"credit\"]=1,result,gap_feedback)\n\n\nall_correct:\n correctif(all(gap_correct))\n\n\nmark:\n assert(all_valid, fail(translate(\"question.can not submit\")));\n apply(answers); \n apply(all_correct)\n", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Enter the first \\(\\var{m}\\) integers, starting from \\(1\\).

\n

[[0]] [[1]][[2]]

\n

(Note that you can only apply the \"conditional visibility\" to the gap when it is in the form of [[ 2 ]] rather than visible in the editor as a gap.)

", "gaps": [{"type": "numberentry", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "1", "maxValue": "1", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "showFractionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "2", "maxValue": "2", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "showFractionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}, {"type": "numberentry", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "minValue": "3", "maxValue": "3", "correctAnswerFraction": false, "allowFractions": false, "mustBeReduced": false, "mustBeReducedPC": 0, "showFractionHint": true, "notationStyles": ["plain", "en", "si-en"], "correctAnswerStyle": "plain"}], "sortAnswers": false}, {"type": "gapfill", "useCustomName": false, "customName": "", "marks": 0, "scripts": {}, "customMarkingAlgorithm": "mygaps (Pick the correct number of gaps depending on the variable m):\n gaps[0..m]\n\nmystudentAnswer (Pick the correct number of gaps in student answer):\n studentAnswer[0..m]\n\nmarked_original_order (Mark the gaps in the original order, mainly to establish if every gap has a valid answer):\n map(\n mark_part(gap[\"path\"],studentAnswer),\n [gap,studentAnswer],\n zip(mygaps,mystudentAnswer)\n )\n\n\ngap_order:\n if(settings[\"sortAnswers\"],\n sort_destinations(interpreted_answers)\n ,\n list(0..len(mygaps)-1)\n )\n\ngap_feedback (Feedback on each of the gaps):\n map(\n let(result,submit_part(mygaps[gap_number][\"path\"],answer),\n feedback(translate('part.gapfill.feedback header',[\"index\":index]));\n concat_feedback(result[\"feedback\"], result[\"marks\"]/marks);\n result\n ),\n [gap_number,answer,index],\n zip(gap_order,mystudentAnswer,list(1..len(mygaps)))\n )\n\ngap_correct:\n map(result[\"credit\"]=1,result,gap_feedback)\n\n\nall_correct:\n correctif(all(gap_correct))\n\n\nmark:\n assert(all_valid, fail(translate(\"question.can not submit\")));\n apply(answers); \n apply(all_correct)\n", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

The correct answer to be entered is \\(\\var{latexAx}\\). Input \\(x_1\\) as x_1 or x1, etc. Use the same notation for all variables, don't mix it.

\n\n\n\n\n\n\n\n\n\n\n\n
\\(Ax= \\left(\\begin{matrix} \\phantom{.}\\\\\\phantom{.}\\\\\\phantom{.}\\end{matrix} \\right. \\)[[0]]\\(\\left.\\begin{matrix} \\phantom{.}\\\\\\phantom{.}\\\\\\phantom{.}\\end{matrix} \\right) \\)
[[1]]
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\\(Ax= \\left(\\begin{matrix} \\phantom{.}\\\\\\phantom{.}\\\\\\phantom{.}\\\\\\phantom{.}\\end{matrix} \\right. \\)[[0]]\\(\\left.\\begin{matrix} \\phantom{.}\\\\\\phantom{.}\\\\\\phantom{.}\\\\\\phantom{.}\\end{matrix} \\right) \\)
[[1]]
[[2]]
\n

Note the use of Ax[m-1] in the third gap \"correct answer\": if you use Ax[2], then it will throw an error when m=2, as then Ax won't have the correct size. So even though the marking algorithm will ignore it, the question would still not work.

\n

Bonus demo if you look in the variables: A way to automatically generate the correct latex code for \\(\\var{latexAx}\\), since it's a variable size. I would usually  need that in the \"Advice\", i.e. solutions, rather than the question text.

", "gaps": [{"type": "jme", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "alternatives": [{"type": "jme", "useCustomName": false, "customName": "", "marks": "1", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "alternativeFeedbackMessage": "", "useAlternativeFeedback": true, "answer": "{Axalt[0]}", "showPreview": true, "checkingType": "absdiff", "checkingAccuracy": 0.001, "failureRate": 1, "vsetRangePoints": 5, "vsetRange": [0, 1], "checkVariableNames": false, "singleLetterVariables": false, "allowUnknownFunctions": true, "implicitFunctionComposition": false, "valuegenerators": []}], "answer": "{Ax[0]}", "showPreview": true, "checkingType": "absdiff", "checkingAccuracy": 0.001, "failureRate": 1, "vsetRangePoints": 5, "vsetRange": [0, 1], "checkVariableNames": false, "singleLetterVariables": false, "allowUnknownFunctions": true, "implicitFunctionComposition": false, "valuegenerators": []}, {"type": "jme", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "alternatives": [{"type": "jme", "useCustomName": false, "customName": "", "marks": "1", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "alternativeFeedbackMessage": "", "useAlternativeFeedback": true, "answer": "{Axalt[1]}", "showPreview": true, "checkingType": "absdiff", "checkingAccuracy": 0.001, "failureRate": 1, "vsetRangePoints": 5, "vsetRange": [0, 1], "checkVariableNames": false, "singleLetterVariables": false, "allowUnknownFunctions": true, "implicitFunctionComposition": false, "valuegenerators": []}], "answer": "{Ax[1]}", "showPreview": true, "checkingType": "absdiff", "checkingAccuracy": 0.001, "failureRate": 1, "vsetRangePoints": 5, "vsetRange": [0, 1], "checkVariableNames": false, "singleLetterVariables": false, "allowUnknownFunctions": true, "implicitFunctionComposition": false, "valuegenerators": []}, {"type": "jme", "useCustomName": false, "customName": "", "marks": 1, "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "alternatives": [{"type": "jme", "useCustomName": false, "customName": "", "marks": "1", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "alternativeFeedbackMessage": "", "useAlternativeFeedback": true, "answer": "{Axalt[m-1]}", "showPreview": true, "checkingType": "absdiff", "checkingAccuracy": 0.001, "failureRate": 1, "vsetRangePoints": 5, "vsetRange": [0, 1], "checkVariableNames": false, "singleLetterVariables": false, "allowUnknownFunctions": true, "implicitFunctionComposition": false, "valuegenerators": []}], "answer": "{Ax[m-1]}", "showPreview": true, "checkingType": "absdiff", "checkingAccuracy": 0.001, "failureRate": 1, "vsetRangePoints": 5, "vsetRange": [0, 1], "checkVariableNames": false, "singleLetterVariables": false, "allowUnknownFunctions": true, "implicitFunctionComposition": false, "valuegenerators": []}], "sortAnswers": false}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always", "type": "question", "contributors": [{"name": "Julia Goedecke", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/5121/"}]}]}], "contributors": [{"name": "Julia Goedecke", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/5121/"}]}