{ "cells": [ { "attachments": {}, "cell_type": "markdown", "metadata": { "id": "7vcVhbkFS81g", "nbgrader": { "grade": false, "locked": true, "solution": false } }, "source": [ "# Exercises" ] }, { "attachments": {}, "cell_type": "markdown", "id": "b30cda82", "metadata": {}, "source": [ "::: {note}\n", "You don't need to worry about using Interactive Jupyter Notebooks for these exercises. You can simply ignore the rocket icon ({fa}`rocket`) and go ahead to answer the questions using the knowledge you've gained from the chapter. Have fun!\n", "::: " ] }, { "cell_type": "code", "execution_count": 1, "id": "2a982fe0", "metadata": { "tags": [ "remove-input" ] }, "outputs": [], "source": [ "import json\n", "from jupyterquiz import display_quiz\n", "#load all questions json file\n", "with open(\"01.json\", \"r\") as file:\n", " questions = json.load(file)\n", "\n", "questions = [[q] for q in questions]" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "id": "Pq9kETciS3VO", "nbgrader": { "grade": false, "locked": true, "solution": false } }, "source": [ "## Exercise 1.2.2\n", "\n", "What is the type of the result of the following expression $3 + 1.5 + 4?$\n", "* `str`\n", "* `int`\n", "* `float`\n" ] }, { "cell_type": "code", "execution_count": 28, "id": "96306ad3", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": "var questionsvUVYPjgjBVqj=[{\"question\": \"What is the type of the result of the following expression:
3 + 1.5 + 4?\", \"type\": \"many_choice\", \"answers\": [{\"answer\": \"str \", \"correct\": false, \"feedback\": \"I hope not.\"}, {\"answer\": \" int \", \"correct\": false, \"feedback\": \"I hope not.\"}, {\"answer\": \" float \", \"correct\": true, \"feedback\": \"Correct.\"}]}];\n // Make a random ID\nfunction makeid(length) {\n var result = [];\n var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n var charactersLength = characters.length;\n for (var i = 0; i < length; i++) {\n result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n }\n return result.join('');\n}\n\n// Choose a random subset of an array. Can also be used to shuffle the array\nfunction getRandomSubarray(arr, size) {\n var shuffled = arr.slice(0), i = arr.length, temp, index;\n while (i--) {\n index = Math.floor((i + 1) * Math.random());\n temp = shuffled[index];\n shuffled[index] = shuffled[i];\n shuffled[i] = temp;\n }\n return shuffled.slice(0, size);\n}\n\nfunction printResponses(responsesContainer) {\n var responses=JSON.parse(responsesContainer.dataset.responses);\n var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
  1. Copy the text in this cell below \"Answer String\"
  2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
  3. Select the whole \"Replace Me\" text
  4. Paste in your answer string and press shift-Enter.
  5. Save the notebook using the save icon or File->Save Notebook menu item



  6. Answer String:
    ';\n console.log(responses);\n responses.forEach((response, index) => {\n if (response) {\n console.log(index + ': ' + response);\n stringResponses+= index + ': ' + response +\"
    \";\n }\n });\n responsesContainer.innerHTML=stringResponses;\n}\nfunction check_mc() {\n var id = this.id.split('-')[0];\n //var response = this.id.split('-')[1];\n //console.log(response);\n //console.log(\"In check_mc(), id=\"+id);\n //console.log(event.srcElement.id) \n //console.log(event.srcElement.dataset.correct) \n //console.log(event.srcElement.dataset.feedback)\n\n var label = event.srcElement;\n //console.log(label, label.nodeName);\n var depth = 0;\n while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n label = label.parentElement;\n console.log(depth, label);\n depth++;\n }\n\n\n\n var answers = label.parentElement.children;\n\n //console.log(answers);\n\n\n // Split behavior based on multiple choice vs many choice:\n var fb = document.getElementById(\"fb\" + id);\n\n\n\n\n if (fb.dataset.numcorrect == 1) {\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n //console.log(responsesContainer);\n var response = label.firstChild.innerText;\n if (label.querySelector(\".QuizCode\")){\n response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n }\n console.log(response);\n //console.log(document.getElementById(\"quizWrap\"+id));\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n console.log(responses);\n responses[qnum]= response;\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End code to preserve responses\n \n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n //console.log(child);\n child.className = \"MCButton\";\n }\n\n\n\n if (label.dataset.correct == \"true\") {\n // console.log(\"Correct action\");\n if (\"feedback\" in label.dataset) {\n fb.textContent = jaxify(label.dataset.feedback);\n } else {\n fb.textContent = \"Correct!\";\n }\n label.classList.add(\"correctButton\");\n\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n\n } else {\n if (\"feedback\" in label.dataset) {\n fb.textContent = jaxify(label.dataset.feedback);\n } else {\n fb.textContent = \"Incorrect -- try again.\";\n }\n //console.log(\"Error action\");\n label.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n }\n else {\n var reset = false;\n var feedback;\n if (label.dataset.correct == \"true\") {\n if (\"feedback\" in label.dataset) {\n feedback = jaxify(label.dataset.feedback);\n } else {\n feedback = \"Correct!\";\n }\n if (label.dataset.answered <= 0) {\n if (fb.dataset.answeredcorrect < 0) {\n fb.dataset.answeredcorrect = 1;\n reset = true;\n } else {\n fb.dataset.answeredcorrect++;\n }\n if (reset) {\n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n child.className = \"MCButton\";\n child.dataset.answered = 0;\n }\n }\n label.classList.add(\"correctButton\");\n label.dataset.answered = 1;\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n\n }\n } else {\n if (\"feedback\" in label.dataset) {\n feedback = jaxify(label.dataset.feedback);\n } else {\n feedback = \"Incorrect -- try again.\";\n }\n if (fb.dataset.answeredcorrect > 0) {\n fb.dataset.answeredcorrect = -1;\n reset = true;\n } else {\n fb.dataset.answeredcorrect--;\n }\n\n if (reset) {\n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n child.className = \"MCButton\";\n child.dataset.answered = 0;\n }\n }\n label.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n //console.log(responsesContainer);\n var response = label.firstChild.innerText;\n if (label.querySelector(\".QuizCode\")){\n response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n }\n console.log(response);\n //console.log(document.getElementById(\"quizWrap\"+id));\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n if (label.dataset.correct == \"true\") {\n if (typeof(responses[qnum]) == \"object\"){\n if (!responses[qnum].includes(response))\n responses[qnum].push(response);\n } else{\n responses[qnum]= [ response ];\n }\n } else {\n responses[qnum]= response;\n }\n console.log(responses);\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End save responses stuff\n\n\n\n var numcorrect = fb.dataset.numcorrect;\n var answeredcorrect = fb.dataset.answeredcorrect;\n if (answeredcorrect >= 0) {\n fb.textContent = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n } else {\n fb.textContent = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n }\n\n\n }\n\n if (typeof MathJax != 'undefined') {\n var version = MathJax.version;\n console.log('MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([fb]);\n }\n } else {\n console.log('MathJax not detected');\n }\n\n}\n\nfunction make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n var shuffled;\n if (shuffle_answers == \"True\") {\n //console.log(shuffle_answers+\" read as true\");\n shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n } else {\n //console.log(shuffle_answers+\" read as false\");\n shuffled = qa.answers;\n }\n\n\n var num_correct = 0;\n\n\n\n shuffled.forEach((item, index, ans_array) => {\n //console.log(answer);\n\n // Make input element\n var inp = document.createElement(\"input\");\n inp.type = \"radio\";\n inp.id = \"quizo\" + id + index;\n inp.style = \"display:none;\";\n aDiv.append(inp);\n\n //Make label for input element\n var lab = document.createElement(\"label\");\n lab.className = \"MCButton\";\n lab.id = id + '-' + index;\n lab.onclick = check_mc;\n var aSpan = document.createElement('span');\n aSpan.classsName = \"\";\n //qDiv.id=\"quizQn\"+id+index;\n if (\"answer\" in item) {\n aSpan.innerHTML = jaxify(item.answer);\n //aSpan.innerHTML=item.answer;\n }\n lab.append(aSpan);\n\n // Create div for code inside question\n var codeSpan;\n if (\"code\" in item) {\n codeSpan = document.createElement('span');\n codeSpan.id = \"code\" + id + index;\n codeSpan.className = \"QuizCode\";\n var codePre = document.createElement('pre');\n codeSpan.append(codePre);\n var codeCode = document.createElement('code');\n codePre.append(codeCode);\n codeCode.innerHTML = item.code;\n lab.append(codeSpan);\n //console.log(codeSpan);\n }\n\n //lab.textContent=item.answer;\n\n // Set the data attributes for the answer\n lab.setAttribute('data-correct', item.correct);\n if (item.correct) {\n num_correct++;\n }\n if (\"feedback\" in item) {\n lab.setAttribute('data-feedback', item.feedback);\n }\n lab.setAttribute('data-answered', 0);\n\n aDiv.append(lab);\n\n });\n\n if (num_correct > 1) {\n outerqDiv.className = \"ManyChoiceQn\";\n } else {\n outerqDiv.className = \"MultipleChoiceQn\";\n }\n\n return num_correct;\n\n}\nfunction check_numeric(ths, event) {\n\n if (event.keyCode === 13) {\n ths.blur();\n\n var id = ths.id.split('-')[0];\n\n var submission = ths.value;\n if (submission.indexOf('/') != -1) {\n var sub_parts = submission.split('/');\n //console.log(sub_parts);\n submission = sub_parts[0] / sub_parts[1];\n }\n //console.log(\"Reader entered\", submission);\n\n if (\"precision\" in ths.dataset) {\n var precision = ths.dataset.precision;\n // console.log(\"1:\", submission)\n submission = Math.round((1 * submission + Number.EPSILON) * 10 ** precision) / 10 ** precision;\n // console.log(\"Rounded to \", submission, \" precision=\", precision );\n }\n\n\n //console.log(\"In check_numeric(), id=\"+id);\n //console.log(event.srcElement.id) \n //console.log(event.srcElement.dataset.feedback)\n\n var fb = document.getElementById(\"fb\" + id);\n fb.style.display = \"none\";\n fb.textContent = \"Incorrect -- try again.\";\n\n var answers = JSON.parse(ths.dataset.answers);\n //console.log(answers);\n\n var defaultFB = \"\";\n var correct;\n var done = false;\n answers.every(answer => {\n //console.log(answer.type);\n\n correct = false;\n // if (answer.type==\"value\"){\n if ('value' in answer) {\n if (submission == answer.value) {\n fb.textContent = jaxify(answer.feedback);\n correct = answer.correct;\n //console.log(answer.correct);\n done = true;\n }\n // } else if (answer.type==\"range\") {\n } else if ('range' in answer) {\n //console.log(answer.range);\n if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n fb.textContent = jaxify(answer.feedback);\n correct = answer.correct;\n //console.log(answer.correct);\n done = true;\n }\n } else if (answer.type == \"default\") {\n defaultFB = answer.feedback;\n }\n if (done) {\n return false; // Break out of loop if this has been marked correct\n } else {\n return true; // Keep looking for case that includes this as a correct answer\n }\n });\n\n if ((!done) && (defaultFB != \"\")) {\n fb.innerHTML = jaxify(defaultFB);\n //console.log(\"Default feedback\", defaultFB);\n }\n\n fb.style.display = \"block\";\n if (correct) {\n ths.className = \"Input-text\";\n ths.classList.add(\"correctButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n } else {\n ths.className = \"Input-text\";\n ths.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n console.log(submission);\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n //console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n console.log(responses);\n if (submission == ths.value){\n responses[qnum]= submission;\n } else {\n responses[qnum]= ths.value + \"(\" + submission +\")\";\n }\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End code to preserve responses\n\n if (typeof MathJax != 'undefined') {\n var version = MathJax.version;\n console.log('MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([fb]);\n }\n } else {\n console.log('MathJax not detected');\n }\n return false;\n }\n\n}\n\nfunction isValid(el, charC) {\n //console.log(\"Input char: \", charC);\n if (charC == 46) {\n if (el.value.indexOf('.') === -1) {\n return true;\n } else if (el.value.indexOf('/') != -1) {\n var parts = el.value.split('/');\n if (parts[1].indexOf('.') === -1) {\n return true;\n }\n }\n else {\n return false;\n }\n } else if (charC == 47) {\n if (el.value.indexOf('/') === -1) {\n if ((el.value != \"\") && (el.value != \".\")) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else if (charC == 45) {\n var edex = el.value.indexOf('e');\n if (edex == -1) {\n edex = el.value.indexOf('E');\n }\n\n if (el.value == \"\") {\n return true;\n } else if (edex == (el.value.length - 1)) { // If just after e or E\n return true;\n } else {\n return false;\n }\n } else if (charC == 101) { // \"e\"\n if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n // Prev symbol must be digit or decimal point:\n if (el.value.slice(-1).search(/\\d/) >= 0) {\n return true;\n } else if (el.value.slice(-1).search(/\\./) >= 0) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else {\n if (charC > 31 && (charC < 48 || charC > 57))\n return false;\n }\n return true;\n}\n\nfunction numeric_keypress(evnt) {\n var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n\n if (charC == 13) {\n check_numeric(this, evnt);\n } else {\n return isValid(this, charC);\n }\n}\n\n\n\n\n\nfunction make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n\n\n\n //console.log(answer);\n\n\n outerqDiv.className = \"NumericQn\";\n aDiv.style.display = 'block';\n\n var lab = document.createElement(\"label\");\n lab.className = \"InpLabel\";\n lab.textContent = \"Type numeric answer here:\";\n aDiv.append(lab);\n\n var inp = document.createElement(\"input\");\n inp.type = \"text\";\n //inp.id=\"input-\"+id;\n inp.id = id + \"-0\";\n inp.className = \"Input-text\";\n inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n if (\"precision\" in qa) {\n inp.setAttribute('data-precision', qa.precision);\n }\n aDiv.append(inp);\n //console.log(inp);\n\n //inp.addEventListener(\"keypress\", check_numeric);\n //inp.addEventListener(\"keypress\", numeric_keypress);\n /*\n inp.addEventListener(\"keypress\", function(event) {\n return numeric_keypress(this, event);\n }\n );\n */\n //inp.onkeypress=\"return numeric_keypress(this, event)\";\n inp.onkeypress = numeric_keypress;\n inp.onpaste = event => false;\n\n inp.addEventListener(\"focus\", function (event) {\n this.value = \"\";\n return false;\n }\n );\n\n\n}\nfunction jaxify(string) {\n var mystring = string;\n\n var count = 0;\n var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n\n var count2 = 0;\n var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n\n //console.log(loc);\n\n while ((loc >= 0) || (loc2 >= 0)) {\n\n /* Have to replace all the double $$ first with current implementation */\n if (loc2 >= 0) {\n if (count2 % 2 == 0) {\n mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n } else {\n mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n }\n count2++;\n } else {\n if (count % 2 == 0) {\n mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n } else {\n mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n }\n count++;\n }\n loc = mystring.search(/([^\\\\]|^)(\\$)/);\n loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n }\n\n //console.log(mystring);\n return mystring;\n}\n\n\nfunction show_questions(json, mydiv) {\n console.log('show_questions');\n //var mydiv=document.getElementById(myid);\n var shuffle_questions = mydiv.dataset.shufflequestions;\n var num_questions = mydiv.dataset.numquestions;\n var shuffle_answers = mydiv.dataset.shuffleanswers;\n\n if (num_questions > json.length) {\n num_questions = json.length;\n }\n\n var questions;\n if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n //console.log(num_questions+\",\"+json.length);\n questions = getRandomSubarray(json, num_questions);\n } else {\n questions = json;\n }\n\n //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n\n // Iterate over questions\n questions.forEach((qa, index, array) => {\n //console.log(qa.question); \n\n var id = makeid(8);\n //console.log(id);\n\n\n // Create Div to contain question and answers\n var iDiv = document.createElement('div');\n //iDiv.id = 'quizWrap' + id + index;\n iDiv.id = 'quizWrap' + id;\n iDiv.className = 'Quiz';\n iDiv.setAttribute('data-qnum', index);\n mydiv.appendChild(iDiv);\n // iDiv.innerHTML=qa.question;\n\n var outerqDiv = document.createElement('div');\n outerqDiv.id = \"OuterquizQn\" + id + index;\n\n iDiv.append(outerqDiv);\n\n // Create div to contain question part\n var qDiv = document.createElement('div');\n qDiv.id = \"quizQn\" + id + index;\n //qDiv.textContent=qa.question;\n qDiv.innerHTML = jaxify(qa.question);\n\n outerqDiv.append(qDiv);\n\n // Create div for code inside question\n var codeDiv;\n if (\"code\" in qa) {\n codeDiv = document.createElement('div');\n codeDiv.id = \"code\" + id + index;\n codeDiv.className = \"QuizCode\";\n var codePre = document.createElement('pre');\n codeDiv.append(codePre);\n var codeCode = document.createElement('code');\n codePre.append(codeCode);\n codeCode.innerHTML = qa.code;\n outerqDiv.append(codeDiv);\n //console.log(codeDiv);\n }\n\n\n // Create div to contain answer part\n var aDiv = document.createElement('div');\n aDiv.id = \"quizAns\" + id + index;\n aDiv.className = 'Answer';\n iDiv.append(aDiv);\n\n //console.log(qa.type);\n\n var num_correct;\n if (qa.type == \"multiple_choice\") {\n num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n } else if (qa.type == \"many_choice\") {\n num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n } else if (qa.type == \"numeric\") {\n //console.log(\"numeric\");\n make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n }\n\n\n //Make div for feedback\n var fb = document.createElement(\"div\");\n fb.id = \"fb\" + id;\n //fb.style=\"font-size: 20px;text-align:center;\";\n fb.className = \"Feedback\";\n fb.setAttribute(\"data-answeredcorrect\", 0);\n fb.setAttribute(\"data-numcorrect\", num_correct);\n iDiv.append(fb);\n\n\n });\n var preserveResponses = mydiv.dataset.preserveresponses;\n console.log(preserveResponses);\n console.log(preserveResponses == \"true\");\n if (preserveResponses == \"true\") {\n console.log(preserveResponses);\n // Create Div to contain record of answers\n var iDiv = document.createElement('div');\n iDiv.id = 'responses' + mydiv.id;\n iDiv.className = 'JCResponses';\n // Create a place to store responses as an empty array\n iDiv.setAttribute('data-responses', '[]');\n\n // Dummy Text\n iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n //iDiv.className = 'Quiz';\n mydiv.appendChild(iDiv);\n }\n//console.log(\"At end of show_questions\");\n if (typeof MathJax != 'undefined') {\n console.log(\"MathJax version\", MathJax.version);\n var version = MathJax.version;\n setTimeout(function(){\n var version = MathJax.version;\n console.log('After sleep, MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([mydiv]);\n }\n }, 500);\nif (typeof version == 'undefined') {\n } else\n {\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([mydiv]);\n } else {\n console.log(\"MathJax not found\");\n }\n }\n }\n return false;\n}\n\n {\n show_questions(questionsvUVYPjgjBVqj, vUVYPjgjBVqj);\n }\n ", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "display_quiz(questions[0])" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "id": "cc546f8c", "nbgrader": { "grade": false, "locked": true, "solution": false } }, "source": [ "## Exercise 1.2.3\n", "\n", "What is the index of the letter 'r' of the sentence 'Hello engineer!'" ] }, { "cell_type": "code", "execution_count": 29, "id": "2528ef76", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
    " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": "var questionsjfGRfMJYVDVJ=[{\"question\": \"What is the index of the letter `r' of the sentence `Hello engineer!'?\", \"type\": \"many_choice\", \"answers\": [{\"answer\": \"0 \", \"correct\": false, \"feedback\": \"I hope not.\"}, {\"answer\": \" 13 \", \"correct\": true, \"feedback\": \"Correct.\"}, {\"answer\": \" 12 \", \"correct\": false, \"feedback\": \"I hope not.\"}]}];\n // Make a random ID\nfunction makeid(length) {\n var result = [];\n var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n var charactersLength = characters.length;\n for (var i = 0; i < length; i++) {\n result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n }\n return result.join('');\n}\n\n// Choose a random subset of an array. Can also be used to shuffle the array\nfunction getRandomSubarray(arr, size) {\n var shuffled = arr.slice(0), i = arr.length, temp, index;\n while (i--) {\n index = Math.floor((i + 1) * Math.random());\n temp = shuffled[index];\n shuffled[index] = shuffled[i];\n shuffled[i] = temp;\n }\n return shuffled.slice(0, size);\n}\n\nfunction printResponses(responsesContainer) {\n var responses=JSON.parse(responsesContainer.dataset.responses);\n var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
    1. Copy the text in this cell below \"Answer String\"
    2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
    3. Select the whole \"Replace Me\" text
    4. Paste in your answer string and press shift-Enter.
    5. Save the notebook using the save icon or File->Save Notebook menu item



    6. Answer String:
      ';\n console.log(responses);\n responses.forEach((response, index) => {\n if (response) {\n console.log(index + ': ' + response);\n stringResponses+= index + ': ' + response +\"
      \";\n }\n });\n responsesContainer.innerHTML=stringResponses;\n}\nfunction check_mc() {\n var id = this.id.split('-')[0];\n //var response = this.id.split('-')[1];\n //console.log(response);\n //console.log(\"In check_mc(), id=\"+id);\n //console.log(event.srcElement.id) \n //console.log(event.srcElement.dataset.correct) \n //console.log(event.srcElement.dataset.feedback)\n\n var label = event.srcElement;\n //console.log(label, label.nodeName);\n var depth = 0;\n while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n label = label.parentElement;\n console.log(depth, label);\n depth++;\n }\n\n\n\n var answers = label.parentElement.children;\n\n //console.log(answers);\n\n\n // Split behavior based on multiple choice vs many choice:\n var fb = document.getElementById(\"fb\" + id);\n\n\n\n\n if (fb.dataset.numcorrect == 1) {\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n //console.log(responsesContainer);\n var response = label.firstChild.innerText;\n if (label.querySelector(\".QuizCode\")){\n response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n }\n console.log(response);\n //console.log(document.getElementById(\"quizWrap\"+id));\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n console.log(responses);\n responses[qnum]= response;\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End code to preserve responses\n \n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n //console.log(child);\n child.className = \"MCButton\";\n }\n\n\n\n if (label.dataset.correct == \"true\") {\n // console.log(\"Correct action\");\n if (\"feedback\" in label.dataset) {\n fb.textContent = jaxify(label.dataset.feedback);\n } else {\n fb.textContent = \"Correct!\";\n }\n label.classList.add(\"correctButton\");\n\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n\n } else {\n if (\"feedback\" in label.dataset) {\n fb.textContent = jaxify(label.dataset.feedback);\n } else {\n fb.textContent = \"Incorrect -- try again.\";\n }\n //console.log(\"Error action\");\n label.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n }\n else {\n var reset = false;\n var feedback;\n if (label.dataset.correct == \"true\") {\n if (\"feedback\" in label.dataset) {\n feedback = jaxify(label.dataset.feedback);\n } else {\n feedback = \"Correct!\";\n }\n if (label.dataset.answered <= 0) {\n if (fb.dataset.answeredcorrect < 0) {\n fb.dataset.answeredcorrect = 1;\n reset = true;\n } else {\n fb.dataset.answeredcorrect++;\n }\n if (reset) {\n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n child.className = \"MCButton\";\n child.dataset.answered = 0;\n }\n }\n label.classList.add(\"correctButton\");\n label.dataset.answered = 1;\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n\n }\n } else {\n if (\"feedback\" in label.dataset) {\n feedback = jaxify(label.dataset.feedback);\n } else {\n feedback = \"Incorrect -- try again.\";\n }\n if (fb.dataset.answeredcorrect > 0) {\n fb.dataset.answeredcorrect = -1;\n reset = true;\n } else {\n fb.dataset.answeredcorrect--;\n }\n\n if (reset) {\n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n child.className = \"MCButton\";\n child.dataset.answered = 0;\n }\n }\n label.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n //console.log(responsesContainer);\n var response = label.firstChild.innerText;\n if (label.querySelector(\".QuizCode\")){\n response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n }\n console.log(response);\n //console.log(document.getElementById(\"quizWrap\"+id));\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n if (label.dataset.correct == \"true\") {\n if (typeof(responses[qnum]) == \"object\"){\n if (!responses[qnum].includes(response))\n responses[qnum].push(response);\n } else{\n responses[qnum]= [ response ];\n }\n } else {\n responses[qnum]= response;\n }\n console.log(responses);\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End save responses stuff\n\n\n\n var numcorrect = fb.dataset.numcorrect;\n var answeredcorrect = fb.dataset.answeredcorrect;\n if (answeredcorrect >= 0) {\n fb.textContent = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n } else {\n fb.textContent = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n }\n\n\n }\n\n if (typeof MathJax != 'undefined') {\n var version = MathJax.version;\n console.log('MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([fb]);\n }\n } else {\n console.log('MathJax not detected');\n }\n\n}\n\nfunction make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n var shuffled;\n if (shuffle_answers == \"True\") {\n //console.log(shuffle_answers+\" read as true\");\n shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n } else {\n //console.log(shuffle_answers+\" read as false\");\n shuffled = qa.answers;\n }\n\n\n var num_correct = 0;\n\n\n\n shuffled.forEach((item, index, ans_array) => {\n //console.log(answer);\n\n // Make input element\n var inp = document.createElement(\"input\");\n inp.type = \"radio\";\n inp.id = \"quizo\" + id + index;\n inp.style = \"display:none;\";\n aDiv.append(inp);\n\n //Make label for input element\n var lab = document.createElement(\"label\");\n lab.className = \"MCButton\";\n lab.id = id + '-' + index;\n lab.onclick = check_mc;\n var aSpan = document.createElement('span');\n aSpan.classsName = \"\";\n //qDiv.id=\"quizQn\"+id+index;\n if (\"answer\" in item) {\n aSpan.innerHTML = jaxify(item.answer);\n //aSpan.innerHTML=item.answer;\n }\n lab.append(aSpan);\n\n // Create div for code inside question\n var codeSpan;\n if (\"code\" in item) {\n codeSpan = document.createElement('span');\n codeSpan.id = \"code\" + id + index;\n codeSpan.className = \"QuizCode\";\n var codePre = document.createElement('pre');\n codeSpan.append(codePre);\n var codeCode = document.createElement('code');\n codePre.append(codeCode);\n codeCode.innerHTML = item.code;\n lab.append(codeSpan);\n //console.log(codeSpan);\n }\n\n //lab.textContent=item.answer;\n\n // Set the data attributes for the answer\n lab.setAttribute('data-correct', item.correct);\n if (item.correct) {\n num_correct++;\n }\n if (\"feedback\" in item) {\n lab.setAttribute('data-feedback', item.feedback);\n }\n lab.setAttribute('data-answered', 0);\n\n aDiv.append(lab);\n\n });\n\n if (num_correct > 1) {\n outerqDiv.className = \"ManyChoiceQn\";\n } else {\n outerqDiv.className = \"MultipleChoiceQn\";\n }\n\n return num_correct;\n\n}\nfunction check_numeric(ths, event) {\n\n if (event.keyCode === 13) {\n ths.blur();\n\n var id = ths.id.split('-')[0];\n\n var submission = ths.value;\n if (submission.indexOf('/') != -1) {\n var sub_parts = submission.split('/');\n //console.log(sub_parts);\n submission = sub_parts[0] / sub_parts[1];\n }\n //console.log(\"Reader entered\", submission);\n\n if (\"precision\" in ths.dataset) {\n var precision = ths.dataset.precision;\n // console.log(\"1:\", submission)\n submission = Math.round((1 * submission + Number.EPSILON) * 10 ** precision) / 10 ** precision;\n // console.log(\"Rounded to \", submission, \" precision=\", precision );\n }\n\n\n //console.log(\"In check_numeric(), id=\"+id);\n //console.log(event.srcElement.id) \n //console.log(event.srcElement.dataset.feedback)\n\n var fb = document.getElementById(\"fb\" + id);\n fb.style.display = \"none\";\n fb.textContent = \"Incorrect -- try again.\";\n\n var answers = JSON.parse(ths.dataset.answers);\n //console.log(answers);\n\n var defaultFB = \"\";\n var correct;\n var done = false;\n answers.every(answer => {\n //console.log(answer.type);\n\n correct = false;\n // if (answer.type==\"value\"){\n if ('value' in answer) {\n if (submission == answer.value) {\n fb.textContent = jaxify(answer.feedback);\n correct = answer.correct;\n //console.log(answer.correct);\n done = true;\n }\n // } else if (answer.type==\"range\") {\n } else if ('range' in answer) {\n //console.log(answer.range);\n if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n fb.textContent = jaxify(answer.feedback);\n correct = answer.correct;\n //console.log(answer.correct);\n done = true;\n }\n } else if (answer.type == \"default\") {\n defaultFB = answer.feedback;\n }\n if (done) {\n return false; // Break out of loop if this has been marked correct\n } else {\n return true; // Keep looking for case that includes this as a correct answer\n }\n });\n\n if ((!done) && (defaultFB != \"\")) {\n fb.innerHTML = jaxify(defaultFB);\n //console.log(\"Default feedback\", defaultFB);\n }\n\n fb.style.display = \"block\";\n if (correct) {\n ths.className = \"Input-text\";\n ths.classList.add(\"correctButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n } else {\n ths.className = \"Input-text\";\n ths.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n console.log(submission);\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n //console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n console.log(responses);\n if (submission == ths.value){\n responses[qnum]= submission;\n } else {\n responses[qnum]= ths.value + \"(\" + submission +\")\";\n }\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End code to preserve responses\n\n if (typeof MathJax != 'undefined') {\n var version = MathJax.version;\n console.log('MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([fb]);\n }\n } else {\n console.log('MathJax not detected');\n }\n return false;\n }\n\n}\n\nfunction isValid(el, charC) {\n //console.log(\"Input char: \", charC);\n if (charC == 46) {\n if (el.value.indexOf('.') === -1) {\n return true;\n } else if (el.value.indexOf('/') != -1) {\n var parts = el.value.split('/');\n if (parts[1].indexOf('.') === -1) {\n return true;\n }\n }\n else {\n return false;\n }\n } else if (charC == 47) {\n if (el.value.indexOf('/') === -1) {\n if ((el.value != \"\") && (el.value != \".\")) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else if (charC == 45) {\n var edex = el.value.indexOf('e');\n if (edex == -1) {\n edex = el.value.indexOf('E');\n }\n\n if (el.value == \"\") {\n return true;\n } else if (edex == (el.value.length - 1)) { // If just after e or E\n return true;\n } else {\n return false;\n }\n } else if (charC == 101) { // \"e\"\n if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n // Prev symbol must be digit or decimal point:\n if (el.value.slice(-1).search(/\\d/) >= 0) {\n return true;\n } else if (el.value.slice(-1).search(/\\./) >= 0) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else {\n if (charC > 31 && (charC < 48 || charC > 57))\n return false;\n }\n return true;\n}\n\nfunction numeric_keypress(evnt) {\n var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n\n if (charC == 13) {\n check_numeric(this, evnt);\n } else {\n return isValid(this, charC);\n }\n}\n\n\n\n\n\nfunction make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n\n\n\n //console.log(answer);\n\n\n outerqDiv.className = \"NumericQn\";\n aDiv.style.display = 'block';\n\n var lab = document.createElement(\"label\");\n lab.className = \"InpLabel\";\n lab.textContent = \"Type numeric answer here:\";\n aDiv.append(lab);\n\n var inp = document.createElement(\"input\");\n inp.type = \"text\";\n //inp.id=\"input-\"+id;\n inp.id = id + \"-0\";\n inp.className = \"Input-text\";\n inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n if (\"precision\" in qa) {\n inp.setAttribute('data-precision', qa.precision);\n }\n aDiv.append(inp);\n //console.log(inp);\n\n //inp.addEventListener(\"keypress\", check_numeric);\n //inp.addEventListener(\"keypress\", numeric_keypress);\n /*\n inp.addEventListener(\"keypress\", function(event) {\n return numeric_keypress(this, event);\n }\n );\n */\n //inp.onkeypress=\"return numeric_keypress(this, event)\";\n inp.onkeypress = numeric_keypress;\n inp.onpaste = event => false;\n\n inp.addEventListener(\"focus\", function (event) {\n this.value = \"\";\n return false;\n }\n );\n\n\n}\nfunction jaxify(string) {\n var mystring = string;\n\n var count = 0;\n var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n\n var count2 = 0;\n var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n\n //console.log(loc);\n\n while ((loc >= 0) || (loc2 >= 0)) {\n\n /* Have to replace all the double $$ first with current implementation */\n if (loc2 >= 0) {\n if (count2 % 2 == 0) {\n mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n } else {\n mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n }\n count2++;\n } else {\n if (count % 2 == 0) {\n mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n } else {\n mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n }\n count++;\n }\n loc = mystring.search(/([^\\\\]|^)(\\$)/);\n loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n }\n\n //console.log(mystring);\n return mystring;\n}\n\n\nfunction show_questions(json, mydiv) {\n console.log('show_questions');\n //var mydiv=document.getElementById(myid);\n var shuffle_questions = mydiv.dataset.shufflequestions;\n var num_questions = mydiv.dataset.numquestions;\n var shuffle_answers = mydiv.dataset.shuffleanswers;\n\n if (num_questions > json.length) {\n num_questions = json.length;\n }\n\n var questions;\n if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n //console.log(num_questions+\",\"+json.length);\n questions = getRandomSubarray(json, num_questions);\n } else {\n questions = json;\n }\n\n //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n\n // Iterate over questions\n questions.forEach((qa, index, array) => {\n //console.log(qa.question); \n\n var id = makeid(8);\n //console.log(id);\n\n\n // Create Div to contain question and answers\n var iDiv = document.createElement('div');\n //iDiv.id = 'quizWrap' + id + index;\n iDiv.id = 'quizWrap' + id;\n iDiv.className = 'Quiz';\n iDiv.setAttribute('data-qnum', index);\n mydiv.appendChild(iDiv);\n // iDiv.innerHTML=qa.question;\n\n var outerqDiv = document.createElement('div');\n outerqDiv.id = \"OuterquizQn\" + id + index;\n\n iDiv.append(outerqDiv);\n\n // Create div to contain question part\n var qDiv = document.createElement('div');\n qDiv.id = \"quizQn\" + id + index;\n //qDiv.textContent=qa.question;\n qDiv.innerHTML = jaxify(qa.question);\n\n outerqDiv.append(qDiv);\n\n // Create div for code inside question\n var codeDiv;\n if (\"code\" in qa) {\n codeDiv = document.createElement('div');\n codeDiv.id = \"code\" + id + index;\n codeDiv.className = \"QuizCode\";\n var codePre = document.createElement('pre');\n codeDiv.append(codePre);\n var codeCode = document.createElement('code');\n codePre.append(codeCode);\n codeCode.innerHTML = qa.code;\n outerqDiv.append(codeDiv);\n //console.log(codeDiv);\n }\n\n\n // Create div to contain answer part\n var aDiv = document.createElement('div');\n aDiv.id = \"quizAns\" + id + index;\n aDiv.className = 'Answer';\n iDiv.append(aDiv);\n\n //console.log(qa.type);\n\n var num_correct;\n if (qa.type == \"multiple_choice\") {\n num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n } else if (qa.type == \"many_choice\") {\n num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n } else if (qa.type == \"numeric\") {\n //console.log(\"numeric\");\n make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n }\n\n\n //Make div for feedback\n var fb = document.createElement(\"div\");\n fb.id = \"fb\" + id;\n //fb.style=\"font-size: 20px;text-align:center;\";\n fb.className = \"Feedback\";\n fb.setAttribute(\"data-answeredcorrect\", 0);\n fb.setAttribute(\"data-numcorrect\", num_correct);\n iDiv.append(fb);\n\n\n });\n var preserveResponses = mydiv.dataset.preserveresponses;\n console.log(preserveResponses);\n console.log(preserveResponses == \"true\");\n if (preserveResponses == \"true\") {\n console.log(preserveResponses);\n // Create Div to contain record of answers\n var iDiv = document.createElement('div');\n iDiv.id = 'responses' + mydiv.id;\n iDiv.className = 'JCResponses';\n // Create a place to store responses as an empty array\n iDiv.setAttribute('data-responses', '[]');\n\n // Dummy Text\n iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n //iDiv.className = 'Quiz';\n mydiv.appendChild(iDiv);\n }\n//console.log(\"At end of show_questions\");\n if (typeof MathJax != 'undefined') {\n console.log(\"MathJax version\", MathJax.version);\n var version = MathJax.version;\n setTimeout(function(){\n var version = MathJax.version;\n console.log('After sleep, MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([mydiv]);\n }\n }, 500);\nif (typeof version == 'undefined') {\n } else\n {\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([mydiv]);\n } else {\n console.log(\"MathJax not found\");\n }\n }\n }\n return false;\n}\n\n {\n show_questions(questionsjfGRfMJYVDVJ, jfGRfMJYVDVJ);\n }\n ", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "display_quiz(questions[1])" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "locked": true, "solution": false } }, "source": [ "## (Fixing) Exercise 1.2.4\n", "In the following exercise you will be using a piece of code, which was written by other people. It can contain concepts you haven't encountered yet but you need to practice with using code you don't understand completely. This is because you want to be able to use programs written by other people. Just like with calculators — if you add two numbers you get the result you expect to get. But you don't know exactly how that piece of plastics with electronic components performs that calculation.\n", "\n", "In order to approach the problem, start from the point of error. If your error cannot be solved there, work your way backwards through the code. Only try to understand the parts that are necessary to fix your problem, and avoid changing parts you know that work.\n", "\n", "There are 2 types of numbers in Python: integer numbers and floating point numbers. Both have overlapping and different applications. For example, counting rocks will require only integers (1 rock, 2 rocks, 3 rocks, etc), while their weight can be expressed in both int and float (depending on the required accuracy).\n", "\n", "In the code cell below you can see a small **dataset** of the measured daily temperatures and a **filter function**, which is used to remove incorrect measurements. A student wanted to indicate the position of the erroneous measurement, so it can be later filtered out during data analysis. However, when using the filter function, ``filter_errors``, the erroneous measurement it wasn't removed. The filter function is known to work flawlessly (no errors there), meaning that the mistake happened in the indication step. It is known that the corrupted sample is the 5th in the dataset (5th because the first element has index 0! Python has a zero-based indexing).\n", "\n", "\n" ] }, { "cell_type": "code", "execution_count": 45, "metadata": { "collapsed": true, "nbgrader": { "grade": false, "locked": true, "solution": false } }, "outputs": [], "source": [ "temperature_dataset = [12.0, 13.5, 11.0, 12.7, 670.5, 11.8] # in Celsius\n", "\n", "def filter_errors(dataset, error_id):\n", " print('Data before filtering', dataset)\n", " del dataset[error_id - 1] \n", "\n", " return print('Data after filtering', dataset)\n", "\n", "filter_errors(temperature_dataset, 5.0)" ] }, { "cell_type": "code", "execution_count": 30, "id": "aa382b90", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
      " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": "var questionsbWprKoWNYBzN=[{\"question\": \"What is the error? \", \"type\": \"many_choice\", \"answers\": [{\"answer\": \"The name of the dataset is wrong.\", \"correct\": false, \"feedback\": \"I hope not.\"}, {\"answer\": \"The error_id argument must be type integer. \", \"correct\": true, \"feedback\": \"Correct.\"}, {\"answer\": \"The function is wrong, Python has not a zero-based indexing. \", \"correct\": false, \"feedback\": \"I hope not.\"}]}];\n // Make a random ID\nfunction makeid(length) {\n var result = [];\n var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n var charactersLength = characters.length;\n for (var i = 0; i < length; i++) {\n result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n }\n return result.join('');\n}\n\n// Choose a random subset of an array. Can also be used to shuffle the array\nfunction getRandomSubarray(arr, size) {\n var shuffled = arr.slice(0), i = arr.length, temp, index;\n while (i--) {\n index = Math.floor((i + 1) * Math.random());\n temp = shuffled[index];\n shuffled[index] = shuffled[i];\n shuffled[i] = temp;\n }\n return shuffled.slice(0, size);\n}\n\nfunction printResponses(responsesContainer) {\n var responses=JSON.parse(responsesContainer.dataset.responses);\n var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
      1. Copy the text in this cell below \"Answer String\"
      2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
      3. Select the whole \"Replace Me\" text
      4. Paste in your answer string and press shift-Enter.
      5. Save the notebook using the save icon or File->Save Notebook menu item



      6. Answer String:
        ';\n console.log(responses);\n responses.forEach((response, index) => {\n if (response) {\n console.log(index + ': ' + response);\n stringResponses+= index + ': ' + response +\"
        \";\n }\n });\n responsesContainer.innerHTML=stringResponses;\n}\nfunction check_mc() {\n var id = this.id.split('-')[0];\n //var response = this.id.split('-')[1];\n //console.log(response);\n //console.log(\"In check_mc(), id=\"+id);\n //console.log(event.srcElement.id) \n //console.log(event.srcElement.dataset.correct) \n //console.log(event.srcElement.dataset.feedback)\n\n var label = event.srcElement;\n //console.log(label, label.nodeName);\n var depth = 0;\n while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n label = label.parentElement;\n console.log(depth, label);\n depth++;\n }\n\n\n\n var answers = label.parentElement.children;\n\n //console.log(answers);\n\n\n // Split behavior based on multiple choice vs many choice:\n var fb = document.getElementById(\"fb\" + id);\n\n\n\n\n if (fb.dataset.numcorrect == 1) {\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n //console.log(responsesContainer);\n var response = label.firstChild.innerText;\n if (label.querySelector(\".QuizCode\")){\n response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n }\n console.log(response);\n //console.log(document.getElementById(\"quizWrap\"+id));\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n console.log(responses);\n responses[qnum]= response;\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End code to preserve responses\n \n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n //console.log(child);\n child.className = \"MCButton\";\n }\n\n\n\n if (label.dataset.correct == \"true\") {\n // console.log(\"Correct action\");\n if (\"feedback\" in label.dataset) {\n fb.textContent = jaxify(label.dataset.feedback);\n } else {\n fb.textContent = \"Correct!\";\n }\n label.classList.add(\"correctButton\");\n\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n\n } else {\n if (\"feedback\" in label.dataset) {\n fb.textContent = jaxify(label.dataset.feedback);\n } else {\n fb.textContent = \"Incorrect -- try again.\";\n }\n //console.log(\"Error action\");\n label.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n }\n else {\n var reset = false;\n var feedback;\n if (label.dataset.correct == \"true\") {\n if (\"feedback\" in label.dataset) {\n feedback = jaxify(label.dataset.feedback);\n } else {\n feedback = \"Correct!\";\n }\n if (label.dataset.answered <= 0) {\n if (fb.dataset.answeredcorrect < 0) {\n fb.dataset.answeredcorrect = 1;\n reset = true;\n } else {\n fb.dataset.answeredcorrect++;\n }\n if (reset) {\n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n child.className = \"MCButton\";\n child.dataset.answered = 0;\n }\n }\n label.classList.add(\"correctButton\");\n label.dataset.answered = 1;\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n\n }\n } else {\n if (\"feedback\" in label.dataset) {\n feedback = jaxify(label.dataset.feedback);\n } else {\n feedback = \"Incorrect -- try again.\";\n }\n if (fb.dataset.answeredcorrect > 0) {\n fb.dataset.answeredcorrect = -1;\n reset = true;\n } else {\n fb.dataset.answeredcorrect--;\n }\n\n if (reset) {\n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n child.className = \"MCButton\";\n child.dataset.answered = 0;\n }\n }\n label.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n //console.log(responsesContainer);\n var response = label.firstChild.innerText;\n if (label.querySelector(\".QuizCode\")){\n response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n }\n console.log(response);\n //console.log(document.getElementById(\"quizWrap\"+id));\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n if (label.dataset.correct == \"true\") {\n if (typeof(responses[qnum]) == \"object\"){\n if (!responses[qnum].includes(response))\n responses[qnum].push(response);\n } else{\n responses[qnum]= [ response ];\n }\n } else {\n responses[qnum]= response;\n }\n console.log(responses);\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End save responses stuff\n\n\n\n var numcorrect = fb.dataset.numcorrect;\n var answeredcorrect = fb.dataset.answeredcorrect;\n if (answeredcorrect >= 0) {\n fb.textContent = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n } else {\n fb.textContent = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n }\n\n\n }\n\n if (typeof MathJax != 'undefined') {\n var version = MathJax.version;\n console.log('MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([fb]);\n }\n } else {\n console.log('MathJax not detected');\n }\n\n}\n\nfunction make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n var shuffled;\n if (shuffle_answers == \"True\") {\n //console.log(shuffle_answers+\" read as true\");\n shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n } else {\n //console.log(shuffle_answers+\" read as false\");\n shuffled = qa.answers;\n }\n\n\n var num_correct = 0;\n\n\n\n shuffled.forEach((item, index, ans_array) => {\n //console.log(answer);\n\n // Make input element\n var inp = document.createElement(\"input\");\n inp.type = \"radio\";\n inp.id = \"quizo\" + id + index;\n inp.style = \"display:none;\";\n aDiv.append(inp);\n\n //Make label for input element\n var lab = document.createElement(\"label\");\n lab.className = \"MCButton\";\n lab.id = id + '-' + index;\n lab.onclick = check_mc;\n var aSpan = document.createElement('span');\n aSpan.classsName = \"\";\n //qDiv.id=\"quizQn\"+id+index;\n if (\"answer\" in item) {\n aSpan.innerHTML = jaxify(item.answer);\n //aSpan.innerHTML=item.answer;\n }\n lab.append(aSpan);\n\n // Create div for code inside question\n var codeSpan;\n if (\"code\" in item) {\n codeSpan = document.createElement('span');\n codeSpan.id = \"code\" + id + index;\n codeSpan.className = \"QuizCode\";\n var codePre = document.createElement('pre');\n codeSpan.append(codePre);\n var codeCode = document.createElement('code');\n codePre.append(codeCode);\n codeCode.innerHTML = item.code;\n lab.append(codeSpan);\n //console.log(codeSpan);\n }\n\n //lab.textContent=item.answer;\n\n // Set the data attributes for the answer\n lab.setAttribute('data-correct', item.correct);\n if (item.correct) {\n num_correct++;\n }\n if (\"feedback\" in item) {\n lab.setAttribute('data-feedback', item.feedback);\n }\n lab.setAttribute('data-answered', 0);\n\n aDiv.append(lab);\n\n });\n\n if (num_correct > 1) {\n outerqDiv.className = \"ManyChoiceQn\";\n } else {\n outerqDiv.className = \"MultipleChoiceQn\";\n }\n\n return num_correct;\n\n}\nfunction check_numeric(ths, event) {\n\n if (event.keyCode === 13) {\n ths.blur();\n\n var id = ths.id.split('-')[0];\n\n var submission = ths.value;\n if (submission.indexOf('/') != -1) {\n var sub_parts = submission.split('/');\n //console.log(sub_parts);\n submission = sub_parts[0] / sub_parts[1];\n }\n //console.log(\"Reader entered\", submission);\n\n if (\"precision\" in ths.dataset) {\n var precision = ths.dataset.precision;\n // console.log(\"1:\", submission)\n submission = Math.round((1 * submission + Number.EPSILON) * 10 ** precision) / 10 ** precision;\n // console.log(\"Rounded to \", submission, \" precision=\", precision );\n }\n\n\n //console.log(\"In check_numeric(), id=\"+id);\n //console.log(event.srcElement.id) \n //console.log(event.srcElement.dataset.feedback)\n\n var fb = document.getElementById(\"fb\" + id);\n fb.style.display = \"none\";\n fb.textContent = \"Incorrect -- try again.\";\n\n var answers = JSON.parse(ths.dataset.answers);\n //console.log(answers);\n\n var defaultFB = \"\";\n var correct;\n var done = false;\n answers.every(answer => {\n //console.log(answer.type);\n\n correct = false;\n // if (answer.type==\"value\"){\n if ('value' in answer) {\n if (submission == answer.value) {\n fb.textContent = jaxify(answer.feedback);\n correct = answer.correct;\n //console.log(answer.correct);\n done = true;\n }\n // } else if (answer.type==\"range\") {\n } else if ('range' in answer) {\n //console.log(answer.range);\n if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n fb.textContent = jaxify(answer.feedback);\n correct = answer.correct;\n //console.log(answer.correct);\n done = true;\n }\n } else if (answer.type == \"default\") {\n defaultFB = answer.feedback;\n }\n if (done) {\n return false; // Break out of loop if this has been marked correct\n } else {\n return true; // Keep looking for case that includes this as a correct answer\n }\n });\n\n if ((!done) && (defaultFB != \"\")) {\n fb.innerHTML = jaxify(defaultFB);\n //console.log(\"Default feedback\", defaultFB);\n }\n\n fb.style.display = \"block\";\n if (correct) {\n ths.className = \"Input-text\";\n ths.classList.add(\"correctButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n } else {\n ths.className = \"Input-text\";\n ths.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n console.log(submission);\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n //console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n console.log(responses);\n if (submission == ths.value){\n responses[qnum]= submission;\n } else {\n responses[qnum]= ths.value + \"(\" + submission +\")\";\n }\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End code to preserve responses\n\n if (typeof MathJax != 'undefined') {\n var version = MathJax.version;\n console.log('MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([fb]);\n }\n } else {\n console.log('MathJax not detected');\n }\n return false;\n }\n\n}\n\nfunction isValid(el, charC) {\n //console.log(\"Input char: \", charC);\n if (charC == 46) {\n if (el.value.indexOf('.') === -1) {\n return true;\n } else if (el.value.indexOf('/') != -1) {\n var parts = el.value.split('/');\n if (parts[1].indexOf('.') === -1) {\n return true;\n }\n }\n else {\n return false;\n }\n } else if (charC == 47) {\n if (el.value.indexOf('/') === -1) {\n if ((el.value != \"\") && (el.value != \".\")) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else if (charC == 45) {\n var edex = el.value.indexOf('e');\n if (edex == -1) {\n edex = el.value.indexOf('E');\n }\n\n if (el.value == \"\") {\n return true;\n } else if (edex == (el.value.length - 1)) { // If just after e or E\n return true;\n } else {\n return false;\n }\n } else if (charC == 101) { // \"e\"\n if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n // Prev symbol must be digit or decimal point:\n if (el.value.slice(-1).search(/\\d/) >= 0) {\n return true;\n } else if (el.value.slice(-1).search(/\\./) >= 0) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else {\n if (charC > 31 && (charC < 48 || charC > 57))\n return false;\n }\n return true;\n}\n\nfunction numeric_keypress(evnt) {\n var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n\n if (charC == 13) {\n check_numeric(this, evnt);\n } else {\n return isValid(this, charC);\n }\n}\n\n\n\n\n\nfunction make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n\n\n\n //console.log(answer);\n\n\n outerqDiv.className = \"NumericQn\";\n aDiv.style.display = 'block';\n\n var lab = document.createElement(\"label\");\n lab.className = \"InpLabel\";\n lab.textContent = \"Type numeric answer here:\";\n aDiv.append(lab);\n\n var inp = document.createElement(\"input\");\n inp.type = \"text\";\n //inp.id=\"input-\"+id;\n inp.id = id + \"-0\";\n inp.className = \"Input-text\";\n inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n if (\"precision\" in qa) {\n inp.setAttribute('data-precision', qa.precision);\n }\n aDiv.append(inp);\n //console.log(inp);\n\n //inp.addEventListener(\"keypress\", check_numeric);\n //inp.addEventListener(\"keypress\", numeric_keypress);\n /*\n inp.addEventListener(\"keypress\", function(event) {\n return numeric_keypress(this, event);\n }\n );\n */\n //inp.onkeypress=\"return numeric_keypress(this, event)\";\n inp.onkeypress = numeric_keypress;\n inp.onpaste = event => false;\n\n inp.addEventListener(\"focus\", function (event) {\n this.value = \"\";\n return false;\n }\n );\n\n\n}\nfunction jaxify(string) {\n var mystring = string;\n\n var count = 0;\n var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n\n var count2 = 0;\n var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n\n //console.log(loc);\n\n while ((loc >= 0) || (loc2 >= 0)) {\n\n /* Have to replace all the double $$ first with current implementation */\n if (loc2 >= 0) {\n if (count2 % 2 == 0) {\n mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n } else {\n mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n }\n count2++;\n } else {\n if (count % 2 == 0) {\n mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n } else {\n mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n }\n count++;\n }\n loc = mystring.search(/([^\\\\]|^)(\\$)/);\n loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n }\n\n //console.log(mystring);\n return mystring;\n}\n\n\nfunction show_questions(json, mydiv) {\n console.log('show_questions');\n //var mydiv=document.getElementById(myid);\n var shuffle_questions = mydiv.dataset.shufflequestions;\n var num_questions = mydiv.dataset.numquestions;\n var shuffle_answers = mydiv.dataset.shuffleanswers;\n\n if (num_questions > json.length) {\n num_questions = json.length;\n }\n\n var questions;\n if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n //console.log(num_questions+\",\"+json.length);\n questions = getRandomSubarray(json, num_questions);\n } else {\n questions = json;\n }\n\n //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n\n // Iterate over questions\n questions.forEach((qa, index, array) => {\n //console.log(qa.question); \n\n var id = makeid(8);\n //console.log(id);\n\n\n // Create Div to contain question and answers\n var iDiv = document.createElement('div');\n //iDiv.id = 'quizWrap' + id + index;\n iDiv.id = 'quizWrap' + id;\n iDiv.className = 'Quiz';\n iDiv.setAttribute('data-qnum', index);\n mydiv.appendChild(iDiv);\n // iDiv.innerHTML=qa.question;\n\n var outerqDiv = document.createElement('div');\n outerqDiv.id = \"OuterquizQn\" + id + index;\n\n iDiv.append(outerqDiv);\n\n // Create div to contain question part\n var qDiv = document.createElement('div');\n qDiv.id = \"quizQn\" + id + index;\n //qDiv.textContent=qa.question;\n qDiv.innerHTML = jaxify(qa.question);\n\n outerqDiv.append(qDiv);\n\n // Create div for code inside question\n var codeDiv;\n if (\"code\" in qa) {\n codeDiv = document.createElement('div');\n codeDiv.id = \"code\" + id + index;\n codeDiv.className = \"QuizCode\";\n var codePre = document.createElement('pre');\n codeDiv.append(codePre);\n var codeCode = document.createElement('code');\n codePre.append(codeCode);\n codeCode.innerHTML = qa.code;\n outerqDiv.append(codeDiv);\n //console.log(codeDiv);\n }\n\n\n // Create div to contain answer part\n var aDiv = document.createElement('div');\n aDiv.id = \"quizAns\" + id + index;\n aDiv.className = 'Answer';\n iDiv.append(aDiv);\n\n //console.log(qa.type);\n\n var num_correct;\n if (qa.type == \"multiple_choice\") {\n num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n } else if (qa.type == \"many_choice\") {\n num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n } else if (qa.type == \"numeric\") {\n //console.log(\"numeric\");\n make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n }\n\n\n //Make div for feedback\n var fb = document.createElement(\"div\");\n fb.id = \"fb\" + id;\n //fb.style=\"font-size: 20px;text-align:center;\";\n fb.className = \"Feedback\";\n fb.setAttribute(\"data-answeredcorrect\", 0);\n fb.setAttribute(\"data-numcorrect\", num_correct);\n iDiv.append(fb);\n\n\n });\n var preserveResponses = mydiv.dataset.preserveresponses;\n console.log(preserveResponses);\n console.log(preserveResponses == \"true\");\n if (preserveResponses == \"true\") {\n console.log(preserveResponses);\n // Create Div to contain record of answers\n var iDiv = document.createElement('div');\n iDiv.id = 'responses' + mydiv.id;\n iDiv.className = 'JCResponses';\n // Create a place to store responses as an empty array\n iDiv.setAttribute('data-responses', '[]');\n\n // Dummy Text\n iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n //iDiv.className = 'Quiz';\n mydiv.appendChild(iDiv);\n }\n//console.log(\"At end of show_questions\");\n if (typeof MathJax != 'undefined') {\n console.log(\"MathJax version\", MathJax.version);\n var version = MathJax.version;\n setTimeout(function(){\n var version = MathJax.version;\n console.log('After sleep, MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([mydiv]);\n }\n }, 500);\nif (typeof version == 'undefined') {\n } else\n {\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([mydiv]);\n } else {\n console.log(\"MathJax not found\");\n }\n }\n }\n return false;\n}\n\n {\n show_questions(questionsbWprKoWNYBzN, bWprKoWNYBzN);\n }\n ", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "display_quiz(questions[2])" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "nbgrader": { "grade": false, "locked": true, "solution": false } }, "source": [ "## (Searching) Exercise 1.2.5\n", "There are also other data types in Python, which were not mentioned in this part (in case they are not as useful or will be introduced later). For instance, Complex is one of them. The sad truth is that every software developer Googles a lot. It's not because she/he is lazy or incompetent. It is because programming languages are constantly updated and some tools are limited to a narrow field of applications. It is impractical to learn everything at once, therefore every coder has learned how to look up the functionality their task requires. Therefore, it is crucial for you to learn how to Google as well. Complex type is used in Python to represent complex numbers. If you haven't heard about them — a complex number is a number, which has a real and an imaginary part. For example, $x = 17 + 5i$. Here, $x$ is a complex number with a real part of $17$ and an imaginary part of $5$.\n", "\n", "Your task is to create a variable my_complex_number of Complex type and assign a $3 + 2i$ value to it. For that you will have to Google a bit. Try to look for something like \"Python complex variables\". Python is very popular and you will be able to find everything you need. Make sure to filter the information you need — not everything you will find will be useful for this simple exercise.\n", "\n", "What is the correct ``my_complex_number`` variable?\n", "\n", "* my_complex_number = 3 + 2i \n", "* my_complex_number = 3 + 2j \n", "* my_complex_number = 3 + 2k \n" ] }, { "cell_type": "code", "execution_count": 2, "id": "6acdf92e", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
        " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": "var questionsJZDRiNQREvMB=[{\"question\": \"What is the correct my_complex_number variable?\", \"type\": \"many_choice\", \"answers\": [{\"answer\": \"my_complex_number = 3 + 2i \", \"correct\": false, \"feedback\": \"I hope not.\"}, {\"answer\": \"my_complex_number = 3 + 2j \", \"correct\": true, \"feedback\": \"Correct.\"}, {\"answer\": \"my_complex_number = 3 + 2k \", \"correct\": false, \"feedback\": \"I hope not.\"}]}];\n // Make a random ID\nfunction makeid(length) {\n var result = [];\n var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n var charactersLength = characters.length;\n for (var i = 0; i < length; i++) {\n result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n }\n return result.join('');\n}\n\n// Choose a random subset of an array. Can also be used to shuffle the array\nfunction getRandomSubarray(arr, size) {\n var shuffled = arr.slice(0), i = arr.length, temp, index;\n while (i--) {\n index = Math.floor((i + 1) * Math.random());\n temp = shuffled[index];\n shuffled[index] = shuffled[i];\n shuffled[i] = temp;\n }\n return shuffled.slice(0, size);\n}\n\nfunction printResponses(responsesContainer) {\n var responses=JSON.parse(responsesContainer.dataset.responses);\n var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
        1. Copy the text in this cell below \"Answer String\"
        2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
        3. Select the whole \"Replace Me\" text
        4. Paste in your answer string and press shift-Enter.
        5. Save the notebook using the save icon or File->Save Notebook menu item



        6. Answer String:
          ';\n console.log(responses);\n responses.forEach((response, index) => {\n if (response) {\n console.log(index + ': ' + response);\n stringResponses+= index + ': ' + response +\"
          \";\n }\n });\n responsesContainer.innerHTML=stringResponses;\n}\nfunction check_mc() {\n var id = this.id.split('-')[0];\n //var response = this.id.split('-')[1];\n //console.log(response);\n //console.log(\"In check_mc(), id=\"+id);\n //console.log(event.srcElement.id) \n //console.log(event.srcElement.dataset.correct) \n //console.log(event.srcElement.dataset.feedback)\n\n var label = event.srcElement;\n //console.log(label, label.nodeName);\n var depth = 0;\n while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n label = label.parentElement;\n console.log(depth, label);\n depth++;\n }\n\n\n\n var answers = label.parentElement.children;\n\n //console.log(answers);\n\n\n // Split behavior based on multiple choice vs many choice:\n var fb = document.getElementById(\"fb\" + id);\n\n\n\n\n if (fb.dataset.numcorrect == 1) {\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n //console.log(responsesContainer);\n var response = label.firstChild.innerText;\n if (label.querySelector(\".QuizCode\")){\n response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n }\n console.log(response);\n //console.log(document.getElementById(\"quizWrap\"+id));\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n console.log(responses);\n responses[qnum]= response;\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End code to preserve responses\n \n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n //console.log(child);\n child.className = \"MCButton\";\n }\n\n\n\n if (label.dataset.correct == \"true\") {\n // console.log(\"Correct action\");\n if (\"feedback\" in label.dataset) {\n fb.textContent = jaxify(label.dataset.feedback);\n } else {\n fb.textContent = \"Correct!\";\n }\n label.classList.add(\"correctButton\");\n\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n\n } else {\n if (\"feedback\" in label.dataset) {\n fb.textContent = jaxify(label.dataset.feedback);\n } else {\n fb.textContent = \"Incorrect -- try again.\";\n }\n //console.log(\"Error action\");\n label.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n }\n else {\n var reset = false;\n var feedback;\n if (label.dataset.correct == \"true\") {\n if (\"feedback\" in label.dataset) {\n feedback = jaxify(label.dataset.feedback);\n } else {\n feedback = \"Correct!\";\n }\n if (label.dataset.answered <= 0) {\n if (fb.dataset.answeredcorrect < 0) {\n fb.dataset.answeredcorrect = 1;\n reset = true;\n } else {\n fb.dataset.answeredcorrect++;\n }\n if (reset) {\n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n child.className = \"MCButton\";\n child.dataset.answered = 0;\n }\n }\n label.classList.add(\"correctButton\");\n label.dataset.answered = 1;\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n\n }\n } else {\n if (\"feedback\" in label.dataset) {\n feedback = jaxify(label.dataset.feedback);\n } else {\n feedback = \"Incorrect -- try again.\";\n }\n if (fb.dataset.answeredcorrect > 0) {\n fb.dataset.answeredcorrect = -1;\n reset = true;\n } else {\n fb.dataset.answeredcorrect--;\n }\n\n if (reset) {\n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n child.className = \"MCButton\";\n child.dataset.answered = 0;\n }\n }\n label.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n //console.log(responsesContainer);\n var response = label.firstChild.innerText;\n if (label.querySelector(\".QuizCode\")){\n response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n }\n console.log(response);\n //console.log(document.getElementById(\"quizWrap\"+id));\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n if (label.dataset.correct == \"true\") {\n if (typeof(responses[qnum]) == \"object\"){\n if (!responses[qnum].includes(response))\n responses[qnum].push(response);\n } else{\n responses[qnum]= [ response ];\n }\n } else {\n responses[qnum]= response;\n }\n console.log(responses);\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End save responses stuff\n\n\n\n var numcorrect = fb.dataset.numcorrect;\n var answeredcorrect = fb.dataset.answeredcorrect;\n if (answeredcorrect >= 0) {\n fb.textContent = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n } else {\n fb.textContent = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n }\n\n\n }\n\n if (typeof MathJax != 'undefined') {\n var version = MathJax.version;\n console.log('MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([fb]);\n }\n } else {\n console.log('MathJax not detected');\n }\n\n}\n\nfunction make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n var shuffled;\n if (shuffle_answers == \"True\") {\n //console.log(shuffle_answers+\" read as true\");\n shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n } else {\n //console.log(shuffle_answers+\" read as false\");\n shuffled = qa.answers;\n }\n\n\n var num_correct = 0;\n\n\n\n shuffled.forEach((item, index, ans_array) => {\n //console.log(answer);\n\n // Make input element\n var inp = document.createElement(\"input\");\n inp.type = \"radio\";\n inp.id = \"quizo\" + id + index;\n inp.style = \"display:none;\";\n aDiv.append(inp);\n\n //Make label for input element\n var lab = document.createElement(\"label\");\n lab.className = \"MCButton\";\n lab.id = id + '-' + index;\n lab.onclick = check_mc;\n var aSpan = document.createElement('span');\n aSpan.classsName = \"\";\n //qDiv.id=\"quizQn\"+id+index;\n if (\"answer\" in item) {\n aSpan.innerHTML = jaxify(item.answer);\n //aSpan.innerHTML=item.answer;\n }\n lab.append(aSpan);\n\n // Create div for code inside question\n var codeSpan;\n if (\"code\" in item) {\n codeSpan = document.createElement('span');\n codeSpan.id = \"code\" + id + index;\n codeSpan.className = \"QuizCode\";\n var codePre = document.createElement('pre');\n codeSpan.append(codePre);\n var codeCode = document.createElement('code');\n codePre.append(codeCode);\n codeCode.innerHTML = item.code;\n lab.append(codeSpan);\n //console.log(codeSpan);\n }\n\n //lab.textContent=item.answer;\n\n // Set the data attributes for the answer\n lab.setAttribute('data-correct', item.correct);\n if (item.correct) {\n num_correct++;\n }\n if (\"feedback\" in item) {\n lab.setAttribute('data-feedback', item.feedback);\n }\n lab.setAttribute('data-answered', 0);\n\n aDiv.append(lab);\n\n });\n\n if (num_correct > 1) {\n outerqDiv.className = \"ManyChoiceQn\";\n } else {\n outerqDiv.className = \"MultipleChoiceQn\";\n }\n\n return num_correct;\n\n}\nfunction check_numeric(ths, event) {\n\n if (event.keyCode === 13) {\n ths.blur();\n\n var id = ths.id.split('-')[0];\n\n var submission = ths.value;\n if (submission.indexOf('/') != -1) {\n var sub_parts = submission.split('/');\n //console.log(sub_parts);\n submission = sub_parts[0] / sub_parts[1];\n }\n //console.log(\"Reader entered\", submission);\n\n if (\"precision\" in ths.dataset) {\n var precision = ths.dataset.precision;\n // console.log(\"1:\", submission)\n submission = Math.round((1 * submission + Number.EPSILON) * 10 ** precision) / 10 ** precision;\n // console.log(\"Rounded to \", submission, \" precision=\", precision );\n }\n\n\n //console.log(\"In check_numeric(), id=\"+id);\n //console.log(event.srcElement.id) \n //console.log(event.srcElement.dataset.feedback)\n\n var fb = document.getElementById(\"fb\" + id);\n fb.style.display = \"none\";\n fb.textContent = \"Incorrect -- try again.\";\n\n var answers = JSON.parse(ths.dataset.answers);\n //console.log(answers);\n\n var defaultFB = \"\";\n var correct;\n var done = false;\n answers.every(answer => {\n //console.log(answer.type);\n\n correct = false;\n // if (answer.type==\"value\"){\n if ('value' in answer) {\n if (submission == answer.value) {\n fb.textContent = jaxify(answer.feedback);\n correct = answer.correct;\n //console.log(answer.correct);\n done = true;\n }\n // } else if (answer.type==\"range\") {\n } else if ('range' in answer) {\n //console.log(answer.range);\n if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n fb.textContent = jaxify(answer.feedback);\n correct = answer.correct;\n //console.log(answer.correct);\n done = true;\n }\n } else if (answer.type == \"default\") {\n defaultFB = answer.feedback;\n }\n if (done) {\n return false; // Break out of loop if this has been marked correct\n } else {\n return true; // Keep looking for case that includes this as a correct answer\n }\n });\n\n if ((!done) && (defaultFB != \"\")) {\n fb.innerHTML = jaxify(defaultFB);\n //console.log(\"Default feedback\", defaultFB);\n }\n\n fb.style.display = \"block\";\n if (correct) {\n ths.className = \"Input-text\";\n ths.classList.add(\"correctButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n } else {\n ths.className = \"Input-text\";\n ths.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n console.log(submission);\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n //console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n console.log(responses);\n if (submission == ths.value){\n responses[qnum]= submission;\n } else {\n responses[qnum]= ths.value + \"(\" + submission +\")\";\n }\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End code to preserve responses\n\n if (typeof MathJax != 'undefined') {\n var version = MathJax.version;\n console.log('MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([fb]);\n }\n } else {\n console.log('MathJax not detected');\n }\n return false;\n }\n\n}\n\nfunction isValid(el, charC) {\n //console.log(\"Input char: \", charC);\n if (charC == 46) {\n if (el.value.indexOf('.') === -1) {\n return true;\n } else if (el.value.indexOf('/') != -1) {\n var parts = el.value.split('/');\n if (parts[1].indexOf('.') === -1) {\n return true;\n }\n }\n else {\n return false;\n }\n } else if (charC == 47) {\n if (el.value.indexOf('/') === -1) {\n if ((el.value != \"\") && (el.value != \".\")) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else if (charC == 45) {\n var edex = el.value.indexOf('e');\n if (edex == -1) {\n edex = el.value.indexOf('E');\n }\n\n if (el.value == \"\") {\n return true;\n } else if (edex == (el.value.length - 1)) { // If just after e or E\n return true;\n } else {\n return false;\n }\n } else if (charC == 101) { // \"e\"\n if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n // Prev symbol must be digit or decimal point:\n if (el.value.slice(-1).search(/\\d/) >= 0) {\n return true;\n } else if (el.value.slice(-1).search(/\\./) >= 0) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else {\n if (charC > 31 && (charC < 48 || charC > 57))\n return false;\n }\n return true;\n}\n\nfunction numeric_keypress(evnt) {\n var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n\n if (charC == 13) {\n check_numeric(this, evnt);\n } else {\n return isValid(this, charC);\n }\n}\n\n\n\n\n\nfunction make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n\n\n\n //console.log(answer);\n\n\n outerqDiv.className = \"NumericQn\";\n aDiv.style.display = 'block';\n\n var lab = document.createElement(\"label\");\n lab.className = \"InpLabel\";\n lab.textContent = \"Type numeric answer here:\";\n aDiv.append(lab);\n\n var inp = document.createElement(\"input\");\n inp.type = \"text\";\n //inp.id=\"input-\"+id;\n inp.id = id + \"-0\";\n inp.className = \"Input-text\";\n inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n if (\"precision\" in qa) {\n inp.setAttribute('data-precision', qa.precision);\n }\n aDiv.append(inp);\n //console.log(inp);\n\n //inp.addEventListener(\"keypress\", check_numeric);\n //inp.addEventListener(\"keypress\", numeric_keypress);\n /*\n inp.addEventListener(\"keypress\", function(event) {\n return numeric_keypress(this, event);\n }\n );\n */\n //inp.onkeypress=\"return numeric_keypress(this, event)\";\n inp.onkeypress = numeric_keypress;\n inp.onpaste = event => false;\n\n inp.addEventListener(\"focus\", function (event) {\n this.value = \"\";\n return false;\n }\n );\n\n\n}\nfunction jaxify(string) {\n var mystring = string;\n\n var count = 0;\n var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n\n var count2 = 0;\n var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n\n //console.log(loc);\n\n while ((loc >= 0) || (loc2 >= 0)) {\n\n /* Have to replace all the double $$ first with current implementation */\n if (loc2 >= 0) {\n if (count2 % 2 == 0) {\n mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n } else {\n mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n }\n count2++;\n } else {\n if (count % 2 == 0) {\n mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n } else {\n mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n }\n count++;\n }\n loc = mystring.search(/([^\\\\]|^)(\\$)/);\n loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n }\n\n //console.log(mystring);\n return mystring;\n}\n\n\nfunction show_questions(json, mydiv) {\n console.log('show_questions');\n //var mydiv=document.getElementById(myid);\n var shuffle_questions = mydiv.dataset.shufflequestions;\n var num_questions = mydiv.dataset.numquestions;\n var shuffle_answers = mydiv.dataset.shuffleanswers;\n\n if (num_questions > json.length) {\n num_questions = json.length;\n }\n\n var questions;\n if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n //console.log(num_questions+\",\"+json.length);\n questions = getRandomSubarray(json, num_questions);\n } else {\n questions = json;\n }\n\n //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n\n // Iterate over questions\n questions.forEach((qa, index, array) => {\n //console.log(qa.question); \n\n var id = makeid(8);\n //console.log(id);\n\n\n // Create Div to contain question and answers\n var iDiv = document.createElement('div');\n //iDiv.id = 'quizWrap' + id + index;\n iDiv.id = 'quizWrap' + id;\n iDiv.className = 'Quiz';\n iDiv.setAttribute('data-qnum', index);\n mydiv.appendChild(iDiv);\n // iDiv.innerHTML=qa.question;\n\n var outerqDiv = document.createElement('div');\n outerqDiv.id = \"OuterquizQn\" + id + index;\n\n iDiv.append(outerqDiv);\n\n // Create div to contain question part\n var qDiv = document.createElement('div');\n qDiv.id = \"quizQn\" + id + index;\n //qDiv.textContent=qa.question;\n qDiv.innerHTML = jaxify(qa.question);\n\n outerqDiv.append(qDiv);\n\n // Create div for code inside question\n var codeDiv;\n if (\"code\" in qa) {\n codeDiv = document.createElement('div');\n codeDiv.id = \"code\" + id + index;\n codeDiv.className = \"QuizCode\";\n var codePre = document.createElement('pre');\n codeDiv.append(codePre);\n var codeCode = document.createElement('code');\n codePre.append(codeCode);\n codeCode.innerHTML = qa.code;\n outerqDiv.append(codeDiv);\n //console.log(codeDiv);\n }\n\n\n // Create div to contain answer part\n var aDiv = document.createElement('div');\n aDiv.id = \"quizAns\" + id + index;\n aDiv.className = 'Answer';\n iDiv.append(aDiv);\n\n //console.log(qa.type);\n\n var num_correct;\n if (qa.type == \"multiple_choice\") {\n num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n } else if (qa.type == \"many_choice\") {\n num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n } else if (qa.type == \"numeric\") {\n //console.log(\"numeric\");\n make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n }\n\n\n //Make div for feedback\n var fb = document.createElement(\"div\");\n fb.id = \"fb\" + id;\n //fb.style=\"font-size: 20px;text-align:center;\";\n fb.className = \"Feedback\";\n fb.setAttribute(\"data-answeredcorrect\", 0);\n fb.setAttribute(\"data-numcorrect\", num_correct);\n iDiv.append(fb);\n\n\n });\n var preserveResponses = mydiv.dataset.preserveresponses;\n console.log(preserveResponses);\n console.log(preserveResponses == \"true\");\n if (preserveResponses == \"true\") {\n console.log(preserveResponses);\n // Create Div to contain record of answers\n var iDiv = document.createElement('div');\n iDiv.id = 'responses' + mydiv.id;\n iDiv.className = 'JCResponses';\n // Create a place to store responses as an empty array\n iDiv.setAttribute('data-responses', '[]');\n\n // Dummy Text\n iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n //iDiv.className = 'Quiz';\n mydiv.appendChild(iDiv);\n }\n//console.log(\"At end of show_questions\");\n if (typeof MathJax != 'undefined') {\n console.log(\"MathJax version\", MathJax.version);\n var version = MathJax.version;\n setTimeout(function(){\n var version = MathJax.version;\n console.log('After sleep, MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([mydiv]);\n }\n }, 500);\nif (typeof version == 'undefined') {\n } else\n {\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([mydiv]);\n } else {\n console.log(\"MathJax not found\");\n }\n }\n }\n return false;\n}\n\n {\n show_questions(questionsJZDRiNQREvMB, JZDRiNQREvMB);\n }\n ", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "display_quiz(questions[3])" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "id": "3BXmdvSbS3WE", "nbgrader": { "grade": false, "locked": true, "solution": false } }, "source": [ "### Exercise 1.3.1\n", "\n", "Given that we have a rectangle with a height of $3$ cm, width of $5$ cm and a cutout circle of radius $0.6$ cm, as shown below. \n", "\n", "![image.png](01.png)\n", "\n", "In the code cell bellow you will find a script that computes the remainder area. However there is a mistake in the code. \n", "" ] }, { "cell_type": "code", "execution_count": 46, "id": "78bdcc2e", "metadata": {}, "outputs": [], "source": [ "rectangle_height = 3\n", "rectangle_width = 5\n", "pi = 3.14159265359\n", "radius = 0.6\n", "\n", "circle_area = pi * radius * 2\n", "rectangle_area = rectangle_height * rectangle_width\n", "remaining_area = rectangle_area - circle_area \n", "\n", "print(f'The remaining area is {remaining_area:.2f} cm^2')" ] }, { "cell_type": "code", "execution_count": 32, "id": "f8eced6e", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
          " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": "var questionsNyWdEVhaYypO=[{\"question\": \"What is the mistake?\", \"type\": \"many_choice\", \"answers\": [{\"answer\": \"The value of pi is incorrect.\", \"correct\": false, \"feedback\": \"I hope not.\"}, {\"answer\": \"The exponent operator is incorrect. \", \"correct\": true, \"feedback\": \"Correct.\"}, {\"answer\": \"The formula of the rectangle area is incorrect. \", \"correct\": false, \"feedback\": \"I hope not.\"}]}, {\"question\": \"What will the remainder area of the rectangle be? Round your answer to 2 decimal places.\", \"type\": \"numeric\", \"precision\": 2, \"answers\": [{\"type\": \"value\", \"value\": 13.87, \"correct\": true, \"feedback\": \"Correct.\"}]}];\n // Make a random ID\nfunction makeid(length) {\n var result = [];\n var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n var charactersLength = characters.length;\n for (var i = 0; i < length; i++) {\n result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n }\n return result.join('');\n}\n\n// Choose a random subset of an array. Can also be used to shuffle the array\nfunction getRandomSubarray(arr, size) {\n var shuffled = arr.slice(0), i = arr.length, temp, index;\n while (i--) {\n index = Math.floor((i + 1) * Math.random());\n temp = shuffled[index];\n shuffled[index] = shuffled[i];\n shuffled[i] = temp;\n }\n return shuffled.slice(0, size);\n}\n\nfunction printResponses(responsesContainer) {\n var responses=JSON.parse(responsesContainer.dataset.responses);\n var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
          1. Copy the text in this cell below \"Answer String\"
          2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
          3. Select the whole \"Replace Me\" text
          4. Paste in your answer string and press shift-Enter.
          5. Save the notebook using the save icon or File->Save Notebook menu item



          6. Answer String:
            ';\n console.log(responses);\n responses.forEach((response, index) => {\n if (response) {\n console.log(index + ': ' + response);\n stringResponses+= index + ': ' + response +\"
            \";\n }\n });\n responsesContainer.innerHTML=stringResponses;\n}\nfunction check_mc() {\n var id = this.id.split('-')[0];\n //var response = this.id.split('-')[1];\n //console.log(response);\n //console.log(\"In check_mc(), id=\"+id);\n //console.log(event.srcElement.id) \n //console.log(event.srcElement.dataset.correct) \n //console.log(event.srcElement.dataset.feedback)\n\n var label = event.srcElement;\n //console.log(label, label.nodeName);\n var depth = 0;\n while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n label = label.parentElement;\n console.log(depth, label);\n depth++;\n }\n\n\n\n var answers = label.parentElement.children;\n\n //console.log(answers);\n\n\n // Split behavior based on multiple choice vs many choice:\n var fb = document.getElementById(\"fb\" + id);\n\n\n\n\n if (fb.dataset.numcorrect == 1) {\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n //console.log(responsesContainer);\n var response = label.firstChild.innerText;\n if (label.querySelector(\".QuizCode\")){\n response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n }\n console.log(response);\n //console.log(document.getElementById(\"quizWrap\"+id));\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n console.log(responses);\n responses[qnum]= response;\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End code to preserve responses\n \n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n //console.log(child);\n child.className = \"MCButton\";\n }\n\n\n\n if (label.dataset.correct == \"true\") {\n // console.log(\"Correct action\");\n if (\"feedback\" in label.dataset) {\n fb.textContent = jaxify(label.dataset.feedback);\n } else {\n fb.textContent = \"Correct!\";\n }\n label.classList.add(\"correctButton\");\n\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n\n } else {\n if (\"feedback\" in label.dataset) {\n fb.textContent = jaxify(label.dataset.feedback);\n } else {\n fb.textContent = \"Incorrect -- try again.\";\n }\n //console.log(\"Error action\");\n label.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n }\n else {\n var reset = false;\n var feedback;\n if (label.dataset.correct == \"true\") {\n if (\"feedback\" in label.dataset) {\n feedback = jaxify(label.dataset.feedback);\n } else {\n feedback = \"Correct!\";\n }\n if (label.dataset.answered <= 0) {\n if (fb.dataset.answeredcorrect < 0) {\n fb.dataset.answeredcorrect = 1;\n reset = true;\n } else {\n fb.dataset.answeredcorrect++;\n }\n if (reset) {\n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n child.className = \"MCButton\";\n child.dataset.answered = 0;\n }\n }\n label.classList.add(\"correctButton\");\n label.dataset.answered = 1;\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n\n }\n } else {\n if (\"feedback\" in label.dataset) {\n feedback = jaxify(label.dataset.feedback);\n } else {\n feedback = \"Incorrect -- try again.\";\n }\n if (fb.dataset.answeredcorrect > 0) {\n fb.dataset.answeredcorrect = -1;\n reset = true;\n } else {\n fb.dataset.answeredcorrect--;\n }\n\n if (reset) {\n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n child.className = \"MCButton\";\n child.dataset.answered = 0;\n }\n }\n label.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n //console.log(responsesContainer);\n var response = label.firstChild.innerText;\n if (label.querySelector(\".QuizCode\")){\n response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n }\n console.log(response);\n //console.log(document.getElementById(\"quizWrap\"+id));\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n if (label.dataset.correct == \"true\") {\n if (typeof(responses[qnum]) == \"object\"){\n if (!responses[qnum].includes(response))\n responses[qnum].push(response);\n } else{\n responses[qnum]= [ response ];\n }\n } else {\n responses[qnum]= response;\n }\n console.log(responses);\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End save responses stuff\n\n\n\n var numcorrect = fb.dataset.numcorrect;\n var answeredcorrect = fb.dataset.answeredcorrect;\n if (answeredcorrect >= 0) {\n fb.textContent = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n } else {\n fb.textContent = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n }\n\n\n }\n\n if (typeof MathJax != 'undefined') {\n var version = MathJax.version;\n console.log('MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([fb]);\n }\n } else {\n console.log('MathJax not detected');\n }\n\n}\n\nfunction make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n var shuffled;\n if (shuffle_answers == \"True\") {\n //console.log(shuffle_answers+\" read as true\");\n shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n } else {\n //console.log(shuffle_answers+\" read as false\");\n shuffled = qa.answers;\n }\n\n\n var num_correct = 0;\n\n\n\n shuffled.forEach((item, index, ans_array) => {\n //console.log(answer);\n\n // Make input element\n var inp = document.createElement(\"input\");\n inp.type = \"radio\";\n inp.id = \"quizo\" + id + index;\n inp.style = \"display:none;\";\n aDiv.append(inp);\n\n //Make label for input element\n var lab = document.createElement(\"label\");\n lab.className = \"MCButton\";\n lab.id = id + '-' + index;\n lab.onclick = check_mc;\n var aSpan = document.createElement('span');\n aSpan.classsName = \"\";\n //qDiv.id=\"quizQn\"+id+index;\n if (\"answer\" in item) {\n aSpan.innerHTML = jaxify(item.answer);\n //aSpan.innerHTML=item.answer;\n }\n lab.append(aSpan);\n\n // Create div for code inside question\n var codeSpan;\n if (\"code\" in item) {\n codeSpan = document.createElement('span');\n codeSpan.id = \"code\" + id + index;\n codeSpan.className = \"QuizCode\";\n var codePre = document.createElement('pre');\n codeSpan.append(codePre);\n var codeCode = document.createElement('code');\n codePre.append(codeCode);\n codeCode.innerHTML = item.code;\n lab.append(codeSpan);\n //console.log(codeSpan);\n }\n\n //lab.textContent=item.answer;\n\n // Set the data attributes for the answer\n lab.setAttribute('data-correct', item.correct);\n if (item.correct) {\n num_correct++;\n }\n if (\"feedback\" in item) {\n lab.setAttribute('data-feedback', item.feedback);\n }\n lab.setAttribute('data-answered', 0);\n\n aDiv.append(lab);\n\n });\n\n if (num_correct > 1) {\n outerqDiv.className = \"ManyChoiceQn\";\n } else {\n outerqDiv.className = \"MultipleChoiceQn\";\n }\n\n return num_correct;\n\n}\nfunction check_numeric(ths, event) {\n\n if (event.keyCode === 13) {\n ths.blur();\n\n var id = ths.id.split('-')[0];\n\n var submission = ths.value;\n if (submission.indexOf('/') != -1) {\n var sub_parts = submission.split('/');\n //console.log(sub_parts);\n submission = sub_parts[0] / sub_parts[1];\n }\n //console.log(\"Reader entered\", submission);\n\n if (\"precision\" in ths.dataset) {\n var precision = ths.dataset.precision;\n // console.log(\"1:\", submission)\n submission = Math.round((1 * submission + Number.EPSILON) * 10 ** precision) / 10 ** precision;\n // console.log(\"Rounded to \", submission, \" precision=\", precision );\n }\n\n\n //console.log(\"In check_numeric(), id=\"+id);\n //console.log(event.srcElement.id) \n //console.log(event.srcElement.dataset.feedback)\n\n var fb = document.getElementById(\"fb\" + id);\n fb.style.display = \"none\";\n fb.textContent = \"Incorrect -- try again.\";\n\n var answers = JSON.parse(ths.dataset.answers);\n //console.log(answers);\n\n var defaultFB = \"\";\n var correct;\n var done = false;\n answers.every(answer => {\n //console.log(answer.type);\n\n correct = false;\n // if (answer.type==\"value\"){\n if ('value' in answer) {\n if (submission == answer.value) {\n fb.textContent = jaxify(answer.feedback);\n correct = answer.correct;\n //console.log(answer.correct);\n done = true;\n }\n // } else if (answer.type==\"range\") {\n } else if ('range' in answer) {\n //console.log(answer.range);\n if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n fb.textContent = jaxify(answer.feedback);\n correct = answer.correct;\n //console.log(answer.correct);\n done = true;\n }\n } else if (answer.type == \"default\") {\n defaultFB = answer.feedback;\n }\n if (done) {\n return false; // Break out of loop if this has been marked correct\n } else {\n return true; // Keep looking for case that includes this as a correct answer\n }\n });\n\n if ((!done) && (defaultFB != \"\")) {\n fb.innerHTML = jaxify(defaultFB);\n //console.log(\"Default feedback\", defaultFB);\n }\n\n fb.style.display = \"block\";\n if (correct) {\n ths.className = \"Input-text\";\n ths.classList.add(\"correctButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n } else {\n ths.className = \"Input-text\";\n ths.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n console.log(submission);\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n //console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n console.log(responses);\n if (submission == ths.value){\n responses[qnum]= submission;\n } else {\n responses[qnum]= ths.value + \"(\" + submission +\")\";\n }\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End code to preserve responses\n\n if (typeof MathJax != 'undefined') {\n var version = MathJax.version;\n console.log('MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([fb]);\n }\n } else {\n console.log('MathJax not detected');\n }\n return false;\n }\n\n}\n\nfunction isValid(el, charC) {\n //console.log(\"Input char: \", charC);\n if (charC == 46) {\n if (el.value.indexOf('.') === -1) {\n return true;\n } else if (el.value.indexOf('/') != -1) {\n var parts = el.value.split('/');\n if (parts[1].indexOf('.') === -1) {\n return true;\n }\n }\n else {\n return false;\n }\n } else if (charC == 47) {\n if (el.value.indexOf('/') === -1) {\n if ((el.value != \"\") && (el.value != \".\")) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else if (charC == 45) {\n var edex = el.value.indexOf('e');\n if (edex == -1) {\n edex = el.value.indexOf('E');\n }\n\n if (el.value == \"\") {\n return true;\n } else if (edex == (el.value.length - 1)) { // If just after e or E\n return true;\n } else {\n return false;\n }\n } else if (charC == 101) { // \"e\"\n if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n // Prev symbol must be digit or decimal point:\n if (el.value.slice(-1).search(/\\d/) >= 0) {\n return true;\n } else if (el.value.slice(-1).search(/\\./) >= 0) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else {\n if (charC > 31 && (charC < 48 || charC > 57))\n return false;\n }\n return true;\n}\n\nfunction numeric_keypress(evnt) {\n var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n\n if (charC == 13) {\n check_numeric(this, evnt);\n } else {\n return isValid(this, charC);\n }\n}\n\n\n\n\n\nfunction make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n\n\n\n //console.log(answer);\n\n\n outerqDiv.className = \"NumericQn\";\n aDiv.style.display = 'block';\n\n var lab = document.createElement(\"label\");\n lab.className = \"InpLabel\";\n lab.textContent = \"Type numeric answer here:\";\n aDiv.append(lab);\n\n var inp = document.createElement(\"input\");\n inp.type = \"text\";\n //inp.id=\"input-\"+id;\n inp.id = id + \"-0\";\n inp.className = \"Input-text\";\n inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n if (\"precision\" in qa) {\n inp.setAttribute('data-precision', qa.precision);\n }\n aDiv.append(inp);\n //console.log(inp);\n\n //inp.addEventListener(\"keypress\", check_numeric);\n //inp.addEventListener(\"keypress\", numeric_keypress);\n /*\n inp.addEventListener(\"keypress\", function(event) {\n return numeric_keypress(this, event);\n }\n );\n */\n //inp.onkeypress=\"return numeric_keypress(this, event)\";\n inp.onkeypress = numeric_keypress;\n inp.onpaste = event => false;\n\n inp.addEventListener(\"focus\", function (event) {\n this.value = \"\";\n return false;\n }\n );\n\n\n}\nfunction jaxify(string) {\n var mystring = string;\n\n var count = 0;\n var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n\n var count2 = 0;\n var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n\n //console.log(loc);\n\n while ((loc >= 0) || (loc2 >= 0)) {\n\n /* Have to replace all the double $$ first with current implementation */\n if (loc2 >= 0) {\n if (count2 % 2 == 0) {\n mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n } else {\n mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n }\n count2++;\n } else {\n if (count % 2 == 0) {\n mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n } else {\n mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n }\n count++;\n }\n loc = mystring.search(/([^\\\\]|^)(\\$)/);\n loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n }\n\n //console.log(mystring);\n return mystring;\n}\n\n\nfunction show_questions(json, mydiv) {\n console.log('show_questions');\n //var mydiv=document.getElementById(myid);\n var shuffle_questions = mydiv.dataset.shufflequestions;\n var num_questions = mydiv.dataset.numquestions;\n var shuffle_answers = mydiv.dataset.shuffleanswers;\n\n if (num_questions > json.length) {\n num_questions = json.length;\n }\n\n var questions;\n if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n //console.log(num_questions+\",\"+json.length);\n questions = getRandomSubarray(json, num_questions);\n } else {\n questions = json;\n }\n\n //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n\n // Iterate over questions\n questions.forEach((qa, index, array) => {\n //console.log(qa.question); \n\n var id = makeid(8);\n //console.log(id);\n\n\n // Create Div to contain question and answers\n var iDiv = document.createElement('div');\n //iDiv.id = 'quizWrap' + id + index;\n iDiv.id = 'quizWrap' + id;\n iDiv.className = 'Quiz';\n iDiv.setAttribute('data-qnum', index);\n mydiv.appendChild(iDiv);\n // iDiv.innerHTML=qa.question;\n\n var outerqDiv = document.createElement('div');\n outerqDiv.id = \"OuterquizQn\" + id + index;\n\n iDiv.append(outerqDiv);\n\n // Create div to contain question part\n var qDiv = document.createElement('div');\n qDiv.id = \"quizQn\" + id + index;\n //qDiv.textContent=qa.question;\n qDiv.innerHTML = jaxify(qa.question);\n\n outerqDiv.append(qDiv);\n\n // Create div for code inside question\n var codeDiv;\n if (\"code\" in qa) {\n codeDiv = document.createElement('div');\n codeDiv.id = \"code\" + id + index;\n codeDiv.className = \"QuizCode\";\n var codePre = document.createElement('pre');\n codeDiv.append(codePre);\n var codeCode = document.createElement('code');\n codePre.append(codeCode);\n codeCode.innerHTML = qa.code;\n outerqDiv.append(codeDiv);\n //console.log(codeDiv);\n }\n\n\n // Create div to contain answer part\n var aDiv = document.createElement('div');\n aDiv.id = \"quizAns\" + id + index;\n aDiv.className = 'Answer';\n iDiv.append(aDiv);\n\n //console.log(qa.type);\n\n var num_correct;\n if (qa.type == \"multiple_choice\") {\n num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n } else if (qa.type == \"many_choice\") {\n num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n } else if (qa.type == \"numeric\") {\n //console.log(\"numeric\");\n make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n }\n\n\n //Make div for feedback\n var fb = document.createElement(\"div\");\n fb.id = \"fb\" + id;\n //fb.style=\"font-size: 20px;text-align:center;\";\n fb.className = \"Feedback\";\n fb.setAttribute(\"data-answeredcorrect\", 0);\n fb.setAttribute(\"data-numcorrect\", num_correct);\n iDiv.append(fb);\n\n\n });\n var preserveResponses = mydiv.dataset.preserveresponses;\n console.log(preserveResponses);\n console.log(preserveResponses == \"true\");\n if (preserveResponses == \"true\") {\n console.log(preserveResponses);\n // Create Div to contain record of answers\n var iDiv = document.createElement('div');\n iDiv.id = 'responses' + mydiv.id;\n iDiv.className = 'JCResponses';\n // Create a place to store responses as an empty array\n iDiv.setAttribute('data-responses', '[]');\n\n // Dummy Text\n iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n //iDiv.className = 'Quiz';\n mydiv.appendChild(iDiv);\n }\n//console.log(\"At end of show_questions\");\n if (typeof MathJax != 'undefined') {\n console.log(\"MathJax version\", MathJax.version);\n var version = MathJax.version;\n setTimeout(function(){\n var version = MathJax.version;\n console.log('After sleep, MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([mydiv]);\n }\n }, 500);\nif (typeof version == 'undefined') {\n } else\n {\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([mydiv]);\n } else {\n console.log(\"MathJax not found\");\n }\n }\n }\n return false;\n}\n\n {\n show_questions(questionsNyWdEVhaYypO, NyWdEVhaYypO);\n }\n ", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "display_quiz(questions[4]+questions[5])" ] }, { "attachments": {}, "cell_type": "markdown", "metadata": { "id": "rax0w6q5S3WF", "nbgrader": { "grade": false, "locked": true, "solution": false } }, "source": [ "## Exercise 1.3.2\n", "\n", "Suppose a group of $5$ engineers ordered $4$ pizzas with $8$ slices each. \n", "" ] }, { "cell_type": "code", "execution_count": 33, "id": "dd01263b", "metadata": { "tags": [ "remove-input" ] }, "outputs": [ { "data": { "text/html": [ "
            " ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": "var questionsXvxYEZONhFQI=[{\"question\": \"How many pizza slices each engineer will get and how many slices will be left untouched?. Use // and % operators.\", \"type\": \"many_choice\", \"answers\": [{\"answer\": \"4 pizza slices per engineer and 4 untouched slices.\", \"correct\": false, \"feedback\": \"I hope not.\"}, {\"answer\": \"6.4 pizza slices per engineer and 0 untouched slices. \", \"correct\": false, \"feedback\": \"I hope not.\"}, {\"answer\": \"6 pizza slices per engineer and 2 untouched slices. \", \"correct\": true, \"feedback\": \"Correct.\"}]}];\n // Make a random ID\nfunction makeid(length) {\n var result = [];\n var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';\n var charactersLength = characters.length;\n for (var i = 0; i < length; i++) {\n result.push(characters.charAt(Math.floor(Math.random() * charactersLength)));\n }\n return result.join('');\n}\n\n// Choose a random subset of an array. Can also be used to shuffle the array\nfunction getRandomSubarray(arr, size) {\n var shuffled = arr.slice(0), i = arr.length, temp, index;\n while (i--) {\n index = Math.floor((i + 1) * Math.random());\n temp = shuffled[index];\n shuffled[index] = shuffled[i];\n shuffled[i] = temp;\n }\n return shuffled.slice(0, size);\n}\n\nfunction printResponses(responsesContainer) {\n var responses=JSON.parse(responsesContainer.dataset.responses);\n var stringResponses='IMPORTANT!To preserve this answer sequence for submission, when you have finalized your answers:
            1. Copy the text in this cell below \"Answer String\"
            2. Double click on the cell directly below the Answer String, labeled \"Replace Me\"
            3. Select the whole \"Replace Me\" text
            4. Paste in your answer string and press shift-Enter.
            5. Save the notebook using the save icon or File->Save Notebook menu item



            6. Answer String:
              ';\n console.log(responses);\n responses.forEach((response, index) => {\n if (response) {\n console.log(index + ': ' + response);\n stringResponses+= index + ': ' + response +\"
              \";\n }\n });\n responsesContainer.innerHTML=stringResponses;\n}\nfunction check_mc() {\n var id = this.id.split('-')[0];\n //var response = this.id.split('-')[1];\n //console.log(response);\n //console.log(\"In check_mc(), id=\"+id);\n //console.log(event.srcElement.id) \n //console.log(event.srcElement.dataset.correct) \n //console.log(event.srcElement.dataset.feedback)\n\n var label = event.srcElement;\n //console.log(label, label.nodeName);\n var depth = 0;\n while ((label.nodeName != \"LABEL\") && (depth < 20)) {\n label = label.parentElement;\n console.log(depth, label);\n depth++;\n }\n\n\n\n var answers = label.parentElement.children;\n\n //console.log(answers);\n\n\n // Split behavior based on multiple choice vs many choice:\n var fb = document.getElementById(\"fb\" + id);\n\n\n\n\n if (fb.dataset.numcorrect == 1) {\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n //console.log(responsesContainer);\n var response = label.firstChild.innerText;\n if (label.querySelector(\".QuizCode\")){\n response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n }\n console.log(response);\n //console.log(document.getElementById(\"quizWrap\"+id));\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n console.log(responses);\n responses[qnum]= response;\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End code to preserve responses\n \n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n //console.log(child);\n child.className = \"MCButton\";\n }\n\n\n\n if (label.dataset.correct == \"true\") {\n // console.log(\"Correct action\");\n if (\"feedback\" in label.dataset) {\n fb.textContent = jaxify(label.dataset.feedback);\n } else {\n fb.textContent = \"Correct!\";\n }\n label.classList.add(\"correctButton\");\n\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n\n } else {\n if (\"feedback\" in label.dataset) {\n fb.textContent = jaxify(label.dataset.feedback);\n } else {\n fb.textContent = \"Incorrect -- try again.\";\n }\n //console.log(\"Error action\");\n label.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n }\n else {\n var reset = false;\n var feedback;\n if (label.dataset.correct == \"true\") {\n if (\"feedback\" in label.dataset) {\n feedback = jaxify(label.dataset.feedback);\n } else {\n feedback = \"Correct!\";\n }\n if (label.dataset.answered <= 0) {\n if (fb.dataset.answeredcorrect < 0) {\n fb.dataset.answeredcorrect = 1;\n reset = true;\n } else {\n fb.dataset.answeredcorrect++;\n }\n if (reset) {\n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n child.className = \"MCButton\";\n child.dataset.answered = 0;\n }\n }\n label.classList.add(\"correctButton\");\n label.dataset.answered = 1;\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n\n }\n } else {\n if (\"feedback\" in label.dataset) {\n feedback = jaxify(label.dataset.feedback);\n } else {\n feedback = \"Incorrect -- try again.\";\n }\n if (fb.dataset.answeredcorrect > 0) {\n fb.dataset.answeredcorrect = -1;\n reset = true;\n } else {\n fb.dataset.answeredcorrect--;\n }\n\n if (reset) {\n for (var i = 0; i < answers.length; i++) {\n var child = answers[i];\n child.className = \"MCButton\";\n child.dataset.answered = 0;\n }\n }\n label.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n //console.log(responsesContainer);\n var response = label.firstChild.innerText;\n if (label.querySelector(\".QuizCode\")){\n response+= label.querySelector(\".QuizCode\").firstChild.innerText;\n }\n console.log(response);\n //console.log(document.getElementById(\"quizWrap\"+id));\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n if (label.dataset.correct == \"true\") {\n if (typeof(responses[qnum]) == \"object\"){\n if (!responses[qnum].includes(response))\n responses[qnum].push(response);\n } else{\n responses[qnum]= [ response ];\n }\n } else {\n responses[qnum]= response;\n }\n console.log(responses);\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End save responses stuff\n\n\n\n var numcorrect = fb.dataset.numcorrect;\n var answeredcorrect = fb.dataset.answeredcorrect;\n if (answeredcorrect >= 0) {\n fb.textContent = feedback + \" [\" + answeredcorrect + \"/\" + numcorrect + \"]\";\n } else {\n fb.textContent = feedback + \" [\" + 0 + \"/\" + numcorrect + \"]\";\n }\n\n\n }\n\n if (typeof MathJax != 'undefined') {\n var version = MathJax.version;\n console.log('MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([fb]);\n }\n } else {\n console.log('MathJax not detected');\n }\n\n}\n\nfunction make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id) {\n var shuffled;\n if (shuffle_answers == \"True\") {\n //console.log(shuffle_answers+\" read as true\");\n shuffled = getRandomSubarray(qa.answers, qa.answers.length);\n } else {\n //console.log(shuffle_answers+\" read as false\");\n shuffled = qa.answers;\n }\n\n\n var num_correct = 0;\n\n\n\n shuffled.forEach((item, index, ans_array) => {\n //console.log(answer);\n\n // Make input element\n var inp = document.createElement(\"input\");\n inp.type = \"radio\";\n inp.id = \"quizo\" + id + index;\n inp.style = \"display:none;\";\n aDiv.append(inp);\n\n //Make label for input element\n var lab = document.createElement(\"label\");\n lab.className = \"MCButton\";\n lab.id = id + '-' + index;\n lab.onclick = check_mc;\n var aSpan = document.createElement('span');\n aSpan.classsName = \"\";\n //qDiv.id=\"quizQn\"+id+index;\n if (\"answer\" in item) {\n aSpan.innerHTML = jaxify(item.answer);\n //aSpan.innerHTML=item.answer;\n }\n lab.append(aSpan);\n\n // Create div for code inside question\n var codeSpan;\n if (\"code\" in item) {\n codeSpan = document.createElement('span');\n codeSpan.id = \"code\" + id + index;\n codeSpan.className = \"QuizCode\";\n var codePre = document.createElement('pre');\n codeSpan.append(codePre);\n var codeCode = document.createElement('code');\n codePre.append(codeCode);\n codeCode.innerHTML = item.code;\n lab.append(codeSpan);\n //console.log(codeSpan);\n }\n\n //lab.textContent=item.answer;\n\n // Set the data attributes for the answer\n lab.setAttribute('data-correct', item.correct);\n if (item.correct) {\n num_correct++;\n }\n if (\"feedback\" in item) {\n lab.setAttribute('data-feedback', item.feedback);\n }\n lab.setAttribute('data-answered', 0);\n\n aDiv.append(lab);\n\n });\n\n if (num_correct > 1) {\n outerqDiv.className = \"ManyChoiceQn\";\n } else {\n outerqDiv.className = \"MultipleChoiceQn\";\n }\n\n return num_correct;\n\n}\nfunction check_numeric(ths, event) {\n\n if (event.keyCode === 13) {\n ths.blur();\n\n var id = ths.id.split('-')[0];\n\n var submission = ths.value;\n if (submission.indexOf('/') != -1) {\n var sub_parts = submission.split('/');\n //console.log(sub_parts);\n submission = sub_parts[0] / sub_parts[1];\n }\n //console.log(\"Reader entered\", submission);\n\n if (\"precision\" in ths.dataset) {\n var precision = ths.dataset.precision;\n // console.log(\"1:\", submission)\n submission = Math.round((1 * submission + Number.EPSILON) * 10 ** precision) / 10 ** precision;\n // console.log(\"Rounded to \", submission, \" precision=\", precision );\n }\n\n\n //console.log(\"In check_numeric(), id=\"+id);\n //console.log(event.srcElement.id) \n //console.log(event.srcElement.dataset.feedback)\n\n var fb = document.getElementById(\"fb\" + id);\n fb.style.display = \"none\";\n fb.textContent = \"Incorrect -- try again.\";\n\n var answers = JSON.parse(ths.dataset.answers);\n //console.log(answers);\n\n var defaultFB = \"\";\n var correct;\n var done = false;\n answers.every(answer => {\n //console.log(answer.type);\n\n correct = false;\n // if (answer.type==\"value\"){\n if ('value' in answer) {\n if (submission == answer.value) {\n fb.textContent = jaxify(answer.feedback);\n correct = answer.correct;\n //console.log(answer.correct);\n done = true;\n }\n // } else if (answer.type==\"range\") {\n } else if ('range' in answer) {\n //console.log(answer.range);\n if ((submission >= answer.range[0]) && (submission < answer.range[1])) {\n fb.textContent = jaxify(answer.feedback);\n correct = answer.correct;\n //console.log(answer.correct);\n done = true;\n }\n } else if (answer.type == \"default\") {\n defaultFB = answer.feedback;\n }\n if (done) {\n return false; // Break out of loop if this has been marked correct\n } else {\n return true; // Keep looking for case that includes this as a correct answer\n }\n });\n\n if ((!done) && (defaultFB != \"\")) {\n fb.innerHTML = jaxify(defaultFB);\n //console.log(\"Default feedback\", defaultFB);\n }\n\n fb.style.display = \"block\";\n if (correct) {\n ths.className = \"Input-text\";\n ths.classList.add(\"correctButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"correct\");\n } else {\n ths.className = \"Input-text\";\n ths.classList.add(\"incorrectButton\");\n fb.className = \"Feedback\";\n fb.classList.add(\"incorrect\");\n }\n\n // What follows is for the saved responses stuff\n var outerContainer = fb.parentElement.parentElement;\n var responsesContainer = document.getElementById(\"responses\" + outerContainer.id);\n if (responsesContainer) {\n console.log(submission);\n var qnum = document.getElementById(\"quizWrap\"+id).dataset.qnum;\n //console.log(\"Question \" + qnum);\n //console.log(id, \", got numcorrect=\",fb.dataset.numcorrect);\n var responses=JSON.parse(responsesContainer.dataset.responses);\n console.log(responses);\n if (submission == ths.value){\n responses[qnum]= submission;\n } else {\n responses[qnum]= ths.value + \"(\" + submission +\")\";\n }\n responsesContainer.setAttribute('data-responses', JSON.stringify(responses));\n printResponses(responsesContainer);\n }\n // End code to preserve responses\n\n if (typeof MathJax != 'undefined') {\n var version = MathJax.version;\n console.log('MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([fb]);\n }\n } else {\n console.log('MathJax not detected');\n }\n return false;\n }\n\n}\n\nfunction isValid(el, charC) {\n //console.log(\"Input char: \", charC);\n if (charC == 46) {\n if (el.value.indexOf('.') === -1) {\n return true;\n } else if (el.value.indexOf('/') != -1) {\n var parts = el.value.split('/');\n if (parts[1].indexOf('.') === -1) {\n return true;\n }\n }\n else {\n return false;\n }\n } else if (charC == 47) {\n if (el.value.indexOf('/') === -1) {\n if ((el.value != \"\") && (el.value != \".\")) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else if (charC == 45) {\n var edex = el.value.indexOf('e');\n if (edex == -1) {\n edex = el.value.indexOf('E');\n }\n\n if (el.value == \"\") {\n return true;\n } else if (edex == (el.value.length - 1)) { // If just after e or E\n return true;\n } else {\n return false;\n }\n } else if (charC == 101) { // \"e\"\n if ((el.value.indexOf('e') === -1) && (el.value.indexOf('E') === -1) && (el.value.indexOf('/') == -1)) {\n // Prev symbol must be digit or decimal point:\n if (el.value.slice(-1).search(/\\d/) >= 0) {\n return true;\n } else if (el.value.slice(-1).search(/\\./) >= 0) {\n return true;\n } else {\n return false;\n }\n } else {\n return false;\n }\n } else {\n if (charC > 31 && (charC < 48 || charC > 57))\n return false;\n }\n return true;\n}\n\nfunction numeric_keypress(evnt) {\n var charC = (evnt.which) ? evnt.which : evnt.keyCode;\n\n if (charC == 13) {\n check_numeric(this, evnt);\n } else {\n return isValid(this, charC);\n }\n}\n\n\n\n\n\nfunction make_numeric(qa, outerqDiv, qDiv, aDiv, id) {\n\n\n\n //console.log(answer);\n\n\n outerqDiv.className = \"NumericQn\";\n aDiv.style.display = 'block';\n\n var lab = document.createElement(\"label\");\n lab.className = \"InpLabel\";\n lab.textContent = \"Type numeric answer here:\";\n aDiv.append(lab);\n\n var inp = document.createElement(\"input\");\n inp.type = \"text\";\n //inp.id=\"input-\"+id;\n inp.id = id + \"-0\";\n inp.className = \"Input-text\";\n inp.setAttribute('data-answers', JSON.stringify(qa.answers));\n if (\"precision\" in qa) {\n inp.setAttribute('data-precision', qa.precision);\n }\n aDiv.append(inp);\n //console.log(inp);\n\n //inp.addEventListener(\"keypress\", check_numeric);\n //inp.addEventListener(\"keypress\", numeric_keypress);\n /*\n inp.addEventListener(\"keypress\", function(event) {\n return numeric_keypress(this, event);\n }\n );\n */\n //inp.onkeypress=\"return numeric_keypress(this, event)\";\n inp.onkeypress = numeric_keypress;\n inp.onpaste = event => false;\n\n inp.addEventListener(\"focus\", function (event) {\n this.value = \"\";\n return false;\n }\n );\n\n\n}\nfunction jaxify(string) {\n var mystring = string;\n\n var count = 0;\n var loc = mystring.search(/([^\\\\]|^)(\\$)/);\n\n var count2 = 0;\n var loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n\n //console.log(loc);\n\n while ((loc >= 0) || (loc2 >= 0)) {\n\n /* Have to replace all the double $$ first with current implementation */\n if (loc2 >= 0) {\n if (count2 % 2 == 0) {\n mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\[\");\n } else {\n mystring = mystring.replace(/([^\\\\]|^)(\\$\\$)/, \"$1\\\\]\");\n }\n count2++;\n } else {\n if (count % 2 == 0) {\n mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\(\");\n } else {\n mystring = mystring.replace(/([^\\\\]|^)(\\$)/, \"$1\\\\)\");\n }\n count++;\n }\n loc = mystring.search(/([^\\\\]|^)(\\$)/);\n loc2 = mystring.search(/([^\\\\]|^)(\\$\\$)/);\n //console.log(mystring,\", loc:\",loc,\", loc2:\",loc2);\n }\n\n //console.log(mystring);\n return mystring;\n}\n\n\nfunction show_questions(json, mydiv) {\n console.log('show_questions');\n //var mydiv=document.getElementById(myid);\n var shuffle_questions = mydiv.dataset.shufflequestions;\n var num_questions = mydiv.dataset.numquestions;\n var shuffle_answers = mydiv.dataset.shuffleanswers;\n\n if (num_questions > json.length) {\n num_questions = json.length;\n }\n\n var questions;\n if ((num_questions < json.length) || (shuffle_questions == \"True\")) {\n //console.log(num_questions+\",\"+json.length);\n questions = getRandomSubarray(json, num_questions);\n } else {\n questions = json;\n }\n\n //console.log(\"SQ: \"+shuffle_questions+\", NQ: \" + num_questions + \", SA: \", shuffle_answers);\n\n // Iterate over questions\n questions.forEach((qa, index, array) => {\n //console.log(qa.question); \n\n var id = makeid(8);\n //console.log(id);\n\n\n // Create Div to contain question and answers\n var iDiv = document.createElement('div');\n //iDiv.id = 'quizWrap' + id + index;\n iDiv.id = 'quizWrap' + id;\n iDiv.className = 'Quiz';\n iDiv.setAttribute('data-qnum', index);\n mydiv.appendChild(iDiv);\n // iDiv.innerHTML=qa.question;\n\n var outerqDiv = document.createElement('div');\n outerqDiv.id = \"OuterquizQn\" + id + index;\n\n iDiv.append(outerqDiv);\n\n // Create div to contain question part\n var qDiv = document.createElement('div');\n qDiv.id = \"quizQn\" + id + index;\n //qDiv.textContent=qa.question;\n qDiv.innerHTML = jaxify(qa.question);\n\n outerqDiv.append(qDiv);\n\n // Create div for code inside question\n var codeDiv;\n if (\"code\" in qa) {\n codeDiv = document.createElement('div');\n codeDiv.id = \"code\" + id + index;\n codeDiv.className = \"QuizCode\";\n var codePre = document.createElement('pre');\n codeDiv.append(codePre);\n var codeCode = document.createElement('code');\n codePre.append(codeCode);\n codeCode.innerHTML = qa.code;\n outerqDiv.append(codeDiv);\n //console.log(codeDiv);\n }\n\n\n // Create div to contain answer part\n var aDiv = document.createElement('div');\n aDiv.id = \"quizAns\" + id + index;\n aDiv.className = 'Answer';\n iDiv.append(aDiv);\n\n //console.log(qa.type);\n\n var num_correct;\n if (qa.type == \"multiple_choice\") {\n num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n } else if (qa.type == \"many_choice\") {\n num_correct = make_mc(qa, shuffle_answers, outerqDiv, qDiv, aDiv, id);\n } else if (qa.type == \"numeric\") {\n //console.log(\"numeric\");\n make_numeric(qa, outerqDiv, qDiv, aDiv, id);\n }\n\n\n //Make div for feedback\n var fb = document.createElement(\"div\");\n fb.id = \"fb\" + id;\n //fb.style=\"font-size: 20px;text-align:center;\";\n fb.className = \"Feedback\";\n fb.setAttribute(\"data-answeredcorrect\", 0);\n fb.setAttribute(\"data-numcorrect\", num_correct);\n iDiv.append(fb);\n\n\n });\n var preserveResponses = mydiv.dataset.preserveresponses;\n console.log(preserveResponses);\n console.log(preserveResponses == \"true\");\n if (preserveResponses == \"true\") {\n console.log(preserveResponses);\n // Create Div to contain record of answers\n var iDiv = document.createElement('div');\n iDiv.id = 'responses' + mydiv.id;\n iDiv.className = 'JCResponses';\n // Create a place to store responses as an empty array\n iDiv.setAttribute('data-responses', '[]');\n\n // Dummy Text\n iDiv.innerHTML=\"Select your answers and then follow the directions that will appear here.\"\n //iDiv.className = 'Quiz';\n mydiv.appendChild(iDiv);\n }\n//console.log(\"At end of show_questions\");\n if (typeof MathJax != 'undefined') {\n console.log(\"MathJax version\", MathJax.version);\n var version = MathJax.version;\n setTimeout(function(){\n var version = MathJax.version;\n console.log('After sleep, MathJax version', version);\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([mydiv]);\n }\n }, 500);\nif (typeof version == 'undefined') {\n } else\n {\n if (version[0] == \"2\") {\n MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]);\n } else if (version[0] == \"3\") {\n MathJax.typeset([mydiv]);\n } else {\n console.log(\"MathJax not found\");\n }\n }\n }\n return false;\n}\n\n {\n show_questions(questionsXvxYEZONhFQI, XvxYEZONhFQI);\n }\n ", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "display_quiz(questions[6])" ] } ], "metadata": { "colab": { "collapsed_sections": [], "name": "merged.ipynb", "provenance": [] }, "kernelspec": { "display_name": "base", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.13" }, "latex_envs": { "LaTeX_envs_menu_present": true, "autoclose": false, "autocomplete": true, "bibliofile": "biblio.bib", "cite_by": "apalike", "current_citInitial": 1, "eqLabelWithNumbers": true, "eqNumInitial": 1, "hotkeys": { "equation": "Ctrl-E", "itemize": "Ctrl-I" }, "labels_anchors": false, "latex_user_defs": false, "report_style_numbering": false, "user_envs_cfg": false } }, "nbformat": 4, "nbformat_minor": 5 }