// Numbas version: exam_results_page_options {"metadata": {"licence": "All rights reserved", "description": ""}, "duration": 0, "name": "EEE2013 Practice Digital Electronics Assignment 2018", "showQuestionGroupNames": false, "feedback": {"allowrevealanswer": true, "showanswerstate": true, "feedbackmessages": [], "advicethreshold": 0, "showactualmark": true, "intro": "

This practice assignment contains similar questions to the real evaluated assignment at the same levels of difficulty. The practice assignment is not timed but the real one will be. The practice assignment may be attempted any number of times when it is accessible, the real one can be attempted only once. Both are open-book. 

", "showtotalmark": true}, "navigation": {"showfrontpage": true, "preventleave": true, "browse": true, "allowregen": true, "onleave": {"message": "", "action": "none"}, "showresultspage": "oncompletion", "reverse": true}, "showstudentname": true, "timing": {"timeout": {"message": "", "action": "none"}, "allowPause": true, "timedwarning": {"message": "

Only 5 minutes left!

", "action": "warn"}}, "question_groups": [{"pickingStrategy": "all-ordered", "name": "Group", "pickQuestions": 1, "questions": [{"name": "CLA adder", "extensions": [], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Graeme Chester", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/189/"}, {"name": "Fei Xia", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/2603/"}], "advice": "", "statement": "

A binary carry look-ahead adder produces propagate and generate signals internally when adding two 4-bit numbers A and B together. The values for a particular addition are shown in the following table:-

\n

{table([['<i>P<sub>k']+reverse(p),['<i>G<sub>k']+reverse(g)],['<i>k',3,2,1,0])}

\n

These are used inside the adder to calculate the carry outputs for each bit $C_{k}$.

\n

a {bin2str(a)} {bin2dec(a)} 

\n

b {bin2str(b)} {bin2dec(b)}

\n

p {bin2str(p)} 

\n

g {bin2str(g)} 

\n

c {bin2str(c)} 

\n

s {bin2str(s)} cout {bin2str([c[3]])} {bin2dec(s+[c[3]])}

\n

", "tags": [], "preamble": {"css": "", "js": ""}, "functions": {"bin2dec": {"definition": "if(abs(bin)=0,\n 0,\n bin[0]+2*bin2dec(bin[1..abs(bin)])\n)", "type": "number", "parameters": [["bin", "list"]], "language": "jme"}, "bin2str": {"definition": "join(map(if(x=0,'0','1'),x,reverse(bin)),'')", "type": "string", "parameters": [["bin", "list"]], "language": "jme"}, "carry": {"definition": "if(abs(p)=0 or abs(g)=0,\n [],\n [if(p[0]*cin+g[0]>0.5,1,0)]+carry(if(p[0]*cin+g[0]>0.5,1,0),p[1..abs(p)],g[1..abs(g)])\n)", "type": "number", "parameters": [["cin", "number"], ["p", "list"], ["g", "list"]], "language": "jme"}}, "variables": {"cin": {"definition": "0", "description": "", "name": "cin", "templateType": "number", "group": "Ungrouped variables"}, "c1": {"definition": "carry(0,p,g)[1]", "description": "", "name": "c1", "templateType": "anything", "group": "Ungrouped variables"}, "g": {"definition": "map(x*y,[x,y],zip(a,b))\n", "description": "", "name": "g", "templateType": "anything", "group": "Ungrouped variables"}, "p": {"definition": "map(mod(x+y,2),[x,y],zip(a,b))\n", "description": "", "name": "p", "templateType": "anything", "group": "Ungrouped variables"}, "na": {"definition": "bin2dec(a)", "description": "", "name": "na", "templateType": "anything", "group": "Ungrouped variables"}, "ns": {"definition": "bin2dec(s+[c[abs(c)-1]])", "description": "", "name": "ns", "templateType": "anything", "group": "Ungrouped variables"}, "gp": {"definition": "carry(0,p,g)[abs(p)-1]", "description": "", "name": "gp", "templateType": "anything", "group": "Ungrouped variables"}, "a": {"definition": "[1]+repeat(random(0..1),3)", "description": "", "name": "a", "templateType": "anything", "group": "Ungrouped variables"}, "c": {"definition": "carry(0,p,g)\n", "description": "", "name": "c", "templateType": "anything", "group": "Ungrouped variables"}, "b": {"definition": "repeat(random(0..1),4)", "description": "", "name": "b", "templateType": "anything", "group": "Ungrouped variables"}, "nb": {"definition": "bin2dec(b)", "description": "", "name": "nb", "templateType": "anything", "group": "Ungrouped variables"}, "ss": {"definition": "bin2str(s)", "description": "", "name": "ss", "templateType": "anything", "group": "Ungrouped variables"}, "c2ci": {"definition": "carry(1,p,g)[2]", "description": "", "name": "c2ci", "templateType": "anything", "group": "Ungrouped variables"}, "debug": {"definition": "false", "description": "", "name": "debug", "templateType": "anything", "group": "Ungrouped variables"}, "s": {"definition": "map(mod(x+y,2),[x,y],zip(p,[cin]+c[0..abs(c)-1]))", "description": "", "name": "s", "templateType": "anything", "group": "Ungrouped variables"}, "pp": {"definition": "carry(1,p,repeat(0,abs(p)))[abs(p)-1]", "description": "", "name": "pp", "templateType": "anything", "group": "Ungrouped variables"}}, "rulesets": {}, "parts": [{"unitTests": [], "correctAnswerStyle": "plain", "type": "numberentry", "extendBaseMarkingAlgorithm": true, "correctAnswerFraction": false, "notationStyles": ["plain", "en", "si-en"], "variableReplacements": [], "scripts": {}, "variableReplacementStrategy": "originalfirst", "showCorrectAnswer": true, "maxValue": "c1", "allowFractions": false, "showFeedbackIcon": true, "mustBeReducedPC": 0, "minValue": "c1", "marks": 1, "prompt": "

Calculate the value of $C_1$ if $C_{IN}=0$

", "customMarkingAlgorithm": "", "mustBeReduced": false}, {"unitTests": [], "correctAnswerStyle": "plain", "type": "numberentry", "extendBaseMarkingAlgorithm": true, "correctAnswerFraction": false, "notationStyles": ["plain", "en", "si-en"], "variableReplacements": [], "scripts": {}, "variableReplacementStrategy": "originalfirst", "showCorrectAnswer": true, "maxValue": "c2ci", "allowFractions": false, "showFeedbackIcon": true, "mustBeReducedPC": 0, "minValue": "c2ci", "marks": "2", "prompt": "

Calculate the value of $C_2$ if $C_{IN}=1$

", "customMarkingAlgorithm": "", "mustBeReduced": false}, {"unitTests": [], "correctAnswerStyle": "plain", "type": "numberentry", "extendBaseMarkingAlgorithm": true, "correctAnswerFraction": false, "notationStyles": ["plain", "en", "si-en"], "variableReplacements": [], "scripts": {}, "variableReplacementStrategy": "originalfirst", "showCorrectAnswer": true, "maxValue": "bin2dec(s+[c[3]])", "allowFractions": false, "showFeedbackIcon": true, "mustBeReducedPC": 0, "minValue": "bin2dec(s+[c[3]])", "marks": "3", "prompt": "

The carry input $C_{IN}$ is {cin}. Find the sum of A and B as an unsigned decimal number 

", "customMarkingAlgorithm": "", "mustBeReduced": false}, {"unitTests": [], "type": "gapfill", "extendBaseMarkingAlgorithm": true, "gaps": [{"unitTests": [], "correctAnswerStyle": "plain", "type": "numberentry", "extendBaseMarkingAlgorithm": true, "correctAnswerFraction": false, "notationStyles": ["plain", "en", "si-en"], "variableReplacements": [], "scripts": {}, "variableReplacementStrategy": "originalfirst", "showCorrectAnswer": true, "maxValue": "pp", "allowFractions": false, "showFeedbackIcon": true, "mustBeReducedPC": 0, "minValue": "pp", "marks": 1, "customMarkingAlgorithm": "", "mustBeReduced": false}, {"unitTests": [], "correctAnswerStyle": "plain", "type": "numberentry", "extendBaseMarkingAlgorithm": true, "correctAnswerFraction": false, "notationStyles": ["plain", "en", "si-en"], "variableReplacements": [], "scripts": {}, "variableReplacementStrategy": "originalfirst", "showCorrectAnswer": true, "maxValue": "gp", "allowFractions": false, "showFeedbackIcon": true, "mustBeReducedPC": 0, "minValue": "gp", "marks": 1, "customMarkingAlgorithm": "", "mustBeReduced": false}], "variableReplacements": [], "sortAnswers": false, "scripts": {}, "variableReplacementStrategy": "originalfirst", "showCorrectAnswer": true, "showFeedbackIcon": true, "marks": 0, "prompt": "

This adder is now to be used in a block carry look-ahead scheme. Find the values of the signals

\n

block propagate $P'_{3\\dots0}$[[0]] and

\n

block generate $G'_{3\\dots0}$[[1]] 

", "customMarkingAlgorithm": ""}], "variable_groups": [], "ungrouped_variables": ["a", "b", "p", "g", "c1", "c2ci", "pp", "gp", "c", "s", "cin", "ns", "na", "nb", "ss", "debug"], "variablesTest": {"maxRuns": 100, "condition": ""}, "metadata": {"licence": "All rights reserved", "description": ""}, "type": "question"}, {"name": "Filling a Karnaugh Map", "extensions": [], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Graeme Chester", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/189/"}, {"name": "Fei Xia", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/2603/"}], "advice": "", "statement": "

A Boolean function of 4 variables is given as 

\n

$f=${join(cubetotext(c1,labels),'.')+'+'+join(cubetotext(c2,labels),'.')+'+'+join(cubetotext(c3,labels),'.')}

\n

{usermap()}

", "rulesets": {}, "tags": [], "metadata": {"description": "", "licence": "All rights reserved"}, "parts": [{"markPerCell": false, "unitTests": [], "numColumns": "4", "prompt": "

Complete the Karnaugh map for $f$ by inserting 0 or 1 in each element of the following matrix.

", "numRows": "4", "scripts": {}, "type": "matrix", "correctAnswer": "kmap", "variableReplacementStrategy": "originalfirst", "tolerance": 0, "showFeedbackIcon": true, "marks": "3", "showCorrectAnswer": true, "variableReplacements": [], "allowResize": false, "correctAnswerFractions": false, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "allowFractions": false}], "variable_groups": [], "functions": {"usermap": {"language": "javascript", "definition": "// draw a 4x4 Karnaugh map for a function given as a truth table\nfunction drawKmap(ctx,bits,literals)\n{\n\nctx.font = \"20px Arial\";ctx.textAlign=\"center\"; ctx.textBaseline=\"middle\";\n ctx.lineWidth=2;\n\n//ctx.fillText(n,10,50);\nctx.beginPath();\nctx.moveTo(20,20);\nctx.lineTo(60,60);\nctx.stroke();\n\nctx.fillText(literals[0]+\" \"+literals[1],15,50);\nctx.fillText(literals[2]+\" \"+literals[3],50,10);\ngraycodebin=[\"00\",\"01\",\"11\",\"10\"];\nfor (ncol=0;ncol<=3;ncol++) {\n\tctx.fillText(graycodebin[ncol],80+ncol*40,40);\n\t}\n\nfor (nrow=0;nrow<=3;nrow++) {\n\tctx.fillText(graycodebin[nrow],40,80+nrow*40);\n\tfor (ncol=0;ncol<=3;ncol++) {\n\t\tctx.rect(60+ncol*40,60+nrow*40,40,40);\n\t\tctx.stroke();\n\t\tbitval=bits[nrow][ncol].toString();\n\t\tctx.fillText(bitval,80+ncol*40,80+nrow*40);\n\t\t}\n\t}\n\n}\n\nvar canv=document.createElement(\"canvas\");\ncanv.setAttribute(\"height\",\"250px\");\ncanv.setAttribute(\"width\",\"500px\");\nvar ctx = canv.getContext(\"2d\");\n\nquestion.signals.on('HTMLAttached',function(e) {\n \n // Create a Knockout.js observable\n ko.computed(function(){\n // Get the student's input string from part 0.\n var studentString = question.parts[0].display.studentAnswer();\n ctx.clearRect(0, 0, canv.width, canv.height);\n drawKmap(ctx,studentString,['a','b','c','d'])\n });\n});\n \nreturn canv;", "parameters": [], "type": "html"}, "cubetotext": {"language": "jme", "definition": "// convert a cube to a formatted text string using recursion \n// fixed for bounding box problem 24-04-18\nif(abs(cube)=0,\n [],\n switch(cube[0]=0,\n [\"$\\\\bbox[2pt]{\\\\bar{\"+labels[0]+\"}}$\"],\n cube[0]=1,\n [\"$\"+labels[0]+\"$\"],[]) + cubetotext(cube[1..abs(cube)],labels[1..abs(labels)]\n )\n)\n", "parameters": [["cube", "list"], ["labels", "list"]], "type": "string"}, "f": {"language": "jme", "definition": "// convert a cube to canonical set form using recursion\nif(abs(p)=1, //terminate on the last or only element of p\n if(p[abs(p)-1]=2, //a \"don't care\" so include both 1 and 0\n set(0,1),\n if(p[abs(p)-1]=1,\n set(1),\n set(0)\n )\n ),\n//else\n if(p[abs(p)-1]=2,\n set(map(x*2,x,f(p[0..abs(p)-1]))) or set(map(x*2+1,x,f(p[0..abs(p)-1]))),\n if(p[abs(p)-1]=1,\n set(map(x*2+1,x,f(p[0..abs(p)-1]))),\n set(map(x*2,x,f(p[0..abs(p)-1])))\n )\n )\n)", "parameters": [["p", "list"]], "type": "set"}, "mat2cube": {"language": "jme", "definition": "if(abs(list(m))=0,\n [],\n [m[0]*2]+mat2cube(m[1..abs(list(m))])\n )", "parameters": [["m", "matrix"]], "type": "list"}}, "ungrouped_variables": ["a", "b", "c", "d", "e", "m", "n", "kmap1", "canonicalsum", "c1", "c2", "c3", "labels", "kmap"], "preamble": {"js": "", "css": ""}, "variablesTest": {"condition": "abs(list(f(c1)-f(c2)))>0 and\nabs(list(f(c2)-f(c3)))>0 and\nabs(list(f(c3)-f(c1)))>0\n", "maxRuns": 100}, "variables": {"n": {"description": "

mat2cube(m)

", "templateType": "anything", "definition": "0\n", "group": "Ungrouped variables", "name": "n"}, "d": {"description": "", "templateType": "anything", "definition": "false", "group": "Ungrouped variables", "name": "d"}, "canonicalsum": {"description": "", "templateType": "anything", "definition": "union(union(f(c1),f(c2)),f(c3))", "group": "Ungrouped variables", "name": "canonicalsum"}, "kmap": {"description": "

Convert a 4-variable Boolean function from canonical (minterm) set to Karnaugh map matrix

", "templateType": "anything", "definition": "map(if(x in canonicalsum,1,0),x,matrix(repeat([0,1,3,2],4))+4*transpose(matrix(repeat([0,1,3,2],4))))", "group": "Ungrouped variables", "name": "kmap"}, "b": {"description": "", "templateType": "anything", "definition": "false", "group": "Ungrouped variables", "name": "b"}, "labels": {"description": "", "templateType": "list of strings", "definition": "[ safe(\"a\"), safe(\"b\"), safe(\"c\"), safe(\"d\") ]", "group": "Ungrouped variables", "name": "labels"}, "a": {"description": "", "templateType": "anything", "definition": "false", "group": "Ungrouped variables", "name": "a"}, "m": {"description": "", "templateType": "anything", "definition": "matrix([1,2],[3,4],[5,6])", "group": "Ungrouped variables", "name": "m"}, "c1": {"description": "", "templateType": "anything", "definition": "shuffle([random(0..1),random(0..1),2,2])", "group": "Ungrouped variables", "name": "c1"}, "c3": {"description": "", "templateType": "anything", "definition": "shuffle([random(0..1),random(0..1),random(0..2),2])", "group": "Ungrouped variables", "name": "c3"}, "kmap1": {"description": "

Convert a 4-variable Boolean function from canonical (minterm) set to Karnaugh map matrix

\n

map(if((4*r+c) in canonicalsum,1,0),[r,c],product([0,1,3,2],[0,1,3,2]))

", "templateType": "anything", "definition": "map(if((4*r+c) in canonicalsum,1,0),[r,c],product([0,1,3,2],[0,1,3,2]))", "group": "Ungrouped variables", "name": "kmap1"}, "c2": {"description": "", "templateType": "anything", "definition": "shuffle([random(0..1),random(0..1),random(0..2),2])", "group": "Ungrouped variables", "name": "c2"}, "c": {"description": "", "templateType": "anything", "definition": "false", "group": "Ungrouped variables", "name": "c"}, "e": {"description": "", "templateType": "anything", "definition": "123", "group": "Ungrouped variables", "name": "e"}}, "type": "question"}, {"name": "Karnaugh map 2 2017", "extensions": ["booleanlogic"], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Graeme Chester", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/189/"}], "variables": {"dkmap": {"templateType": "anything", "group": "Unused variables", "description": "

Convert a 4-variable Boolean function from canonical (minterm) set to Karnaugh map matrix

", "definition": "map(if(x in canonicalsum,1,0),x,matrix(repeat([0,1,3,2],4))+4*transpose(matrix(repeat([0,1,3,2],4))))", "name": "dkmap"}, "dkmap1": {"templateType": "anything", "group": "Unused variables", "description": "

Convert a 4-variable Boolean function from canonical (minterm) set to Karnaugh map matrix

\n

map(if((4*r+c) in canonicalsum,1,0),[r,c],product([0,1,3,2],[0,1,3,2]))

", "definition": "map(if((4*r+c) in canonicalsum,1,0),[r,c],product([0,1,3,2],[0,1,3,2]))", "name": "dkmap1"}, "test": {"templateType": "anything", "group": "Unused variables", "description": "", "definition": "cubedist(c1,c3)", "name": "test"}, "canonicalsum": {"templateType": "anything", "group": "Ungrouped variables", "description": "", "definition": "union(union(union(f(c1),f(c2)),f(c3)),f(c4))", "name": "canonicalsum"}, "displayc": {"templateType": "anything", "group": "Unused variables", "description": "", "definition": "matrix(c1,c2,c3)", "name": "displayc"}, "labels": {"templateType": "list of strings", "group": "Ungrouped variables", "description": "", "definition": "[ \"a\", \"b\", \"c\", \"d\" ]", "name": "labels"}, "c1": {"templateType": "anything", "group": "Ungrouped variables", "description": "", "definition": "shuffle([random(0..1),random(0..1),random(0..2),2])", "name": "c1"}, "truthtablesum": {"templateType": "anything", "group": "Ungrouped variables", "description": "", "definition": "map(if(x in canonicalsum,1,0),x,0..15)", "name": "truthtablesum"}, "c3": {"templateType": "anything", "group": "Ungrouped variables", "description": "

shuffle([random(0..1),random(0..1),random(0..2),2])

", "definition": "shuffle([random(0..1),random(0..1),random(0..2),2])", "name": "c3"}, "c2": {"templateType": "anything", "group": "Ungrouped variables", "description": "", "definition": "shuffle([random(0..1),random(0..1),random(0..2),2])", "name": "c2"}, "c4": {"templateType": "anything", "group": "Ungrouped variables", "description": "", "definition": "shuffle([random(0..1),random(0..1),random(0..1),random(0..1)])", "name": "c4"}}, "variablesTest": {"condition": "abs(list(f(c1)-union(union(f(c2),f(c3)),f(c4))))>0 and //no redundant or duplicate terms\nabs(list(f(c2)-union(union(f(c1),f(c3)),f(c4))))>0 and \nabs(list(f(c3)-union(union(f(c2),f(c1)),f(c4))))>0 and \nabs(list(f(c4)-union(union(f(c2),f(c3)),f(c1))))>0 and \ncubedist(c3,c2)>1 and cubedist(c3,c1)>1 and cubedist(c2,c1)>1\nand cubedist(c4,c1)>1 and cubedist(c2,c4)>1 and cubedist(c4,c3)>1", "maxRuns": 100}, "variable_groups": [{"variables": ["dkmap", "dkmap1", "test", "displayc"], "name": "Unused variables"}, {"variables": [], "name": "test"}], "tags": [], "metadata": {"licence": "All rights reserved", "description": "

Development copy to test adding extra terms

"}, "advice": "

The function is equivalent to {join([join(cubetotext(c1,labels),'.'),join(cubetotext(c2,labels),'.'),join(cubetotext(c3,labels),'.'),join(cubetotext(c4,labels),'.')],'+')}

", "ungrouped_variables": ["canonicalsum", "c1", "c2", "c3", "c4", "labels", "truthtablesum"], "preamble": {"css": "", "js": ""}, "rulesets": {}, "functions": {"mat2cube": {"language": "jme", "definition": "if(abs(list(m))=0,\n [],\n [m[0]*2]+mat2cube(m[1..abs(list(m))])\n )", "type": "list", "parameters": [["m", "matrix"]]}, "test": {"language": "jme", "definition": "args[0] or args[1]", "type": "number", "parameters": [["args", "list"]]}, "cubetotext": {"language": "jme", "definition": "// convert a cube to a formatted text string using recursion \n// fixed for bounding box problem 24-04-18\nif(abs(cube)=0,\n [],\n switch(cube[0]=0,\n [\"$\\\\bbox[2pt]{\\\\bar{\"+labels[0]+\"}}$\"],\n cube[0]=1,\n [\"$\"+labels[0]+\"$\"],[]) + cubetotext(cube[1..abs(cube)],labels[1..abs(labels)]\n )\n)\n", "type": "string", "parameters": [["cube", "list"], ["labels", "list"]]}, "cubedist": {"language": "jme", "definition": "// find distance between two cubes using recursion\nif(abs(cube1)=0||abs(cube2)=0,\n 0,\n if(cube1[0]=cube2[0],\n cubedist(cube1[1..abs(cube1)], cube2[1..abs(cube2)]),\n cubedist(cube1[1..abs(cube1)], cube2[1..abs(cube2)])+1\n )\n)\n", "type": "number", "parameters": [["cube1", "list"], ["cube2", "list"]]}, "makeanswer": {"language": "jme", "definition": "((c1[0]=1) and a or (c1[0]=0) and not a or (c1[0]=2)) and \n((c1[1]=1) and b or (c1[1]=0) and not b or (c1[1]=2)) and \n((c1[2]=1) and c or (c1[2]=0) and not c or (c1[2]=2)) and \n((c1[3]=1) and d or (c1[3]=0) and not d or (c1[3]=2)) or \n\n((c2[0]=1) and a or (c2[0]=0) and not a or (c2[0]=2)) and \n((c2[1]=1) and b or (c2[1]=0) and not b or (c2[1]=2)) and \n((c2[2]=1) and c or (c2[2]=0) and not c or (c2[2]=2)) and \n((c2[3]=1) and d or (c2[3]=0) and not d or (c2[3]=2)) or \n\n((c3[0]=1) and a or (c3[0]=0) and not a or (c3[0]=2)) and \n((c3[1]=1) and b or (c3[1]=0) and not b or (c3[1]=2)) and \n((c3[2]=1) and c or (c3[2]=0) and not c or (c3[2]=2)) and \n((c3[3]=1) and d or (c3[3]=0) and not d or (c3[3]=2))", "type": "boolean", "parameters": [["c1", "list"], ["c2", "list"], ["c3", "list"], ["a", "boolean"], ["b", "boolean"], ["c", "boolean"], ["d", "boolean"]]}, "f": {"language": "jme", "definition": "// convert a cube to canonical set form using recursion\nif(abs(p)=1, //terminate on the last or only element of p\n if(p[abs(p)-1]=2, //a \"don't care\" so include both 1 and 0\n set(0,1),\n if(p[abs(p)-1]=1,\n set(1),\n set(0)\n )\n ),\n//else\n if(p[abs(p)-1]=2,\n set(map(x*2,x,f(p[0..abs(p)-1]))) or set(map(x*2+1,x,f(p[0..abs(p)-1]))),\n if(p[abs(p)-1]=1,\n set(map(x*2+1,x,f(p[0..abs(p)-1]))),\n set(map(x*2,x,f(p[0..abs(p)-1])))\n )\n )\n)", "type": "set", "parameters": [["p", "list"]]}, "evalpterm": {"language": "jme", "definition": "((c1[0]=1) and a or (c1[0]=0) and not a or (c1[0]=2)) and \n((c1[1]=1) and b or (c1[1]=0) and not b or (c1[1]=2)) and \n((c1[2]=1) and c or (c1[2]=0) and not c or (c1[2]=2)) and \n((c1[3]=1) and d or (c1[3]=0) and not d or (c1[3]=2))", "type": "boolean", "parameters": [["c1", "list"], ["a", "boolean"], ["b", "boolean"], ["c", "boolean"], ["d", "boolean"]]}, "drawKmapcanvas": {"language": "javascript", "definition": "// draw a 4x4 Karnaugh map for a function given as a truth table\nfunction drawKmap(ctx,bits,literals)\n{\n\nctx.font = \"20px Arial\";ctx.textAlign=\"center\"; ctx.textBaseline=\"middle\";\n ctx.lineWidth=2;\n\n//ctx.fillText(n,10,50);\nctx.beginPath();\nctx.moveTo(20,20);\nctx.lineTo(60,60);\nctx.stroke();\n\nctx.fillText(literals[0]+\" \"+literals[1],15,50);\nctx.fillText(literals[2]+\" \"+literals[3],50,10);\ngraycode=[0,1,3,2];\ngraycodebin=[\"00\",\"01\",\"11\",\"10\"];\nfor (ncol=0;ncol<=3;ncol++) {\n\tctx.fillText(graycodebin[ncol],80+ncol*40,40);\n\t}\n\nfor (nrow=0;nrow<=3;nrow++) {\n\tctx.fillText(graycodebin[nrow],40,80+nrow*40);\n\tfor (ncol=0;ncol<=3;ncol++) {\n\t\tctx.rect(60+ncol*40,60+nrow*40,40,40);\n\t\tctx.stroke();\n\t\tbitval=bits[graycode[nrow]*4+graycode[ncol]].toString();\n\t\tctx.fillText(bitval,80+ncol*40,80+nrow*40);\n\t\t}\n\t}\n\n}\n\n function drawcanvas(ctx)\n {\nvar num = 15;\nvar n = num.toString();\nctx.font = \"20px Arial\";ctx.textAlign=\"center\"; ctx.textBaseline=\"middle\";\n\nctx.fillText(n,10,50);\n\n\nfor (nrow=0;nrow<=3;nrow++) {\n\tctx.fillText(\"00\",40,80+nrow*40);\n\tfor (ncol=0;ncol<=3;ncol++) {\n\t\tctx.rect(60+ncol*40,60+nrow*40,40,40);\n\t\tctx.stroke();\n\t\tbitval=bits[nrow*4+ncol].toString();\n\t\tctx.fillText(bitval,80+ncol*40,80+nrow*40);\n\t\t}\n\t}\n\nctx.rect(0,0,400,300);\nctx.stroke();\n \n \n\t}\n\n\nvar canv=document.createElement(\"canvas\");\ncanv.setAttribute(\"height\",\"250px\");\ncanv.setAttribute(\"width\",\"500px\");\nvar ctx = canv.getContext(\"2d\");\n\n//literals=[\"a\",\"b\",\"c\",\"d\"];\ndrawKmap(ctx,bits,literals);\n//drawcanvas(ctx)\nreturn canv;", "type": "html", "parameters": [["bits", "list"], ["literals", "list"]]}, "usermap": {"language": "javascript", "definition": "// draw a 4x4 Karnaugh map for a function given as a truth table\nfunction drawKmap(ctx,bits,literals)\n{\n\nctx.font = \"20px Arial\";ctx.textAlign=\"center\"; ctx.textBaseline=\"middle\";\n ctx.lineWidth=2;\n\n//ctx.fillText(n,10,50);\nctx.beginPath();\nctx.moveTo(20,20);\nctx.lineTo(60,60);\nctx.stroke();\n\nctx.fillText(literals[0]+\" \"+literals[1],15,50);\nctx.fillText(literals[2]+\" \"+literals[3],50,10);\ngraycodebin=[\"00\",\"01\",\"11\",\"10\"];\nfor (ncol=0;ncol<=3;ncol++) {\n\tctx.fillText(graycodebin[ncol],80+ncol*40,40);\n\t}\n\nfor (nrow=0;nrow<=3;nrow++) {\n\tctx.fillText(graycodebin[nrow],40,80+nrow*40);\n\tfor (ncol=0;ncol<=3;ncol++) {\n\t\tctx.rect(60+ncol*40,60+nrow*40,40,40);\n\t\tctx.stroke();\n\t\tbitval=bits[nrow][ncol].toString();\n\t\tctx.fillText(bitval,80+ncol*40,80+nrow*40);\n\t\t}\n\t}\n\n}\n\nvar canv=document.createElement(\"canvas\");\ncanv.setAttribute(\"height\",\"250px\");\ncanv.setAttribute(\"width\",\"500px\");\nvar ctx = canv.getContext(\"2d\");\n\nquestion.signals.on('HTMLAttached',function(e) {\n \n // Create a Knockout.js observable\n ko.computed(function(){\n // Get the student's input string from part 0.\n var studentString = question.parts[0].display.studentAnswer();\n ctx.clearRect(0, 0, canv.width, canv.height);\n drawKmap(ctx,studentString,['a','b','c','d'])\n });\n});\n \nreturn canv;", "type": "html", "parameters": []}}, "statement": "

A Boolean function is described by the following Karnaugh map:-

\n

{drawKmapcanvas(truthtablesum,labels)}

\n

", "parts": [{"prompt": "

Enter a Boolean expression for the function shown on the above Karnaugh map, without the use of brackets.

\n

Enter Boolean operators using the words \"and\", \"or\" and \"not\" (without the quotation marks, and remembering to use spaces to separate them). They will be displayed in mathematical notation.

\n

For example, to enter \"$a.\\bar{b}+c$\" then type \"a and not b or c\", this will display as \"$a \\land \\lnot b \\lor c$\"

", "showCorrectAnswer": false, "answer": "evalpterm({c1},a,b,c,d) or evalpterm({c2},a,b,c,d) or evalpterm({c3},a,b,c,d) or evalpterm({c4},a,b,c,d)", "type": "jme", "notallowed": {"strings": ["(", ")"], "showStrings": true, "message": "

Brackets may not be used

", "partialCredit": 0}, "variableReplacements": [], "vsetrangepoints": 5, "checkingtype": "absdiff", "showFeedbackIcon": false, "scripts": {"validate": {"script": "// Use the jme validation code but with variable types changed to Boolean\ndebugger;\nvar validation = this.validation;\n\t\tif(this.studentAnswer.length===0)\n\t\t{\n\t\t\tthis.giveWarning(R('part.marking.not submitted'));\n\t\t\treturn false;\n\t\t}\n\t\ttry{\n\t\t\tvar scope = new jme.Scope(this.question.scope);\n\t\t\tvar tree = jme.compile(this.studentAnswer,scope);\n\t\t\tvar varnames = jme.findvars(tree);\n\t\t\tfor(i=0;i3) {\n\t\t\t\tvar suggestion = [];\n\t\t\t\tfor(var i=1;i0 && simplifiedAnswer.length0 && simplifiedAnswer.length>this.settings.maxLength);\n\t\tvalidation.failNotAllowed = false;\n\t\tvalidation.failMustHave = false;\n\t\t//did student actually write anything?\n\t\tthis.answered = this.studentAnswer.length > 0;\n\t\t\n\t\t//do comparison of student's answer with correct answer\n//\t\tif(!jme.compare(this.studentAnswer, this.settings.correctAnswer, this.settings, this.markingScope))\n\t\tif(!boolCompare(this.studentAnswer, this.settings.correctAnswer, this.settings, this.markingScope))\n\t\t{\n\t\t\tthis.setCredit(0,R('part.marking.incorrect'));\n\t\t\treturn;\n\t\t}\n\t\tvar noSpaceAnswer = this.studentAnswer.replace(/\\s/g,'').toLowerCase();\n\t\t//see if student answer contains any forbidden strings\n\t\tfor( i=0; i0 && simplifiedAnswer.length0 && simplifiedAnswer.length>this.settings.maxLength);\n\t\tvalidation.failNotAllowed = false;\n\t\tvalidation.failMustHave = false;\n\t\t//did student actually write anything?\n\t\tthis.answered = this.studentAnswer.length > 0;\n\t\t\n\t\t//do comparison of student's answer with correct answer\n//\t\tif(!jme.compare(this.studentAnswer, this.settings.correctAnswer, this.settings, this.markingScope))\n\t\tif(!boolCompare(this.studentAnswer, this.settings.correctAnswer, this.settings, this.markingScope))\n\t\t{\n\t\t\tthis.setCredit(0,R('part.marking.incorrect'));\n\t\t\treturn;\n\t\t}\n\t\tvar noSpaceAnswer = this.studentAnswer.replace(/\\s/g,'').toLowerCase();\n\t\t//see if student answer contains any forbidden strings\n\t\tfor( i=0; i3) {\n\t\t\t\tvar suggestion = [];\n\t\t\t\tfor(var i=1;iBrackets may not be used

", "strings": ["(", ")"], "partialCredit": 0}, "prompt": "

Enter a Boolean expression for all the common product terms in the above Karnaugh maps. Give the answer as a sum of products.

\n

Enter Boolean operators using the words \"and\", \"or\" and \"not\" (without the quotation marks, and remembering to use spaces to separate them). They will be displayed in mathematical notation.

\n

For example, to enter \"$a.\\bar{b}+c$\" then type \"a and not b or c\", this will display as \"$a \\land \\lnot b \\lor c$\"

", "customName": "", "checkVariableNames": false, "valuegenerators": [{"value": "", "name": "a"}, {"value": "", "name": "b"}, {"value": "", "name": "c"}, {"value": "", "name": "d"}], "showPreview": false}], "metadata": {"licence": "All rights reserved", "description": "

Development copy to test adding extra terms

"}, "functions": {"f": {"language": "jme", "parameters": [["p", "list"]], "type": "set", "definition": "// convert a cube to canonical set form using recursion\nif(abs(p)=1, //terminate on the last or only element of p\n if(p[abs(p)-1]=2, //a \"don't care\" so include both 1 and 0\n set(0,1),\n if(p[abs(p)-1]=1,\n set(1),\n set(0)\n )\n ),\n//else\n if(p[abs(p)-1]=2,\n set(map(x*2,x,f(p[0..abs(p)-1]))) or set(map(x*2+1,x,f(p[0..abs(p)-1]))),\n if(p[abs(p)-1]=1,\n set(map(x*2+1,x,f(p[0..abs(p)-1]))),\n set(map(x*2,x,f(p[0..abs(p)-1])))\n )\n )\n)"}, "usermap": {"language": "javascript", "parameters": [], "type": "html", "definition": "// draw a 4x4 Karnaugh map for a function given as a truth table\nfunction drawKmap(ctx,bits,literals)\n{\n\nctx.font = \"20px Arial\";ctx.textAlign=\"center\"; ctx.textBaseline=\"middle\";\n ctx.lineWidth=2;\n\n//ctx.fillText(n,10,50);\nctx.beginPath();\nctx.moveTo(20,20);\nctx.lineTo(60,60);\nctx.stroke();\n\nctx.fillText(literals[0]+\" \"+literals[1],15,50);\nctx.fillText(literals[2]+\" \"+literals[3],50,10);\ngraycodebin=[\"00\",\"01\",\"11\",\"10\"];\nfor (ncol=0;ncol<=3;ncol++) {\n\tctx.fillText(graycodebin[ncol],80+ncol*40,40);\n\t}\n\nfor (nrow=0;nrow<=3;nrow++) {\n\tctx.fillText(graycodebin[nrow],40,80+nrow*40);\n\tfor (ncol=0;ncol<=3;ncol++) {\n\t\tctx.rect(60+ncol*40,60+nrow*40,40,40);\n\t\tctx.stroke();\n\t\tbitval=bits[nrow][ncol].toString();\n\t\tctx.fillText(bitval,80+ncol*40,80+nrow*40);\n\t\t}\n\t}\n\n}\n\nvar canv=document.createElement(\"canvas\");\ncanv.setAttribute(\"height\",\"250px\");\ncanv.setAttribute(\"width\",\"500px\");\nvar ctx = canv.getContext(\"2d\");\n\nquestion.signals.on('HTMLAttached',function(e) {\n \n // Create a Knockout.js observable\n ko.computed(function(){\n // Get the student's input string from part 0.\n var studentString = question.parts[0].display.studentAnswer();\n ctx.clearRect(0, 0, canv.width, canv.height);\n drawKmap(ctx,studentString,['a','b','c','d'])\n });\n});\n \nreturn canv;"}, "draw2Kmapcanvas": {"language": "javascript", "parameters": [["bits", "list"], ["literals", "list"], ["bits2", "list"]], "type": "html", "definition": "// draw a 4x4 Karnaugh map for a function given as a truth table\nfunction drawKmap(ctx,bits,literals,legend)\n{\n\nctx.font = \"20px Arial\";ctx.textAlign=\"center\"; ctx.textBaseline=\"middle\";\n ctx.lineWidth=2;\n\n//ctx.fillText(n,10,50);\nctx.beginPath();\nctx.moveTo(20,20);\nctx.lineTo(60,60);\nctx.stroke();\nctx.fillText(legend,140,240);\n\nctx.fillText(literals[0]+\" \"+literals[1],15,50);\nctx.fillText(literals[2]+\" \"+literals[3],50,10);\ngraycode=[0,1,3,2];\ngraycodebin=[\"00\",\"01\",\"11\",\"10\"];\nfor (ncol=0;ncol<=3;ncol++) {\n\tctx.fillText(graycodebin[ncol],80+ncol*40,40);\n\t}\n\nfor (nrow=0;nrow<=3;nrow++) {\n\tctx.fillText(graycodebin[nrow],40,80+nrow*40);\n\tfor (ncol=0;ncol<=3;ncol++) {\n\t\tctx.rect(60+ncol*40,60+nrow*40,40,40);\n\t\tctx.stroke();\n\t\tbitval=bits[graycode[nrow]*4+graycode[ncol]].toString();\n\t\tctx.fillText(bitval,80+ncol*40,80+nrow*40);\n\t\t}\n\t}\n\n}\n\n function drawcanvas(ctx)\n {\nvar num = 15;\nvar n = num.toString();\nctx.font = \"20px Arial\";ctx.textAlign=\"center\"; ctx.textBaseline=\"middle\";\n\nctx.fillText(n,10,50);\n\n\nfor (nrow=0;nrow<=3;nrow++) {\n\tctx.fillText(\"00\",40,80+nrow*40);\n\tfor (ncol=0;ncol<=3;ncol++) {\n\t\tctx.rect(60+ncol*40,60+nrow*40,40,40);\n\t\tctx.stroke();\n\t\tbitval=bits[nrow*4+ncol].toString();\n\t\tctx.fillText(bitval,80+ncol*40,80+nrow*40);\n\t\t}\n\t}\n\nctx.rect(0,0,400,300);\nctx.stroke();\n \n \n\t}\n\n\nvar canv=document.createElement(\"canvas\");\ncanv.setAttribute(\"height\",\"250px\");\ncanv.setAttribute(\"width\",\"600px\");\nvar ctx = canv.getContext(\"2d\");\n\n//literals=[\"a\",\"b\",\"c\",\"d\"];\ndrawKmap(ctx,bits,literals,'Y1');\nctx.save();\nctx.translate(320,0);\ndrawKmap(ctx,bits2,literals,'Y0');\nctx.restore();\n//drawcanvas(ctx)\nreturn canv;"}, "test": {"language": "jme", "parameters": [["args", "list"]], "type": "number", "definition": "args[0] or args[1]"}, "evalpterm": {"language": "jme", "parameters": [["c1", "list"], ["a", "boolean"], ["b", "boolean"], ["c", "boolean"], ["d", "boolean"]], "type": "boolean", "definition": "((c1[0]=1) and a or (c1[0]=0) and not a or (c1[0]=2)) and \n((c1[1]=1) and b or (c1[1]=0) and not b or (c1[1]=2)) and \n((c1[2]=1) and c or (c1[2]=0) and not c or (c1[2]=2)) and \n((c1[3]=1) and d or (c1[3]=0) and not d or (c1[3]=2))"}, "cubedist": {"language": "jme", "parameters": [["cube1", "list"], ["cube2", "list"]], "type": "number", "definition": "// find distance between two cubes using recursion\nif(abs(cube1)=0||abs(cube2)=0,\n 0,\n if(cube1[0]=cube2[0],\n cubedist(cube1[1..abs(cube1)], cube2[1..abs(cube2)]),\n cubedist(cube1[1..abs(cube1)], cube2[1..abs(cube2)])+1\n )\n)\n"}, "cubetotext": {"language": "jme", "parameters": [["cube", "list"], ["labels", "list"]], "type": "string", "definition": "// convert a cube to a formatted text string using recursion \n// fixed for bounding box problem 24-04-18\nif(abs(cube)=0,\n [],\n switch(cube[0]=0,\n [\"$\\\\bbox[2pt]{\\\\bar{\"+labels[0]+\"}}$\"],\n cube[0]=1,\n [\"$\"+labels[0]+\"$\"],[]) + cubetotext(cube[1..abs(cube)],labels[1..abs(labels)]\n )\n)\n"}, "mat2cube": {"language": "jme", "parameters": [["m", "matrix"]], "type": "list", "definition": "if(abs(list(m))=0,\n [],\n [m[0]*2]+mat2cube(m[1..abs(list(m))])\n )"}}, "preamble": {"css": "", "js": ""}, "variablesTest": {"condition": "abs(list(f(c1)-union(union(f(c2),f(c3)),f(c4))))>0 and //no redundant or duplicate terms\nabs(list(f(c2)-union(union(f(c1),f(c3)),f(c4))))>0 and \nabs(list(f(c3)-union(union(f(c2),f(c1)),f(c4))))>0 and \nabs(list(f(c4)-union(union(f(c2),f(c3)),f(c1))))>0 and \nabs(list((f(c1)-union(f(c3),f(c4))) and (f(c2)-union(f(c3),f(c4)))))=0 //no common terms except c3+c4\nand cubedist(c4,c3)>1 //common terms are prime", "maxRuns": 100}, "rulesets": {}, "tags": [], "statement": "

A three-output logic circuit is described by the following Karnaugh maps:-

\n

{draw2Kmapcanvas(truthtablesum,labels,truthtablesum2)}

\n

", "variables": {"c1": {"description": "", "definition": "shuffle([random(0..1),random(0..1),random(0..2),2])", "name": "c1", "templateType": "anything", "group": "Ungrouped variables"}, "dkmap1": {"description": "

Convert a 4-variable Boolean function from canonical (minterm) set to Karnaugh map matrix

\n

map(if((4*r+c) in canonicalsum,1,0),[r,c],product([0,1,3,2],[0,1,3,2]))

", "definition": "map(if((4*r+c) in canonicalsum,1,0),[r,c],product([0,1,3,2],[0,1,3,2]))", "name": "dkmap1", "templateType": "anything", "group": "Unused variables"}, "c4": {"description": "

common term

", "definition": "shuffle([random(0..1),random(0..1),random(0..1),2])", "name": "c4", "templateType": "anything", "group": "Unused variables"}, "truthtablesum2": {"description": "", "definition": "map(if(x in canonicalsum2,1,0),x,0..15)", "name": "truthtablesum2", "templateType": "anything", "group": "Ungrouped variables"}, "canonicalsum": {"description": "", "definition": "union(union(f(c1),f(c3)),f(c4))", "name": "canonicalsum", "templateType": "anything", "group": "Ungrouped variables"}, "canonicalsum2": {"description": "", "definition": "union(union(f(c2),f(c3)),f(c4))", "name": "canonicalsum2", "templateType": "anything", "group": "Ungrouped variables"}, "dkmap": {"description": "

Convert a 4-variable Boolean function from canonical (minterm) set to Karnaugh map matrix

", "definition": "map(if(x in canonicalsum,1,0),x,matrix(repeat([0,1,3,2],4))+4*transpose(matrix(repeat([0,1,3,2],4))))", "name": "dkmap", "templateType": "anything", "group": "Unused variables"}, "c3": {"description": "

common term

", "definition": "shuffle([random(0..1),random(0..1),random(0..2),2])", "name": "c3", "templateType": "anything", "group": "Ungrouped variables"}, "c2": {"description": "", "definition": "shuffle([random(0..1),random(0..1),random(0..2),2])\n", "name": "c2", "templateType": "anything", "group": "Ungrouped variables"}, "labels": {"description": "", "definition": "[ safe(\"a\"), safe(\"b\"), safe(\"c\"), safe(\"d\") ]", "name": "labels", "templateType": "list of strings", "group": "Ungrouped variables"}, "truthtablesum": {"description": "", "definition": "map(if(x in canonicalsum,1,0),x,0..15)", "name": "truthtablesum", "templateType": "anything", "group": "Ungrouped variables"}}, "advice": "

The functions are

\n

$Y1$={join([join(cubetotext(c1,labels),'.'),join(cubetotext(c3,labels),'.'),join(cubetotext(c4,labels),'.')],'+')} 

\n

$Y0$={join([join(cubetotext(c2,labels),'.'),join(cubetotext(c3,labels),'.'),join(cubetotext(c4,labels),'.')],'+')}

\n

The common terms are {join([join(cubetotext(c3,labels),'.'),join(cubetotext(c4,labels),'.')],'+')}

", "ungrouped_variables": ["canonicalsum", "canonicalsum2", "c1", "c2", "c3", "labels", "truthtablesum", "truthtablesum2"]}, {"name": "PLA minimisation 2017", "extensions": [], "custom_part_types": [], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "contributors": [{"name": "Graeme Chester", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/189/"}, {"name": "Fei Xia", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/2603/"}], "statement": "

A programmable logic array has to implement the following functions y0, y1 and y2:-

\n

y0 = {cset2textshuffled((y0),labels)}

\n

y1 = {cset2textshuffled((y1),labels)}

\n

y2 = {cset2textshuffled((y2),labels)}

\n

Complete the table below with 0 or 1 in each box to program the corresponding AND-plane and OR-plane links in the PLA.(Hint: minimisation must be performed before entering the values).

\n
\n

y0={join(cubetotext(c0,labels),'.')+'+'+join(cubetotext(cboth,labels),'.')}  {y0}

\n

y1={join(cubetotext(c1,labels),'.')+'+'+join(cubetotext(cboth2,labels),'.')}  {y1}

\n

y2={join(cubetotext(cboth,labels),'.')+'+'+join(cubetotext(cboth2,labels),'.')}  {y2}

\n
", "functions": {"mat2cube": {"parameters": [["m", "matrix"]], "language": "jme", "type": "list", "definition": "if(abs(list(m))=0,\n [],\n [m[0]*2]+mat2cube(m[1..abs(list(m))])\n )"}, "reduce": {"parameters": [["lst", "list"]], "language": "javascript", "type": "list", "definition": "return lst.reduce(function(total,currentValue){return total.concat(currentValue);},[]);"}, "dec2bin": {"parameters": [["n", "number"], ["bitlen", "number"]], "language": "jme", "type": "list", "definition": "if(n>0||bitlen>0,\n dec2bin(trunc(n/2),bitlen-1)+mod(n,2) ,\n []\n )\n "}, "cset2text": {"parameters": [["cset", "set"], ["labels", "list"]], "language": "jme", "type": "string", "definition": "cubelist2text(map(dec2bin(x,len(labels)),x,cset),labels)"}, "cubetotext": {"parameters": [["cube", "list"], ["labels", "list"]], "language": "jme", "type": "string", "definition": "// convert a cube to a formatted text string using recursion \n// fixed for bounding box problem 24-04-18\nif(abs(cube)=0,\n [],\n switch(cube[0]=0,\n [\"$\\\\bbox[2pt]{\\\\bar{\"+labels[0]+\"}}$\"],\n cube[0]=1,\n [\"$\"+labels[0]+\"$\"],[]) + cubetotext(cube[1..abs(cube)],labels[1..abs(labels)]\n )\n)\n"}, "cset2textshuffled": {"parameters": [["cset", "set"], ["labels", "list"]], "language": "jme", "type": "string", "definition": "cubelist2text(shuffle(map(dec2bin(x,len(labels)),x,cset)),labels)"}, "f": {"parameters": [["p", "list"]], "language": "jme", "type": "set", "definition": "// convert a cube to canonical set form using recursion\nif(abs(p)=1, //terminate on the last or only element of p\n if(p[abs(p)-1]=2, //a \"don't care\" so include both 1 and 0\n set(0,1),\n if(p[abs(p)-1]=1,\n set(1),\n set(0)\n )\n ),\n//else\n if(p[abs(p)-1]=2,\n set(map(x*2,x,f(p[0..abs(p)-1]))) or set(map(x*2+1,x,f(p[0..abs(p)-1]))),\n if(p[abs(p)-1]=1,\n set(map(x*2+1,x,f(p[0..abs(p)-1]))),\n set(map(x*2,x,f(p[0..abs(p)-1])))\n )\n )\n)"}, "cubedist": {"parameters": [["cube1", "list"], ["cube2", "list"]], "language": "jme", "type": "number", "definition": "// find distance between two cubes using recursion\nif(abs(cube1)=0||abs(cube2)=0,\n 0,\n if(cube1[0]=cube2[0],\n cubedist(cube1[1..abs(cube1)], cube2[1..abs(cube2)]),\n cubedist(cube1[1..abs(cube1)], cube2[1..abs(cube2)])+1\n )\n)\n"}, "userpla1": {"parameters": [["inlabels", "list"], ["outlabels", "list"], ["pterms", "number"]], "language": "javascript", "type": "html", "definition": "function PLA(andplanearray, orplanearray, innames, outnames) {\n\t//need to add some error checking for row/columnn counts etc.\n\t// andplanearray=array(npterms,innames*2)\n\t// orplanearray=array(npterms,outnames)\n\tthis.andplane = andplanearray;\n\tthis.orplane = orplanearray;\n\tthis.inlabels = innames;\n\tthis.outlabels = outnames;\n\n\tthis.npterms = function() {\n\t\treturn this.andplane.length;\n\t};\n\n\tthis.ninputs = function() {\n\t\treturn this.inlabels.length;\n\t};\n\tthis.noutputs = function() {\n\t\treturn this.outlabels.length;\n\t};\n}\n\nfunction drawArrow(context, x, y, size) {\n//Draw arrow head with tip at x,y and orientation along positive x-axis\n\tcontext.beginPath();\n context.moveTo(x, y);\n\tcontext.lineTo(x - size, y - size / 2);\n\tcontext.lineTo(x - size, y + size / 2);\n\tcontext.lineTo(x, y);\n\tcontext.fill();\n\t}\n\ndebugger;\nandplane = [[1, 0, 1, 1,0,1], [1, 1, 1, 0,0,0], [0, 1, 0, 1,0,1]];\norplane = [[1, 0], [0, 1], [1, 1]];\n//inlabels = [\"a\", \"b\",\"c\"];\n//outlabels = [\"y0\", \"y1\"];\n//pterms=3; maybe use to size the canvas, answer array length used otherwise\nvar myPLA = new PLA(andplane, orplane, inlabels, outlabels);\n\nconsole.log(myPLA);\n\nvar pitch = 40;\n\nvar canv=document.createElement(\"canvas\");\nvar canvH = pitch*pterms + 180;\nvar canvW = pitch*(2*inlabels.length+outlabels.length) + 180;\ncanv.setAttribute(\"height\",canvH+\"px\");\ncanv.setAttribute(\"width\",canvW+\"px\");\nvar ctx = canv.getContext(\"2d\");\n\nquestion.signals.on('HTMLAttached',function(e) {\n\n// Create a Knockout.js observable\nko.computed(function(){\n// Get the student's input string from part 0.\nvar studentPLA = question.parts[0].display.studentAnswer();\nvar studentPLAInputs = inlabels.length; \nvar studentPLAOutputs = outlabels.length; \n \nvar studentandp = studentPLA.map(function(value,index) { return value.slice(0,studentPLAInputs*2); });\nvar studentorp = studentPLA.map(function(value,index) { return value.slice(studentPLAInputs*2,studentPLAInputs*2+studentPLAOutputs); });\nvar myPLA = new PLA(studentandp, studentorp, inlabels, outlabels);\nctx.clearRect(0, 0, canv.width, canv.height);\ndrawPLA(ctx, myPLA, pitch);\n});\n});\n\t\t \nreturn canv;\n\n\n\n\t\t\t\t\tfunction drawArrow(context, x, y, size,rotation) {\n\t\t\t\t\t\t//Draw arrow head with tip at x,y and orientation along positive x-axis\n\t\t\t\t\t\tcontext.save();\n\t\t\t\t\t\tcontext.lineWidth=3;\n\t\t\t\t\t\tcontext.translate(x, y);\n\t\t\t\t\t\tcontext.rotate(rotation);\n\t\t\t\t\t\tcontext.beginPath();\n\t\t\t\t\t\tcontext.moveTo(0, 0);\n\t\t\t\t\t\tcontext.lineTo( - size, - size / 2);\n\t\t\t\t\t\tcontext.lineTo( - size, size / 2);\n\t\t\t\t\t\tcontext.lineTo(0, 0);\n\t\t\t\t\t\tcontext.fill();\n\t\t\t\t\t\tcontext.restore();\n\t\t\t\t\t}\n\n\n\t\t\t\t\tfunction drawPLA(ctx, thePLA, pitch) {\n\t\t\t\t\t\tctx.lineWidth = 2;\n\t\t\t\t\t\tctx.font = (pitch / 2).toString() + \"px Arial\";\n\t\t\t\t\t\t//\t\t\t\t\t\tconsole.log((pitch / 2).toString());\n\t\t\t\t\t\tctx.textAlign = \"center\";\n\t\t\t\t\t\tctx.textBaseline = \"middle\";\n\t\t\t\t\t\tninputs = thePLA.ninputs();\n\t\t\t\t\t\tnoutputs = thePLA.noutputs();\n\t\t\t\t\t\tnpterms = thePLA.npterms();\n\t\t\t\t\t\t\n\t\t\t\t\t\t//i/o wires and labels\n\t\t\t\t\t\tfor (var ncol = 0; ncol < 2 * ninputs; ncol++) {\n\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\t\tctx.moveTo((ncol + 2) * pitch, (npterms + 1.5) * pitch);\n\t\t\t\t\t\t\tctx.lineTo((ncol + 2) * pitch, (npterms + 2 ) * pitch);\n\t\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t\t\tdrawArrow(ctx, (ncol + 2) * pitch, (npterms + 1.5) * pitch, pitch / 4, -Math.PI / 2);\n\n\t\t\t\t\t\t\tif (ncol % 2 == 0) {\n\t\t\t\t\t\t\t\tctx.fillText(thePLA.inlabels[ncol / 2], pitch * (ncol + 2), (npterms + 2.5) * pitch);\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tctx.fillText(thePLA.inlabels[(ncol - 1) / 2] + \"'\", pitch * (ncol + 2), (npterms + 2.5) * pitch);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tfor (var ncol = 0; ncol < noutputs; ncol++) {\n\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\t\tctx.moveTo(ncol * pitch + (2 * ninputs + 3.5) * pitch, (npterms + 1.5) * pitch);\n\t\t\t\t\t\t\tctx.lineTo(ncol * pitch + (2 * ninputs + 3.5) * pitch, (npterms + 2) * pitch);\n\t\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t\t\tctx.fillText(thePLA.outlabels[ncol], pitch * ncol + (2 * ninputs + 3.5) * pitch, (npterms + 2.5) * pitch);\n\t\t\t\t\t\t\tdrawArrow(ctx, ncol * pitch + (2 * ninputs + 3.5) * pitch, (npterms + 2) * pitch, pitch / 4, Math.PI / 2);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// AND plane cells\n\t\t\t\t\t\tfor (var nrow = 0; nrow < npterms; nrow++) {\n\n\t\t\t\t\t\t\tfor (var ncol = 0; ncol < 2 * ninputs; ncol++) {\n\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\t\t\tctx.rect((1.5 + ncol) * pitch, (1.5 + nrow) * pitch, pitch, pitch);\n\t\t\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t\t\t\tctx.fillText(thePLA.andplane[nrow][ncol].toString(), (2 + ncol) * pitch, (2 + nrow) * pitch);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t// product term links\n\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\t\tctx.moveTo((2 * ninputs + 1.5) * pitch, (nrow + 2) * pitch);\n\t\t\t\t\t\t\tctx.lineTo((2 * ninputs + 3) * pitch, (nrow + 2) * pitch);\n\t\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t\t\tdrawArrow(ctx, (2 * ninputs + 3) * pitch, (nrow + 2) * pitch, pitch / 4, 0);\n\n\t\t\t\t\t\t\t// OR plane cells\n\t\t\t\t\t\t\tfor (var ncol = 0; ncol < noutputs; ncol++) {\n\t\t\t\t\t\t\tctx.beginPath();\n\t\t\t\t\t\t\t\tctx.rect((3 + 2 * ninputs + ncol) * pitch, (1.5 + nrow) * pitch, pitch, pitch);\n\t\t\t\t\t\t\t\tctx.stroke();\n\t\t\t\t\t\t\t\tctx.fillText(thePLA.orplane[nrow][ncol].toString(), (3.5 + 2 * ninputs + ncol) * pitch, (2 + nrow) * pitch);\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t}\n\n\t\t\t\t\t}\n"}, "cubelist2text": {"parameters": [["cubelist", "list"], ["labels", "list"]], "language": "jme", "type": "string", "definition": "join(map(join(cubetotext(x,labels),'.'),x,cubelist),'+')"}}, "metadata": {"description": "

Development versin for increasing size of PLA

", "licence": "All rights reserved"}, "advice": "

The common terms {join(cubetotext(cboth,labels),'.')} and {join(cubetotext(cboth2,labels),'.')} can be used to reduce the functions:-

\n

y0={join(cubetotext(c0,labels),'.')+'+'+join(cubetotext(cboth,labels),'.')}

\n

y1={join(cubetotext(c1,labels),'.')+'+'+join(cubetotext(cboth2,labels),'.')}

\n

y2={join(cubetotext(cboth,labels),'.')+'+'+join(cubetotext(cboth2,labels),'.')}

", "tags": [], "parts": [{"extendBaseMarkingAlgorithm": true, "allowFractions": false, "numColumns": "length(labels)*2+length(outlabels)", "marks": "9", "type": "matrix", "showFeedbackIcon": true, "prompt": "

{userpla1(labels,outlabels,terms)}

\n

Programming table (note that the columns are in the order: AND plane, OR plane) 

", "correctAnswerFractions": false, "variableReplacements": [], "correctAnswer": "ans", "showCorrectAnswer": true, "markPerCell": false, "scripts": {"validate": {"order": "instead", "script": "debugger;\n// Use the built-in validation function to catch syntax errors and so on\nif(!Numbas.parts.MatrixEntryPart.prototype.validate.apply(this)) {\n return false;\n}\nreturn true;"}, "mark": {"order": "instead", "script": "\t\t\t\t\tfunction PLA(andplanearray, orplanearray, innames, outnames) {\n\t\t\t\t\t\t//need to add some error checking for row/columnn counts etc.\n\t\t\t\t\t\t// andplanearray=array(npterms,innames*2)\n\t\t\t\t\t\t// orplanearray=array(npterms,outnames)\n\t\t\t\t\t\tthis.andplane = andplanearray;\n\t\t\t\t\t\tthis.orplane = orplanearray;\n\t\t\t\t\t\tthis.inlabels = innames;\n\t\t\t\t\t\tthis.outlabels = outnames;\n\n\t\t\t\t\t\tthis.npterms = function() {\n\t\t\t\t\t\t\treturn this.andplane.length;\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tthis.ninputs = function() {\n\t\t\t\t\t\t\treturn this.inlabels.length;\n\t\t\t\t\t\t};\n\t\t\t\t\t\tthis.noutputs = function() {\n\t\t\t\t\t\t\treturn this.outlabels.length;\n\t\t\t\t\t\t};\n\n\t\t\t\t\t\tthis.eval = function(invalues) {\n\t\t\t\t\t\t\tvar outvalues = new Array(this.noutputs());\n for (var ind = 0; ind < outvalues.length; ind++) {\n outvalues[ind] = 0;\n }\n //not supported in some browsers outvalues.fill(0, 0, this.noutputs());\n\t\t\t\t\t\t\tfor (var nrow = 0; nrow < this.npterms(); nrow++) {\n\t\t\t\t\t\t\t\tvar ptout = 1;\n\t\t\t\t\t\t\t\tfor (var ncol = 0; ncol < this.ninputs(); ncol++) {\n\t\t\t\t\t\t\t\t\tif ((this.andplane[nrow][2 * ncol] == 1) && (invalues[ncol] == 0) || (this.andplane[nrow][2 * ncol + 1] == 1) && (invalues[ncol] == 1)) {\n\t\t\t\t\t\t\t\t\t\tptout = 0;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tfor (var ncol = 0; ncol < this.noutputs(); ncol++) {\n\t\t\t\t\t\t\t\t\tif ((this.orplane[nrow][ncol] == 1) && (ptout == 1)) {\n\t\t\t\t\t\t\t\t\t\toutvalues[ncol] = 1;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn outvalues;\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\ndebugger;\nthis.answered=true;\nvar studentPLA = this.studentAnswer;\nvar studentandp = studentPLA.map(function(value,index) { return value.slice(0,8); });\nvar studentorp = studentPLA.map(function(value,index) { return value.slice(8,11); });\nconsole.log('andplane ', studentandp);\nconsole.log('orplane ', studentorp);\nthePLA=new PLA(studentandp,studentorp,['a','b','c','d'],['y0','y1','y2']);\n\n//andplane = [[1, 0, 1, 1], [1, 1, 1, 0], [0, 1, 0, 1]];\n//orplane = [[1, 0], [0, 1], [1, 1], ];\n//inlabels = [\"a\", \"b\"];\n//outlabels = [\"y0\", \"y1\"];\n//thePLA = new PLA(andplane, orplane, inlabels, outlabels);\n\n\nvar y0set=[]; var y1set=[]; var y2set=[];\nfor (var aval=0;aval<2;aval++){\n\tfor (var bval=0;bval<2;bval++){\n \tfor (var cval=0;cval<2;cval++){\n \tfor (var dval=0;dval<2;dval++){\n \t\t var k=8*aval+4*bval+2*cval+dval;\n\t \t var y=thePLA.eval([aval,bval,cval,dval]);\n\t\t if (y[0]==1) y0set.push(new Numbas.jme.types.TNum(k));\n\t\t if (y[1]==1) y1set.push(new Numbas.jme.types.TNum(k));\n\t\t if (y[2]==1) y2set.push(new Numbas.jme.types.TNum(k));\n }\n }\n\t}\n}\n\n//console.log('y0 ', y0set);\n//console.log('y1 ', y1set);\n//get the canonical set variables y0 y1\nvar variables = this.question.scope.variables;\nvar unwrap = Numbas.jme.unwrapValue;\nvar setmath = Numbas.setmath;\n\nvar y0ans=(unwrap(variables.y0));\nvar y1ans=unwrap((variables.y1));\nvar y2ans=unwrap((variables.y2));\nconsole.log('y0 ', y0set, y0ans);\nconsole.log('y1 ', y1set, y1ans);\nconsole.log('y2 ', y0set, y0ans);\n\n//compare the answers\nif (setmath.eq(y0set,y0ans)) { this.addCredit(1.0/3,'Output y0 is correct. ');}\nelse{this.addCredit(0,'Output y0 is incorrect. ');\n};\n\nif (setmath.eq(y1set,y1ans)) { this.addCredit(1.0/3,'Output y1 is correct. ');}\nelse{this.addCredit(0,'Output y1 is incorrect. ');\n};\n\nif (setmath.eq(y2set,y2ans)) { this.addCredit(1.0/3,'Output y2 is correct. ');}\nelse{this.addCredit(0,'Output y2 is incorrect. ');\n};\n"}}, "variableReplacementStrategy": "originalfirst", "tolerance": 0, "numRows": "terms", "customMarkingAlgorithm": "", "allowResize": false, "unitTests": []}], "variable_groups": [], "preamble": {"js": "", "css": ""}, "rulesets": {}, "ungrouped_variables": ["c1", "c0", "cboth", "cboth2", "labels", "y0", "y1", "y2", "displayc", "ans", "test", "outlabels", "terms"], "variablesTest": {"condition": "//abs(list(f(c1)-f(cboth)))>0 and abs(list(f(cboth)-f(c1)))>0 and\n//abs(list(f(cboth)-f(c0)))>0 and abs(list(f(c0)-f(cboth)))>0 and\n//abs(list(f(c0)-f(c1)))>0 and abs(list(f(c1)-f(c0)))>0 and\n//cubedist(cboth,c0)>1 and cubedist(cboth,c1)>1\n\nabs(list(f(c1)-union(union(f(c0),f(cboth)),f(cboth2))))>0 and //no redundant or duplicate terms\nabs(list(f(c0)-union(union(f(c1),f(cboth)),f(cboth2))))>0 and \nabs(list(f(cboth)-union(union(f(c0),f(c1)),f(cboth2))))>0 and \nabs(list(f(cboth2)-union(union(f(c0),f(cboth)),f(c1))))>0 and \nabs(list((f(c1)-union(f(cboth),f(cboth2))) and (f(c0)-union(f(cboth),f(cboth2)))))=0 and //no common terms except cboth,cboth2\ncubedist(cboth2,cboth)>1 //common terms are prime", "maxRuns": "40"}, "variables": {"y2": {"name": "y2", "definition": "union(f(cboth),f(cboth2))", "group": "Ungrouped variables", "description": "", "templateType": "anything"}, "cboth2": {"name": "cboth2", "definition": "shuffle([random(0..1),random(0..1),random(0..1),2])", "group": "Ungrouped variables", "description": "", "templateType": "anything"}, "c1": {"name": "c1", "definition": "shuffle([random(0..1),random(0..1),random(0..1),random(0..2)])", "group": "Ungrouped variables", "description": "", "templateType": "anything"}, "outlabels": {"name": "outlabels", "definition": "[ safe(\"y0\"), safe(\"y1\"), safe(\"y2\") ]", "group": "Ungrouped variables", "description": "", "templateType": "list of strings"}, "terms": {"name": "terms", "definition": "4", "group": "Ungrouped variables", "description": "", "templateType": "number"}, "test": {"name": "test", "definition": "matrix(reduce([[1,2],[2,3]]))", "group": "Ungrouped variables", "description": "", "templateType": "anything"}, "labels": {"name": "labels", "definition": "[ safe(\"a\"), safe(\"b\"), safe(\"c\"), safe(\"d\") ]", "group": "Ungrouped variables", "description": "", "templateType": "list of strings"}, "ans": {"name": "ans", "definition": "matrix(\n reduce(map(switch(x=0,[0,1],x=1,[1,0],[0,0]),x,c0) +[1,0,0] ),\n reduce(map(switch(x=0,[0,1],x=1,[1,0],[0,0]),x,c1) +[0,1,0] ),\n reduce(map(switch(x=0,[0,1],x=1,[1,0],[0,0]),x,cboth) +[1,0,1] ), \n reduce(map(switch(x=0,[0,1],x=1,[1,0],[0,0]),x,cboth2)+[0,1,1] )\n)", "group": "Ungrouped variables", "description": "

map(if(x==2,0,1),x,c0)+[0,0],c1+[0,0],cboth+[1,1])matrix(

", "templateType": "anything"}, "y0": {"name": "y0", "definition": "union(f(c0),f(cboth))\n", "group": "Ungrouped variables", "description": "", "templateType": "anything"}, "y1": {"name": "y1", "definition": "union(f(c1),f(cboth2))", "group": "Ungrouped variables", "description": "", "templateType": "anything"}, "displayc": {"name": "displayc", "definition": "matrix(c0,c1,cboth)", "group": "Ungrouped variables", "description": "

Used to display lists in editor here, not used at run time

", "templateType": "anything"}, "c0": {"name": "c0", "definition": "shuffle([random(0..1),random(0..1),random(0..1),2])", "group": "Ungrouped variables", "description": "", "templateType": "anything"}, "cboth": {"name": "cboth", "definition": "shuffle([random(0..1),random(0..1),random(0..1),2])", "group": "Ungrouped variables", "description": "", "templateType": "anything"}}, "type": "question"}]}], "percentPass": "40", "type": "exam", "contributors": [{"name": "Graeme Chester", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/189/"}, {"name": "Fei Xia", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/2603/"}], "extensions": ["booleanlogic"], "custom_part_types": [], "resources": []}