// Numbas version: finer_feedback_settings {"name": "Fill in a truth table corresponding to a circuit diagram", "extensions": ["sheets"], "custom_part_types": [{"source": {"pk": 242, "author": {"name": "Christian Lawson-Perfect", "pk": 7}, "edit_page": "/part_type/242/edit"}, "name": "Spreadsheet", "short_name": "spreadsheet", "description": "

An editable spreadsheet. Ranges of cells can be disabled, and you can specify ranges of cells to be marked. A cell is marked correct if its value is equal to the value in the expected answer spreadsheet.

", "help_url": "", "input_widget": "spread-sheet", "input_options": {"correctAnswer": "settings[\"correct_answer\"]", "hint": {"static": true, "value": ""}, "initial_sheet": {"static": false, "value": "disable_cells(settings[\"initial_sheet\"], settings[\"disable_ranges\"])"}}, "can_be_gap": true, "can_be_step": true, "marking_script": "mark:\nif(sum(mark_ranges)=0,\n incorrect(),\n apply(mark_ranges)\n)\n\ninterpreted_answer:\nstudentAnswer\n\nrange_cells:\nmap(parse_range(ref),ref,values(settings[\"mark_ranges\"]))\n\ntotal_cells:\nlen(flatten(range_cells))\n\nrange_weights:\nswitch(\n settings[\"marking_method\"]=\"per_cell\",\n map(len(r)/total_cells, r, range_cells),\n // otherwise, mark per range\n repeat(1/len(range_cells), len(range_cells))\n)\n\nmark_ranges:\nmap(\n let(\n range_credit,\n sum(map(\n let(\n correctCellString, correctAnswer[c],\n correctCellNumber, parsenumber(correctCellString, notation_styles),\n studentCellString, studentAnswer[c],\n studentCellNumber, parsenumber(studentCellString, notation_styles),\n award(\n 1/len(cells), \n switch(\n correctCellString=\"\",\n isnan(studentCellNumber) or studentCellString=\"\",\n isnan(correctCellNumber),\n lower(correctCellString) = lower(studentCellString)\n ,\n abs(studentCellNumber - if(isnan(correctCellNumber),0,correctCellNumber)) <= settings[\"tolerance\"]\n )\n )\n ),\n c,\n cells\n )),\n message,\n switch(\n range_credit=0,\n if(len(cells)=1, \"This entry is incorrect.\", \"All entries in this range are incorrect.\"),\n range_credit=1,\n if(len(cells)=1, \"This entry is correct.\", \"All entries in this range are correct.\"),\n //otherwise\n \"Some entries in this range are correct.\"\n ),\n assert(len(cells)=0, add_credit(range_credit*w, \"{name}: \"+message)); \n range_credit\n ),\n [cells,w,name],\n zip(range_cells, range_weights, keys(settings[\"mark_ranges\"]))\n)\n\nnotation_styles:\n[\"plain\",\"si-en\"]\n\ncorrectAnswer:\nsettings[\"correct_answer\"]", "marking_notes": [{"name": "mark", "description": "This is the main marking note. It should award credit and provide feedback based on the student's answer.", "definition": "if(sum(mark_ranges)=0,\n incorrect(),\n apply(mark_ranges)\n)"}, {"name": "interpreted_answer", "description": "A value representing the student's answer to this part.", "definition": "studentAnswer"}, {"name": "range_cells", "description": "

For each range to be marked, the addresses of the cells in that range.

", "definition": "map(parse_range(ref),ref,values(settings[\"mark_ranges\"]))"}, {"name": "total_cells", "description": "

The total number of cells to be marked. Cells in overlapping ranges will be counted once for each range they're in.

", "definition": "len(flatten(range_cells))"}, {"name": "range_weights", "description": "

The weight of each range, as a proportion of the available credit.

", "definition": "switch(\n settings[\"marking_method\"]=\"per_cell\",\n map(len(r)/total_cells, r, range_cells),\n // otherwise, mark per range\n repeat(1/len(range_cells), len(range_cells))\n)"}, {"name": "mark_ranges", "description": "

Mark each of the ranges specified by the question author.

", "definition": "map(\n let(\n range_credit,\n sum(map(\n let(\n correctCellString, correctAnswer[c],\n correctCellNumber, parsenumber(correctCellString, notation_styles),\n studentCellString, studentAnswer[c],\n studentCellNumber, parsenumber(studentCellString, notation_styles),\n award(\n 1/len(cells), \n switch(\n correctCellString=\"\",\n isnan(studentCellNumber) or studentCellString=\"\",\n isnan(correctCellNumber),\n lower(correctCellString) = lower(studentCellString)\n ,\n abs(studentCellNumber - if(isnan(correctCellNumber),0,correctCellNumber)) <= settings[\"tolerance\"]\n )\n )\n ),\n c,\n cells\n )),\n message,\n switch(\n range_credit=0,\n if(len(cells)=1, \"This entry is incorrect.\", \"All entries in this range are incorrect.\"),\n range_credit=1,\n if(len(cells)=1, \"This entry is correct.\", \"All entries in this range are correct.\"),\n //otherwise\n \"Some entries in this range are correct.\"\n ),\n assert(len(cells)=0, add_credit(range_credit*w, \"{name}: \"+message)); \n range_credit\n ),\n [cells,w,name],\n zip(range_cells, range_weights, keys(settings[\"mark_ranges\"]))\n)"}, {"name": "notation_styles", "description": "

Accepted number notation styles for a value in an individual cell.

", "definition": "[\"plain\",\"si-en\"]"}, {"name": "correctAnswer", "description": "", "definition": "settings[\"correct_answer\"]"}], "settings": [{"name": "initial_sheet", "label": "Initial sheet", "help_url": "", "hint": "A spreadsheet object giving the initial state of the sheet that the student should fill in.", "input_type": "code", "default_value": "", "evaluate": true}, {"name": "correct_answer", "label": "Correct answer", "help_url": "", "hint": "A spreadsheet object representing a correct answer to the part.", "input_type": "code", "default_value": "", "evaluate": true}, {"name": "disable_ranges", "label": "Ranges to disable", "help_url": "", "hint": "A list of cell or range references, denoting the cells that should not be editable.", "input_type": "code", "default_value": "[]", "evaluate": true}, {"name": "mark_ranges", "label": "Ranges to mark", "help_url": "", "hint": "A dictionary of cell or range references, mapping names to ranges of cells, denoting the cells that should be compared for equality with the expected answer.", "input_type": "code", "default_value": "dict()", "evaluate": true}, {"name": "marking_method", "label": "Marking method", "help_url": "", "hint": "", "input_type": "dropdown", "default_value": "per_cell", "choices": [{"value": "per_cell", "label": "Each cell has the same weight"}, {"value": "per_range", "label": "Each range has the same weight"}]}, {"name": "tolerance", "label": "Allowed margin of error", "help_url": "", "hint": "", "input_type": "code", "default_value": "0", "evaluate": true}], "public_availability": "always", "published": true, "extensions": ["sheets"]}], "resources": [], "navigation": {"allowregen": true, "showfrontpage": false, "preventleave": false, "typeendtoleave": false}, "question_groups": [{"pickingStrategy": "all-ordered", "questions": [{"name": "Fill in a truth table corresponding to a circuit diagram", "tags": [], "metadata": {"description": "

The student is shown a circuit diagram with three logic gates. It's always in the form (a OP b) OP (b OP c).

\n

They have to fill in a truth table for the circuit. There is a step which expands the truth table, adding a column for each of the first two gates.

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

The function $f(a,b,c)$ is defined by the following circuit diagram:

\n

{diagram}

", "advice": "

The diagram corresponds to the expression $f(a,b,c) = (a \\operatorname{\\var{upper(a)}} b) \\operatorname{\\var{upper(c)}} (b \\operatorname{\\var{upper(b)}} c)$.

\n

Here are the truth tables for those logical operations:

\n

{tt_a}

\n

{tt_b}

\n

{tt_c}

\n

It can help to write out a truth table with a column for each step in the circuit:

\n

{expanded_filled_truth_table}

", "rulesets": {}, "extensions": ["sheets"], "builtin_constants": {"e": true, "pi,\u03c0": true, "i": true, "j": false}, "constants": [], "variables": {"truth_table": {"name": "truth_table", "group": "Ungrouped variables", "definition": "spreadsheet([[\"$a$\", \"$b$\", \"$c$\", \"$f(a,b,c)$\"]])\n |> fill_range(\"A2:C9\", product(bool_symbols,3))\n |> update_range(\"A1:D1\", font_style(\"bold\") |> border(\"bottom\", \"thin\"))", "description": "", "templateType": "anything", "can_override": false}, "values": {"name": "values", "group": "Values", "definition": "product([false,true],3)", "description": "

The possible combinations of values of A and B.

", "templateType": "anything", "can_override": false}, "filled_table": {"name": "filled_table", "group": "Ungrouped variables", "definition": "truth_table\n |> fill_range(\"D2:D9\", map(map(bool_symbols[award(1,x)],x,row),row,transpose([evals[2]])))", "description": "", "templateType": "anything", "can_override": false}, "fn": {"name": "fn", "group": "Expressions", "definition": "exec(\n op(c),\n [fn_a\n ,fn_b\n ]\n)", "description": "", "templateType": "anything", "can_override": false}, "evals": {"name": "evals", "group": "Values", "definition": "(eval(expr,[\"a\":a,\"b\":b,\"c\":c]) for: [a,b,c] of: values) for: expr of: [fn_a, fn_b, fn]", "description": "", "templateType": "anything", "can_override": false}, "fn_a": {"name": "fn_a", "group": "Expressions", "definition": "exec(op(a),[name(\"a\"),name(\"b\")])", "description": "", "templateType": "anything", "can_override": false}, "fn_b": {"name": "fn_b", "group": "Expressions", "definition": "exec(op(b),[name(\"b\"),name(\"c\")])", "description": "", "templateType": "anything", "can_override": false}, "a,b,c": {"name": "a,b,c", "group": "Randomisation", "definition": "shuffle(ops)", "description": "

The operations used in the function.

", "templateType": "anything", "can_override": false}, "bool_symbols": {"name": "bool_symbols", "group": "Symbols", "definition": "[\"0\",\"1\"]", "description": "", "templateType": "anything", "can_override": true}, "expanded_truth_table": {"name": "expanded_truth_table", "group": "Ungrouped variables", "definition": "spreadsheet([[\"$a$\", \"$b$\", \"$c$\", label_a, label_b, label_fn]])\n|> fill_range(\"A2:C9\", product(bool_symbols,3))\n|> update_range(\"A1:F1\", font_style(\"bold\") |> border(\"bottom\", \"thin\"))", "description": "", "templateType": "anything", "can_override": false}, "label_a": {"name": "label_a", "group": "Ungrouped variables", "definition": "\"$a$ {upper(a)} $b$\"", "description": "", "templateType": "anything", "can_override": false}, "label_b": {"name": "label_b", "group": "Ungrouped variables", "definition": "\"$b$ {upper(b)} $c$\"", "description": "", "templateType": "anything", "can_override": false}, "label_fn": {"name": "label_fn", "group": "Ungrouped variables", "definition": "\"($a$ {upper(a)} $b$) {upper(c)} ($b$ {upper(b)} $c$)\"", "description": "", "templateType": "anything", "can_override": false}, "expanded_filled_truth_table": {"name": "expanded_filled_truth_table", "group": "Ungrouped variables", "definition": "expanded_truth_table\n|> fill_range(\"D2:F9\", map(map(bool_symbols[award(1,x)],x,row),row,transpose(evals)))\n", "description": "", "templateType": "anything", "can_override": false}, "diagram": {"name": "diagram", "group": "Ungrouped variables", "definition": "html(\"\"\"\n\n Circuit diagram with three inputs: a, b and c. a and b lead into a {a} gate. b and c lead into a {b} gate. The outputs from those gates lead into a {c} gate.\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n a\n b\n c\n f(a,b,c)\n \n\"\"\")", "description": "

The circuit diagram.

", "templateType": "anything", "can_override": false}, "ops": {"name": "ops", "group": "Symbols", "definition": "[\"AND\", \"OR\", \"XOR\", \"NOR\", \"NAND\"]", "description": "", "templateType": "anything", "can_override": true}, "tt_a,tt_b,tt_c": {"name": "tt_a,tt_b,tt_c", "group": "Ungrouped variables", "definition": "truth_table(\"x {upper(op)} y\") for: op of: [a,b,c]", "description": "", "templateType": "anything", "can_override": false}}, "variablesTest": {"condition": "", "maxRuns": 100}, "ungrouped_variables": ["label_a", "label_b", "label_fn", "truth_table", "filled_table", "expanded_truth_table", "expanded_filled_truth_table", "diagram", "tt_a,tt_b,tt_c"], "variable_groups": [{"name": "Symbols", "variables": ["ops", "bool_symbols"]}, {"name": "Randomisation", "variables": ["a,b,c"]}, {"name": "Values", "variables": ["values", "evals"]}, {"name": "Expressions", "variables": ["fn", "fn_a", "fn_b"]}], "functions": {"truth_table": {"parameters": [["expr_jme", "string"]], "type": "spreadsheet", "language": "jme", "definition": "let(\n expr, parse(expr_jme),\n variables, findvars(expr),\n n, int(len(variables)),\n values, product([false,true], n),\n \n spreadsheet([variables+[expr_jme]])\n |> update_range(encode_range(0,0,n,0), font_style(\"bold\") |> border(\"bottom\", \"thin\"))\n |> fill_range(\n encode_range(0,1,n-1,int(2^n)), \n product(bool_symbols,n)\n )\n |> fill_range(\n encode_range(n,1,n,int(2^n)),\n bool_symbols[award(1,eval(expr, dict(zip(variables,value))))] for: value of: values\n )\n |> disable_cells([encode_range(0,0,n,0), encode_range(0,0,n,int(2^n))])\n)"}}, "preamble": {"js": "", "css": ""}, "parts": [{"type": "spreadsheet", "useCustomName": false, "customName": "", "marks": "6", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "prompt": "

Fill in this truth table.

", "stepsPenalty": 0, "steps": [{"type": "spreadsheet", "useCustomName": false, "customName": "", "marks": "6", "scripts": {}, "customMarkingAlgorithm": "", "extendBaseMarkingAlgorithm": true, "unitTests": [], "showCorrectAnswer": true, "showFeedbackIcon": true, "variableReplacements": [], "variableReplacementStrategy": "originalfirst", "nextParts": [], "suggestGoingBack": false, "adaptiveMarkingPenalty": 0, "exploreObjective": null, "settings": {"initial_sheet": "expanded_truth_table", "correct_answer": "expanded_filled_truth_table", "disable_ranges": "[\"A1:F1\", \"A1:C9\"]", "mark_ranges": "dict([\n [label_a, \"D2:D9\"],\n [label_b, \"E2:E9\"],\n [label_fn, \"F2:F9\"]\n])", "marking_method": "per_cell", "tolerance": "0"}}], "settings": {"initial_sheet": "truth_table", "correct_answer": "filled_table", "disable_ranges": "[\"A1:D1\", \"A1:C9\"]", "mark_ranges": "[\"$f(a,b,c)\": \"D2:D9\"]", "marking_method": "per_cell", "tolerance": "0"}}], "partsMode": "all", "maxMarks": 0, "objectives": [], "penalties": [], "objectiveVisibility": "always", "penaltyVisibility": "always", "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}, {"name": "Christian Lawson-Perfect", "profile_url": "http://clppc:8000/accounts/profile/1/"}], "resources": []}]}], "contributors": [{"name": "Christian Lawson-Perfect", "profile_url": "https://numbas.mathcentre.ac.uk/accounts/profile/7/"}, {"name": "Christian Lawson-Perfect", "profile_url": "http://clppc:8000/accounts/profile/1/"}]}