Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add exercises: Multiplying a matrix with a vector, multiplying a matr…

…ix with a matrix, matrix dimensions, and defined and undefined matrix operations

Summary:
- Add 4 exercises
- First pass at question-based hints

Test Plan: Tested locally

Reviewers: eater

Reviewed By: eater

Differential Revision: http://phabricator.khanacademy.org/D856
  • Loading branch information...
commit 94549034f38eb31a27a73232496a0e3399adc974 1 parent a1978a3
@stephjang stephjang authored
View
30 css/khan-exercise.css
@@ -654,3 +654,33 @@ div.timeline-total {
opacity: 0.8;
filter: alpha(opacity = 80);
}
+
+/* Question-based hints */
+
+.qhint {
+ border: 1px solid #aaaaaa;
+ background: #f9f9f9;
+ -moz-border-radius: 4px;
+ -webkit-border-radius: 4px;
+ border-radius: 4px;
+ margin-right: 20px;
+ margin-bottom: 20px;
+ padding: 10px;
+}
+
+.qhint-answer {
+ display: none;
+}
+
+.qhint-feedback {
+ font-weight: bold;
+ color: #6495ED;
+}
+
+.qhint-feedback.correct {
+ color: #28AE7B;
+}
+
+.qhint-feedback.incorrect {
+ color: #CE4444;
+}
View
125 exercises/defined_and_undefined_matrix_operations.html
@@ -0,0 +1,125 @@
+<!DOCTYPE html>
+<html data-require="math matrix">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Defined and undefined matrix operations</title>
+ <script src="../khan-exercise.js"></script>
+ <style>
+ #answer_area .sol input[type=text] {
+ width: 20px;
+ }
+ </style>
+</head>
+<body>
+ <div class="exercise">
+
+ <div class="vars" data-ensure="!(DIM_1 === 1 && DIM_2 === 1) && !(DIM_3 === 1 && DIM_4 === 1) && (PRETTY_MAT_1_ID !== PRETTY_MAT_2_ID)">
+ <var id="ANSWER">DEFINED ? "Yes" : "No"</var>
+
+ <var id="MAT_1">makeMatrix(randRange(-2, 4, DIM_1, DIM_2))</var>
+ <var id="MAT_2">makeMatrix(randRange(-2, 4, DIM_3, DIM_4))</var>
+
+ <var id="PRETTY_MAT_1_ID">"\\textbf " + randFromArray("ABCDEF")</var>
+ <var id="PRETTY_MAT_2_ID">"\\textbf " + randFromArray("ABCDEF")</var>
+
+ <var id="PRETTY_MAT_1">
+ printSimpleMatrix(MAT_1)
+ </var>
+ <var id="PRETTY_MAT_2">
+ printSimpleMatrix(MAT_2)
+ </var>
+ </div>
+
+ <div class="problem">
+ <p>
+ <code><var>PRETTY_MAT_1_ID</var> = <var>PRETTY_MAT_1</var></code>
+ </p>
+ <p>
+ <code><var>PRETTY_MAT_2_ID</var> = <var>PRETTY_MAT_2</var></code>
+ </p>
+ </div>
+
+ <p class="question">
+ Is <code><var>PRETTY_MAT_1_ID + OPERATION + PRETTY_MAT_2_ID</var></code> defined?
+ </p>
+
+ <p class="solution"><var>ANSWER</var></p>
+ <ul class="choices" data-category="true">
+ <li>Yes</li>
+ <li>No</li>
+ </ul>
+
+ <div class="problems">
+ <div id="addition-subtraction">
+ <div class="vars" data-apply="prependVars">
+ <var id="DEFINED">randRange(0, 1)</var>
+ <var id="DIM_1">randRange(1, 3)</var>
+ <var id="DIM_2">randRange(1, 3)</var>
+ <var id="DIM_3">DIM_1</var>
+ <var id="DIM_4">
+ DEFINED ? DIM_2 : randRangeExclude(1, 3, [DIM_2])
+ </var>
+ <var id="OPERATION">randFromArray("+-")</var>
+ </div>
+
+ <div class="hints">
+ <div>
+ <p>
+ In order for <span data-if="OPERATION === '+'">addition</span><span data-else>subtraction</span> of two matrices to be defined, the matrices must have the same dimensions.
+ </p>
+ <p>
+ If <code><var>PRETTY_MAT_1_ID</var></code> is of dimension <code>(\blue m \times \red n)</code> and <code><var>PRETTY_MAT_2_ID</var></code> is of dimension <code>(\blue p \times \red q)</code>, then:
+ </p>
+ <p>
+ 1. <code>\blue m</code> (number of rows in <code><var>PRETTY_MAT_1_ID</var></code>) must equal <code>\blue p</code> (number of rows in <code><var>PRETTY_MAT_2_ID</var></code>) and
+ </p>
+ <p>
+ 2. <code>\red n</code> (number of columns in <code><var>PRETTY_MAT_1_ID</var></code>) must equal <code>\red q</code> (number of columns in <code><var>PRETTY_MAT_2_ID</var></code>)
+ </p>
+ <p>
+ for their <span data-if="OPERATION === '+'">sum</span><span data-else>difference</span> to be defined.
+ </p>
+ </div>
+ <div>
+ <p>
+ Since <code><var>PRETTY_MAT_1_ID</var></code> has <span data-if="DEFINED">the same</span><span data-else>different</span> dimensions <code>(<var>DIM_1 + "\\times" + DIM_2</var>)</code> <span data-if="DEFINED">as</span><span data-else>from</span> <code><var>PRETTY_MAT_2_ID</var></code> <code>(<var>DIM_3 + "\\times" + DIM_4</var>)</code>,
+ <p>
+ <code><var>PRETTY_MAT_1_ID + OPERATION + PRETTY_MAT_2_ID</var></code> is <span data-if="!DEFINED">not</span> defined.
+ </p>
+ </div>
+ </div>
+ </div>
+
+ <div id="multiplication">
+ <div class="vars" data-apply="prependVars">
+ <var id="DEFINED">randRange(0, 1)</var>
+ <var id="DIM_1">randRange(1, 3)</var>
+ <var id="DIM_2">randRange(1, 3)</var>
+ <var id="DIM_3">
+ DEFINED ? DIM_2 : randRangeExclude(1, 3, [DIM_2])
+ </var>
+ <var id="DIM_4">randRange(1, 3)</var>
+ <var id="OPERATION">""</var>
+ </div>
+
+ <div class="hints">
+ <div>
+ <p>
+ In order for multiplication of two matrices to be defined, the two inner dimensions must be equal.
+ </p>
+ </div>
+ <div>
+ <p>
+ If the two matrices have dimensions <code>(\blue m \times \red n)</code> and <code>(\red p \times \green q)</code>, then <code>\red n</code> (number of columns in the first matrix) must equal <code>\red p</code> (number of rows in the second matrix) for their product to be defined.
+ </p>
+ </div>
+ <div>
+ Since <code><var>PRETTY_MAT_1_ID</var></code> has <span data-if="DEFINED">the same</span><span data-else>a different</span> number of columns (<var>DIM_2</var>) <span data-if="DEFINED">as</span><span data-else>than</span> <code><var>PRETTY_MAT_2_ID</var></code> has rows (<var>DIM_3</var>), <code><var>PRETTY_MAT_1_ID + PRETTY_MAT_2_ID</var></code> is <span data-if="!DEFINED">not</span> defined.
+ </div>
+ </div>
+ </div>
+ </div>
+
+ </div>
+</body>
+</html>
View
165 exercises/defined_and_undefined_matrix_operations_alternative.html
@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+<html data-require="math matrix qhints">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Defined and undefined matrix operations</title>
+ <script src="../khan-exercise.js"></script>
+ <style>
+ #answer_area .sol input[type=text] {
+ width: 20px;
+ }
+ </style>
+</head>
+<body>
+ <div class="exercise">
+
+ <div class="vars" data-ensure="!(DIM_1 === 1 && DIM_2 === 1) && !(DIM_3 === 1 && DIM_4 === 1) && (PRETTY_MAT_1_ID !== PRETTY_MAT_2_ID)">
+ <var id="ANSWER">DEFINED ? "Yes" : "No"</var>
+
+ <var id="MAT_1">makeMatrix(randRange(-2, 4, DIM_1, DIM_2))</var>
+ <var id="MAT_2">makeMatrix(randRange(-2, 4, DIM_3, DIM_4))</var>
+
+ <var id="PRETTY_MAT_1_ID">"\\textbf " + randFromArray("ABCDEF")</var>
+ <var id="PRETTY_MAT_2_ID">"\\textbf " + randFromArray("ABCDEF")</var>
+
+ <var id="PRETTY_MAT_1">
+ printSimpleMatrix(MAT_1)
+ </var>
+ <var id="PRETTY_MAT_2">
+ printSimpleMatrix(MAT_2)
+ </var>
+ </div>
+
+ <div class="problem">
+ <p>
+ <code><var>PRETTY_MAT_1_ID</var> = <var>PRETTY_MAT_1</var></code>
+ </p>
+ <p>
+ <code><var>PRETTY_MAT_2_ID</var> = <var>PRETTY_MAT_2</var></code>
+ </p>
+ </div>
+
+ <p class="question">
+ Is <code><var>PRETTY_MAT_1_ID + OPERATION + PRETTY_MAT_2_ID</var></code> defined?
+ </p>
+
+ <p class="solution"><var>ANSWER</var></p>
+ <ul class="choices" data-category="true">
+ <li>Yes</li>
+ <li>No</li>
+ </ul>
+
+ <div class="problems">
+ <div id="addition-subtraction">
+ <div class="vars" data-apply="prependVars">
+ <var id="DEFINED">randRange(0, 1)</var>
+ <var id="DIM_1">randRange(1, 3)</var>
+ <var id="DIM_2">randRange(1, 3)</var>
+ <var id="DIM_3">DIM_1</var>
+ <var id="DIM_4">
+ DEFINED ? DIM_2 : randRangeExclude(1, 3, [DIM_2])
+ </var>
+ <var id="OPERATION">randFromArray("+-")</var>
+ </div>
+
+ <div class="hints">
+ <div>
+ <p>
+ In order for <span data-if="OPERATION === '+'">addition</span><span data-else>subtraction</span> of two matrices to be defined, the matrices must have the same dimensions.
+ </p>
+ <p>
+ If <code><var>PRETTY_MAT_1_ID</var></code> is of dimension <code>(\blue m \times \red n)</code> and <code><var>PRETTY_MAT_2_ID</var></code> is of dimension <code>(\blue p \times \red q)</code>, then:
+ </p>
+ <p>
+ 1. <code>\blue m</code> (number of rows in <code><var>PRETTY_MAT_1_ID</var></code>) must equal <code>\blue p</code> (number of rows in <code><var>PRETTY_MAT_2_ID</var></code>) and
+ </p>
+ <p>
+ 2. <code>\red n</code> (number of columns in <code><var>PRETTY_MAT_1_ID</var></code>) must equal <code>\red q</code> (number of columns in <code><var>PRETTY_MAT_2_ID</var></code>)
+ </p>
+ <p>
+ for their <span data-if="OPERATION === '+'">sum</span><span data-else>difference</span> to be defined.
+ </p>
+ </div>
+ <div class="qhint">
+ <p>
+ Do <code><var>PRETTY_MAT_1_ID</var></code> and <code><var>PRETTY_MAT_2_ID</var></code> have the same number of rows?
+ </p>
+ <span class="qhint-answer"><var>DIM_1 === DIM_3 ? "Yes" : "No"</var></span>
+ <p class="qhint-input">
+ <input class="simple-button" type="button" value="Yes"/>
+ <input class="simple-button" type="button" value="No"/>
+ </p>
+ </div>
+ <div class="qhint">
+ <p>
+ Do <code><var>PRETTY_MAT_1_ID</var></code> and <code><var>PRETTY_MAT_2_ID</var></code> have the same number of columns?
+ </p>
+ <span class="qhint-answer"><var>DIM_2 === DIM_4 ? "Yes" : "No"</var></span>
+ <p class="qhint-input">
+ <input class="simple-button" type="button" value="Yes"/>
+ <input class="simple-button" type="button" value="No"/>
+ </p>
+ </div>
+ <div>
+ <p>
+ Since <code><var>PRETTY_MAT_1_ID</var></code> has <span data-if="DEFINED">the same</span><span data-else>different</span> dimensions <code>(<var>DIM_1 + "\\times" + DIM_2</var>)</code> <span data-if="DEFINED">as</span><span data-else>from</span> <code><var>PRETTY_MAT_2_ID</var></code> <code>(<var>DIM_3 + "\\times" + DIM_4</var>)</code>,
+ <p>
+ <code><var>PRETTY_MAT_1_ID + OPERATION + PRETTY_MAT_2_ID</var></code> is <span data-if="!DEFINED">not</span> defined.
+ </p>
+ </div>
+ </div>
+ </div>
+
+ <div id="multiplication">
+ <div class="vars" data-apply="prependVars">
+ <var id="DEFINED">randRange(0, 1)</var>
+ <var id="DIM_1">randRange(1, 3)</var>
+ <var id="DIM_2">randRange(1, 3)</var>
+ <var id="DIM_3">
+ DEFINED ? DIM_2 : randRangeExclude(1, 3, [DIM_2])
+ </var>
+ <var id="DIM_4">randRange(1, 3)</var>
+ <var id="OPERATION">""</var>
+ </div>
+
+ <div class="hints">
+ <div>
+ <p>
+ In order for multiplication of two matrices to be defined, the two inner dimensions must be equal.
+ </p>
+ </div>
+ <div>
+ <p>
+ If the two matrices have dimensions <code>(\blue m \times \red n)</code> and <code>(\red p \times \green q)</code>, then <code>\red n</code> (number of columns in the first matrix) must equal <code>\red p</code> (number of rows in the second matrix) for their product to be defined.
+ </p>
+ </div>
+ <div class="qhint">
+ <p>
+ How many columns does the first matrix, <code><var>PRETTY_MAT_1_ID</var></code>, have?
+ </p>
+ <span class="qhint-answer"><var>DIM_2</var></span>
+ <p class="qhint-input">
+ <input type="text" value=""/>
+ <input type="submit" value="Check"/>
+ </p>
+ </div>
+ <div class="qhint">
+ <p>
+ How many rows does the second matrix, <code><var>PRETTY_MAT_2_ID</var></code>, have?
+ </p>
+ <span class="qhint-answer"><var>DIM_3</var></span>
+ <p class="qhint-input">
+ <input type="text" value=""/>
+ <input type="submit" value="Check"/>
+ </p>
+ </div>
+ <div>
+ Since <code><var>PRETTY_MAT_1_ID</var></code> has <span data-if="DEFINED">the same</span><span data-else>a different</span> number of columns (<var>DIM_2</var>) <span data-if="DEFINED">as</span><span data-else>than</span> <code><var>PRETTY_MAT_2_ID</var></code> has rows (<var>DIM_3</var>), <code><var>PRETTY_MAT_1_ID + PRETTY_MAT_2_ID</var></code> is <span data-if="!DEFINED">not</span> defined.
+ </div>
+ </div>
+ </div>
+ </div>
+
+ </div>
+</body>
+</html>
View
12 exercises/matrix_addition_and_subtraction.html
@@ -38,16 +38,20 @@
<var id="SOLN_MAT_COLOR">PINK</var>
<var id="PRETTY_MAT_A">
- printMatrix(MAT_A, MAT_A_COLOR)
+ printSimpleMatrix(MAT_A, MAT_A_COLOR)
</var>
<var id="PRETTY_MAT_B">
- printMatrix(MAT_B, MAT_B_COLOR)
+ printSimpleMatrix(MAT_B, MAT_B_COLOR)
</var>
<var id="PRETTY_HINT_MAT">
- printMatrix(MAT_A, MAT_A_COLOR, MAT_B, MAT_B_COLOR, OPERATION)
+ printMatrix(function(a, b) {
+ a = colorMarkup(a, MAT_A_COLOR);
+ b = colorMarkup(b, MAT_B_COLOR);
+ return a + OPERATION + b;
+ }, MAT_A, MAT_B)
</var>
<var id="PRETTY_SOLN_MAT">
- printMatrix(SOLN_MAT, SOLN_MAT_COLOR)
+ printSimpleMatrix(SOLN_MAT, SOLN_MAT_COLOR)
</var>
</div>
View
61 exercises/matrix_dimensions.html
@@ -0,0 +1,61 @@
+<!DOCTYPE html>
+<html data-require="math matrix qhints">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Matrix dimensions</title>
+ <script src="../khan-exercise.js"></script>
+ <style>
+ #answer_area .sol input[type=text] {
+ width: 20px;
+ }
+ </style>
+</head>
+<body>
+ <div class="exercise">
+ <div class="vars" data-ensure="!(DIM_1 === 1 && DIM_2 === 1)">
+ <var id="DIM_1">randRange(1, 4)</var>
+ <var id="DIM_2">randRange(1, 4)</var>
+ <var id="MAT_A">makeMatrix(randRange(-2, 4, DIM_1, DIM_2))</var>
+
+ <var id="PRETTY_MAT_ID">"\\textbf " + randFromArray("ABCDEF")</var>
+ <var id="PRETTY_MAT_A">
+ printSimpleMatrix(MAT_A)
+ </var>
+ </div>
+ <div class="problems">
+ <div>
+ <div class="problem">
+ <p>
+ <code><var>PRETTY_MAT_ID</var> = <var>PRETTY_MAT_A</var></code>
+ </p>
+ </div>
+
+ <p class="question">
+ What are the dimensions of matrix <code><var>PRETTY_MAT_ID</var></code>?
+ </p>
+
+ <div class="solution" data-type="multiple">
+ <span class="sol"><var>DIM_1</var></span>
+ <code>\times</code>
+ <span class="sol"><var>DIM_2</var></span>
+ </div>
+ </div>
+ </div>
+
+ <div class="hints">
+ <div>
+ <p>
+ The first dimension is the number of rows in the matrix. <code><var>PRETTY_MAT_ID</var></code> has <var>DIM_1</var> rows.
+ </p>
+ </div>
+ <div>
+ <p>
+ The second dimension is the number of columns in the matrix. <code><var>PRETTY_MAT_ID</var></code> has <var>DIM_2</var> columns.
+ </div>
+ <div>
+ So, <code><var>PRETTY_MAT_ID</var></code> is a <var>DIM_1</var> <code>\times</code> <var>DIM_2</var> matrix.
+ </div>
+ </div>
+ </div>
+</body>
+</html>
View
72 exercises/matrix_dimensions_alternative.html
@@ -0,0 +1,72 @@
+<!DOCTYPE html>
+<html data-require="math matrix qhints">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Matrix dimensions</title>
+ <script src="../khan-exercise.js"></script>
+ <style>
+ #answer_area .sol input[type=text] {
+ width: 20px;
+ }
+ </style>
+</head>
+<body>
+ <div class="exercise">
+ <div class="vars" data-ensure="!(DIM_1 === 1 && DIM_2 === 1)">
+ <var id="DIM_1">randRange(1, 4)</var>
+ <var id="DIM_2">randRange(1, 4)</var>
+ <var id="MAT_A">makeMatrix(randRange(-2, 4, DIM_1, DIM_2))</var>
+
+ <var id="PRETTY_MAT_ID">"\\textbf " + randFromArray("ABCDEF")</var>
+ <var id="PRETTY_MAT_A">
+ printSimpleMatrix(MAT_A)
+ </var>
+ </div>
+ <div class="problems">
+ <div>
+ <div class="problem">
+ <p>
+ <code><var>PRETTY_MAT_ID</var> = <var>PRETTY_MAT_A</var></code>
+ </p>
+ </div>
+
+ <p class="question">
+ What are the dimensions of matrix <code><var>PRETTY_MAT_ID</var></code>?
+ </p>
+
+ <div class="solution" data-type="multiple">
+ <span class="sol"><var>DIM_1</var></span>
+ <code>\times</code>
+ <span class="sol"><var>DIM_2</var></span>
+ </div>
+ </div>
+ </div>
+
+ <div class="hints">
+ <div class="qhint">
+ <p>
+ The first dimension is the number of rows in the matrix. How many rows does <code><var>PRETTY_MAT_ID</var></code> have?
+ </p>
+ <span class="qhint-answer"><var>DIM_1</var></span>
+ <p class="qhint-input">
+ <input type="text" value=""/>
+ <input type="submit" value="Check"/>
+ </p>
+ </div>
+ <div class="qhint">
+ <p>
+ The second dimension is the number of columns in the matrix. How many columns does <code><var>PRETTY_MAT_ID</var></code> have?
+ </p>
+ <span class="qhint-answer"><var>DIM_2</var></span>
+ <p class="qhint-input">
+ <input type="text" value=""/>
+ <input type="submit" value="Check"/>
+ </p>
+ </div>
+ <div>
+ So, <code><var>PRETTY_MAT_ID</var></code> is a <var>DIM_1</var> <code>\times</code> <var>DIM_2</var> matrix.
+ </div>
+ </div>
+ </div>
+</body>
+</html>
View
194 exercises/multiplying_a_matrix_by_a_matrix.html
@@ -0,0 +1,194 @@
+<!DOCTYPE html>
+<html data-require="math matrix">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Multiplying a matrix by a matrix</title>
+ <script src="../khan-exercise.js"></script>
+ <style>
+ #answer_area .row input[type=text] {
+ width: 40px;
+ margin-right: 5px;
+ }
+
+ #answer_area .row {
+ margin: 0;
+ }
+ </style>
+</head>
+<body>
+ <div class="exercise">
+
+ <div class="vars" data-ensure="PRETTY_MAT_1_ID !== PRETTY_MAT_2_ID">
+ <var id="DIM_3">DIM_2</var>
+ <var id="MAT_1">makeMatrix(randRange(-2, 5, DIM_1, DIM_2))</var>
+ <var id="MAT_2">makeMatrix(randRange(-2, 5, DIM_3, DIM_4))</var>
+
+ <var id="SOLN_MAT">
+ matrixMult(MAT_1, MAT_2)
+ </var>
+
+ <var id="PRETTY_MAT_1_ID">"\\textbf " + randFromArray("ABCDEF")</var>
+ <var id="PRETTY_MAT_2_ID">"\\textbf " + randFromArray("ABCDEF")</var>
+
+ <!-- For generating hint matrices-->
+ <var id="ROW_COLORS">[GREEN, BLUE, GRAY]</var>
+ <var id="COL_COLORS">[ORANGE, "#DF0030", "#9D38BD"]</var>
+
+ <var id="FINAL_HINT_MAT">
+ makeMultHintMatrix(MAT_1, MAT_2, ROW_COLORS, COL_COLORS)
+ </var>
+
+ </div>
+
+ <div class="problem">
+ <p>
+ Let <code><var>PRETTY_MAT_1_ID</var> = <var>printSimpleMatrix(MAT_1)</var></code> and
+ <code><var>PRETTY_MAT_2_ID</var> = <var>printSimpleMatrix(MAT_2)</var></code>.
+ </p>
+ </div>
+
+ <p class="question">
+ What is <code><var>PRETTY_MAT_1_ID + PRETTY_MAT_2_ID</var></code>?
+ </p>
+
+ <div class="hints">
+ <div>
+ <p>
+ Because <code><var>PRETTY_MAT_1_ID</var></code> has dimensions <code>(<var>DIM_1 + "\\times" + DIM_2</var>)</code> and <code><var>PRETTY_MAT_2_ID</var></code> has dimensions <code>(<var>DIM_3 + "\\times" + DIM_4</var>)</code>, the answer matrix will have dimensions <code>(<var>DIM_1 + "\\times" + DIM_4</var>)</code>.
+ </p>
+ <p>
+ <code>
+ <var>PRETTY_MAT_1_ID + PRETTY_MAT_2_ID</var>
+ =
+ <var>printColoredDimMatrix(MAT_1, ROW_COLORS, true)</var>
+ <var>printColoredDimMatrix(MAT_2, COL_COLORS, false)</var>
+ =
+ <var>
+ printSimpleMatrix(maskMatrix(FINAL_HINT_MAT, []))
+ </var>
+ </code>
+ </p>
+ </div>
+ <div>
+ <p>
+ To find the element at any row <code>i</code>, column <code>j</code> of the answer matrix, multiply the elements in row <code>i</code> of the first matrix, <code><var>PRETTY_MAT_1_ID</var></code>, with the corresponding elements in column <code>j</code> of the second matrix, <code><var>PRETTY_MAT_2_ID</var></code>, and add the products together.
+ </p>
+ </div>
+ <div>
+ <p>
+ So, to find the element at row 1, column 1 of the answer matrix, multiply the first element in <code><var>colorMarkup("\\text{row }1", ROW_COLORS[0])</var></code> of <code><var>PRETTY_MAT_1_ID</var></code> with the first element in <code><var>colorMarkup("\\text{column }1", COL_COLORS[0])</var></code> of <code><var>PRETTY_MAT_2_ID</var></code>, then multiply the second element in <code><var>colorMarkup("\\text{row }1", ROW_COLORS[0])</var></code> of <code><var>PRETTY_MAT_1_ID</var></code> with the second element in <code><var>colorMarkup("\\text{column }1", COL_COLORS[0])</var></code> of <code><var>PRETTY_MAT_2_ID</var></code>, and so on. Add the products together.
+ </p>
+ <p>
+ <code>
+ <var>
+ printSimpleMatrix(
+ maskMatrix(FINAL_HINT_MAT, [[1, 1]])
+ )
+ </var>
+ </code>
+ </p>
+ </div>
+ <div>
+ <p>
+ Likewise, to find the element at row 2, column 1 of the answer matrix, multiply the elements in <code><var>colorMarkup("\\text{row }2", ROW_COLORS[1])</var></code> of <code><var>PRETTY_MAT_1_ID</var></code> with the corresponding elements in <code><var>colorMarkup("\\text{column }1", COL_COLORS[0])</var></code> of <code><var>PRETTY_MAT_2_ID</var></code> and add the products together.
+ </p>
+ <p>
+ <code>
+ <var>
+ printSimpleMatrix(
+ maskMatrix(FINAL_HINT_MAT, [[1, 1], [2, 1]])
+ )
+ </var>
+ </code>
+ </p>
+ </div>
+ <div>
+ <p>
+ Likewise, to find the element at row 1, column 2 of the answer matrix, multiply the elements in <code><var>colorMarkup("\\text{row }1", ROW_COLORS[0])</var></code> of <code><var>PRETTY_MAT_1_ID</var></code> with the corresponding elements in <code><var>colorMarkup("\\text{column }2", COL_COLORS[1])</var></code> of <code><var>PRETTY_MAT_2_ID</var></code> and add the products together.
+ </p>
+ <p>
+ <code>
+ <var>
+ printSimpleMatrix(
+ maskMatrix(FINAL_HINT_MAT, [[1, 1], [2, 1], [1, 2]])
+ )
+ </var>
+ </code>
+ </p>
+ </div>
+ <div>
+ <p>
+ Fill out the rest:
+ </p>
+ <p>
+ <code>
+ <var>
+ printSimpleMatrix(FINAL_HINT_MAT)
+ </var>
+ </code>
+ </p>
+ </div>
+ <div>
+ <p>After simplifying, we end up with:</p>
+ <div>
+ <code>
+ <var>printSimpleMatrix(SOLN_MAT)</var>
+ </code>
+ </div>
+ </div>
+ </div>
+
+ <div class="solution" data-type="multiple">
+ <p data-each="SOLN_MAT as row" class="row">
+ <span data-each="row as elem" class="sol">
+ <var>elem</var>
+ </span>
+ </p>
+ </div>
+
+ <div class="problems">
+ <!-- 2x2 solution dimensions -->
+ <div id="2x2-2x2">
+ <div class="vars" data-apply="prependVars">
+ <var id="DIM_1">2</var>
+ <var id="DIM_2">2</var>
+ <var id="DIM_4">2</var>
+ </div>
+ </div>
+ <div id="2x3-3x2">
+ <div class="vars" data-apply="prependVars">
+ <var id="DIM_1">2</var>
+ <var id="DIM_2">3</var>
+ <var id="DIM_4">2</var>
+ </div>
+ </div>
+
+ <!-- 2x3 solution dimensions -->
+ <div id="2x2-2x3">
+ <div class="vars" data-apply="prependVars">
+ <var id="DIM_1">2</var>
+ <var id="DIM_2">2</var>
+ <var id="DIM_4">3</var>
+ </div>
+ </div>
+
+ <!-- 3x2 solution dimensions -->
+ <div id="3x1-1x2">
+ <div class="vars" data-apply="prependVars">
+ <var id="DIM_1">3</var>
+ <var id="DIM_2">1</var>
+ <var id="DIM_4">2</var>
+ </div>
+ </div>
+ <div id="3x2-2x2">
+ <div class="vars" data-apply="prependVars">
+ <var id="DIM_1">3</var>
+ <var id="DIM_2">2</var>
+ <var id="DIM_4">2</var>
+ </div>
+ </div>
+ </div>
+
+ </div>
+</body>
+</html>
View
170 exercises/multiplying_a_matrix_by_a_vector.html
@@ -0,0 +1,170 @@
+<!DOCTYPE html>
+<html data-require="math matrix">
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+ <title>Multiplying a matrix by a vector</title>
+ <script src="../khan-exercise.js"></script>
+ <style>
+ #answer_area .row input[type=text] {
+ width: 40px;
+ margin-right: 5px;
+ }
+
+ #answer_area .row {
+ margin: 0;
+ }
+ </style>
+</head>
+<body>
+ <div class="exercise">
+
+ <div class="vars">
+ <var id="DIM_3">DIM_2</var>
+ <var id="DIM_4">1</var>
+ <var id="MAT_1">makeMatrix(randRange(-2, 5, DIM_1, DIM_2))</var>
+ <var id="MAT_2">makeMatrix(randRange(-2, 5, DIM_3, DIM_4))</var>
+
+ <var id="SOLN_MAT">
+ matrixMult(MAT_1, MAT_2)
+ </var>
+
+ <var id="PRETTY_MAT_1_ID">"\\textbf " + randFromArray("ABCDEF")</var>
+ <var id="PRETTY_MAT_2_ID">"\\textbf " + randFromArray("vw")</var>
+
+ <!-- For generating hint matrices-->
+ <var id="ROW_COLORS">[GREEN, BLUE, GRAY]</var>
+ <var id="COL_COLORS">[ORANGE]</var>
+
+ <var id="FINAL_HINT_MAT">
+ makeMultHintMatrix(MAT_1, MAT_2, ROW_COLORS, COL_COLORS)
+ </var>
+
+ </div>
+
+ <div class="problem">
+ <p>
+ Let <code><var>PRETTY_MAT_1_ID</var> = <var>printSimpleMatrix(MAT_1)</var></code> and
+ <code><var>PRETTY_MAT_2_ID</var> = <var>printSimpleMatrix(MAT_2)</var></code>.
+ </p>
+ </div>
+
+ <p class="question">
+ What is <code><var>PRETTY_MAT_1_ID + PRETTY_MAT_2_ID</var></code>?
+ </p>
+
+ <div class="hints">
+ <div>
+ <p>
+ Because <code><var>PRETTY_MAT_1_ID</var></code> has dimensions <code>(<var>DIM_1 + "\\times" + DIM_2</var>)</code> and <code><var>PRETTY_MAT_2_ID</var></code> has dimensions <code>(<var>DIM_3 + "\\times" + DIM_4</var>)</code>, the answer matrix will have dimensions <code>(<var>DIM_1 + "\\times" + DIM_4</var>)</code>.
+ </p>
+ <p>
+ <code>
+ <var>PRETTY_MAT_1_ID + PRETTY_MAT_2_ID</var>
+ =
+ <var>printColoredDimMatrix(MAT_1, ROW_COLORS, true)</var>
+ <var>printColoredDimMatrix(MAT_2, COL_COLORS, false)</var>
+ =
+ <var>
+ printSimpleMatrix(maskMatrix(FINAL_HINT_MAT, []))
+ </var>
+ </code>
+ </p>
+ </div>
+ <div>
+ <p>
+ To find the element at any row <code>i</code>, column <code>j</code> of the answer matrix, multiply the elements in row <code>i</code> of the first matrix, <code><var>PRETTY_MAT_1_ID</var></code>, with the corresponding elements in column <code>j</code> of the second matrix, <code><var>PRETTY_MAT_2_ID</var></code>, and add the products together.
+ </p>
+ </div>
+ <div>
+ <p>
+ So, to find the element at row 1, column 1 of the answer matrix, multiply the first element in <code><var>colorMarkup("\\text{row }1", ROW_COLORS[0])</var></code> of <code><var>PRETTY_MAT_1_ID</var></code> with the first element in <code><var>colorMarkup("\\text{column }1", COL_COLORS[0])</var></code> of <code><var>PRETTY_MAT_2_ID</var></code>, then multiply the second element in <code><var>colorMarkup("\\text{row }1", ROW_COLORS[0])</var></code> of <code><var>PRETTY_MAT_1_ID</var></code> with the second element in <code><var>colorMarkup("\\text{column }1", COL_COLORS[0])</var></code> of <code><var>PRETTY_MAT_2_ID</var></code>, and so on. Add the products together.
+ </p>
+ <p>
+ <code>
+ <var>
+ printSimpleMatrix(
+ maskMatrix(FINAL_HINT_MAT, [[1, 1]])
+ )
+ </var>
+ </code>
+ </p>
+ </div>
+ <div>
+ <p>
+ Likewise, to find the element at row 2, column 1 of the answer matrix, multiply the elements in <code><var>colorMarkup("\\text{row }2", ROW_COLORS[1])</var></code> of <code><var>PRETTY_MAT_1_ID</var></code> with the corresponding elements in <code><var>colorMarkup("\\text{column }1", COL_COLORS[0])</var></code> of <code><var>PRETTY_MAT_2_ID</var></code> and add the products together.
+ </p>
+ <p>
+ <code>
+ <var>
+ printSimpleMatrix(
+ maskMatrix(FINAL_HINT_MAT, [[1, 1], [2, 1]])
+ )
+ </var>
+ </code>
+ </p>
+ </div>
+ <div>
+ <p>
+ Fill out the rest:
+ </p>
+ <p>
+ <code>
+ <var>
+ printSimpleMatrix(FINAL_HINT_MAT)
+ </var>
+ </code>
+ </p>
+ </div>
+ <div>
+ <p>After simplifying, we end up with:</p>
+ <div>
+ <code>
+ <var>printSimpleMatrix(SOLN_MAT)</var>
+ </code>
+ </div>
+ </div>
+ </div>
+
+ <div class="solution" data-type="multiple">
+ <p data-each="SOLN_MAT as row" class="row">
+ <span data-each="row as elem" class="sol">
+ <var>elem</var>
+ </span>
+ </p>
+ </div>
+
+ <div class="problems">
+
+ <!-- 2x1 solution dimensions -->
+ <div id="2x2-2x1">
+ <div class="vars" data-apply="prependVars">
+ <var id="DIM_1">2</var>
+ <var id="DIM_2">2</var>
+ </div>
+ </div>
+ <div id="2x3-3x1">
+ <div class="vars" data-apply="prependVars">
+ <var id="DIM_1">2</var>
+ <var id="DIM_2">3</var>
+ </div>
+ </div>
+
+ <!-- 3x1 solution dimensions -->
+ <div id="3x2-2x1">
+ <div class="vars" data-apply="prependVars">
+ <var id="DIM_1">3</var>
+ <var id="DIM_2">2</var>
+ </div>
+ </div>
+
+ <!-- 4x1 solution dimensions -->
+ <div id="4x2-2x1">
+ <div class="vars" data-apply="prependVars">
+ <var id="DIM_1">4</var>
+ <var id="DIM_2">2</var>
+ </div>
+ </div>
+ </div>
+ </div>
+</body>
+</html>
View
15 exercises/scalar_matrix_multiplication.html
@@ -27,24 +27,23 @@
return a * SCALAR;
}, MAT_A)
</var>
- <var id="SCALAR_MAT">
- deepZipWith(2, function(a) {
- return SCALAR;
- }, MAT_A)
- </var>
<var id="MAT_A_COLOR">BLUE</var>
<var id="SCALAR_COLOR">GREEN</var>
<var id="SOLN_MAT_COLOR">PINK</var>
<var id="PRETTY_MAT_A">
- printMatrix(MAT_A, MAT_A_COLOR)
+ printSimpleMatrix(MAT_A, MAT_A_COLOR)
</var>
<var id="PRETTY_HINT_MAT">
- printMatrix(SCALAR_MAT, SCALAR_COLOR, MAT_A, MAT_A_COLOR, OPERATION)
+ printMatrix(function(a) {
+ var s = colorMarkup(SCALAR, SCALAR_COLOR);
+ var b = colorMarkup(a, MAT_A_COLOR);
+ return s + OPERATION + b;
+ }, MAT_A)
</var>
<var id="PRETTY_SOLN_MAT">
- printMatrix(SOLN_MAT, SOLN_MAT_COLOR)
+ printSimpleMatrix(SOLN_MAT, SOLN_MAT_COLOR)
</var>
</div>
View
22 utils/math.js
@@ -482,6 +482,28 @@ $.extend(KhanUtil, {
isInt: function(num) {
return parseFloat(num) === parseInt(num, 10) && !isNaN(num);
},
+
+
+ /**
+ * Add LaTeX color markup to a given value.
+ */
+ colorMarkup: function(val, color) {
+ return "\\color{" + color + "}{" + val + "}";
+ },
+
+ /**
+ * Like _.contains except using _.isEqual to verify if item is present.
+ * (Works for lists of non-primitive values.)
+ */
+ contains: function(list, item) {
+ return _.any(list, function(elem) {
+ if (_.isEqual(item, elem)) {
+ return true;
+ }
+ return false;
+ });
+ },
+
BLUE: "#6495ED",
ORANGE: "#FFA500",
PINK: "#FF00AF",
View
177 utils/matrix.js
@@ -14,51 +14,67 @@ $.extend(KhanUtil, {
},
/**
- * Given a 2d matrix, return the LaTeX (MathJax) code for printing
- * the matrix.
- *
- * If optional parameters mat2, color2, and operation are included, this
- * can be used to generate intermediate hint matrices as in
- * matrix_addition.html.
- *
- * @param mat {array} a 2d matrix
- * ex: [[0, 2], [1, 3], [4, 5]] (3 x 2 matrix)
- * @param color {string} (optional) color to format the elements of /mat/,
- in hexadecimal. ex: "#28AE7B" (KhanUtil.GREEN)
- * @param mat2 {array} (optional) a 2d matrix w/ same dimensions as /mat/
- * @param color2 {string} (optional) color to format the elements of /mat2/
- * @param operation {string} (optional) operation being explained in hints
- * ex: "+"
+ * Apply the given function to each element of the given matrix and return
+ * the resulting matrix.
*/
- printMatrix: function(mat, color, mat2, color2, operation) {
- // return prematurely if no matrix included
- if (!_.isArray(mat) || !mat.length) {
- return "";
- }
+ matrixMap: function(fn, mat) {
+ return _.map(mat, function(row, i) {
+ return _.map(row, function(elem, j) {
+ return fn(elem, i, j);
+ });
+ });
+ },
- var isCombo = (_.isArray(mat2) && mat2.length === mat.length &&
- mat2[0].length === mat[0].length &&
- _.isString(color2) && _.isString(operation));
+ /**
+ * Given a matrix and list of row-col indices to exclude from masking,
+ * return a new matrix with all but the elements in excludeList overwritten
+ * by the value "?".
+ *
+ * @param mat {result of makeMatrix}
+ * @param excludeList {array of arrays} List of row-col indices to keep
+ * from being overwritten. Note that these indices start at 1, not
+ * 0, to match with common math notation.
+ */
+ maskMatrix: function(mat, excludeList) {
+ var result = [];
+
+ _.times(mat.r, function(i) {
+ var row = [];
+ _.times(mat.c, function(j) {
+ if (KhanUtil.contains(excludeList, [i+1, j+1])) {
+ row.push(mat[i][j]);
+ } else {
+ row.push("?");
+ }
+ });
+ result.push(row);
+ });
+ return result;
+ },
- if (isCombo) {
- mat = KhanUtil.deepZipWith(2, function(a, b) {
- var elem1 = "\\color{" + color + "}{" + a + "}";
- var elem2 = "\\color{" + color2 + "}{" + b + "}";
- return elem1 + operation + elem2;
- }, mat, mat2);
- }
+ /**
+ * Given one or more same-dimension 2d matrices and a function for
+ * how to combine and format their elements in the output matrix,
+ * return the LaTeX code for rendering the matrix. Inherits syntax from
+ * deepZipWith().
+ *
+ * Example usage:
+ *
+ * printMatrix(function(a, b) {
+ * return colorMarkup(a, "#FF0000") + "-" + colorMarkup(b, "#00FF00");
+ * }, matA, matB);
+ *
+ */
+ printMatrix: function(fn) {
+ var args = Array.prototype.slice.call(arguments);
+ mat = KhanUtil.deepZipWith.apply(this, [2].concat(args));
var table = _.map(mat, function(row, i) {
return row.join(" & ");
}).join(" \\\\ ");
- var prefix = "\\left[ \\begin{array}";
- var suffix = "\\end{array} \\right]";
-
- if (!isCombo && color) {
- prefix = "\\left[ \\color{" + color + "}{\\begin{array}";
- suffix = "\\end{array}} \\right]";
- }
+ var prefix = "\\left[\\begin{array}";
+ var suffix = "\\end{array}\\right]";
// to generate the alignment info needed for LaTeX table markup
var alignment = "{";
@@ -71,6 +87,77 @@ $.extend(KhanUtil, {
return prefix + alignment + table + suffix;
},
+ /**
+ * Given a matrix and a color, format all elements with the given color
+ * (if supplied) and return the LaTeX code for rendering the matrix.
+ *
+ * @param mat {array of arrays} the matrix to format
+ * @param color {string}
+ */
+ printSimpleMatrix: function(mat, color) {
+ return KhanUtil.printMatrix(function(item) {
+ if (color) {
+ return KhanUtil.colorMarkup(item, color);
+ }
+ return item;
+ }, mat);
+ },
+
+ /**
+ * Format the rows or columns of the given matrix with the colors in the
+ * given colors array, and return the LaTeX code for rendering the matrix.
+ *
+ * @param mat {array of arrays} the matrix to format
+ * @param colors {array of strings} list of colors
+ * @param isRow {bool} whether to apply the colors by row or by column
+ */
+ printColoredDimMatrix: function(mat, colors, isRow) {
+ var matrix = KhanUtil.matrixMap(function(item, i, j) {
+ var color = colors[isRow ? i : j];
+ return KhanUtil.colorMarkup(item, color);
+ }, mat);
+ return KhanUtil.printSimpleMatrix(matrix);
+ },
+
+ /**
+ * Generate markup for a color-coded matrix illustrating the calculations
+ * behind each element in matrix multiplication.
+ *
+ * @param a {result of makeMatrix} the first matrix
+ * @param b {result of makeMatrix} the second matrix
+ * @param rowColors {array of strings} list of colors to apply to the
+ * rows of the first matrix
+ * @param colColors {array of strings} list of colors to apply to the
+ * columns of the second matrix
+ */
+ makeMultHintMatrix: function(a, b, rowColors, colColors) {
+ var c = [];
+ // create the new matrix
+ _.times(a.r, function() {
+ c.push([]);
+ });
+
+ // perform the multiply
+ _.times(a.r, function(i) {
+ var c1 = rowColors[i];
+ _.times(b.c, function(j) {
+ var c2 = colColors[j];
+ var temp = "";
+ _.times(a.c, function(k) {
+ if (k > 0) {
+ temp += "+";
+ }
+ var elem1 = KhanUtil.colorMarkup(a[i][k], c1);
+ var elem2 = KhanUtil.colorMarkup(b[k][j], c2);
+ temp += elem1 + "\\cdot" + elem2;
+ });
+ c[i][j] = temp;
+ });
+ });
+
+ return KhanUtil.makeMatrix(c);
+ },
+
// add matrix properties to a 2d matrix
// currently only rows and columns
makeMatrix: function(m) {
@@ -84,20 +171,20 @@ $.extend(KhanUtil, {
matrixMult: function(a, b) {
var c = [];
// create the new matrix
- for (var i = 0; i < a.r; ++i) {
+ _.times(a.r, function() {
c.push([]);
- }
+ });
// perform the multiply
- for (var i = 0; i < a.r; ++i) {
- for (var j = 0; j < b.c; ++j) {
+ _.times(a.r, function(i) {
+ _.times(b.c, function(j) {
var temp = 0;
- for (var k = 0; k < a.c; ++k) {
+ _.times(a.c, function(k) {
temp += a[i][k] * b[k][j];
- }
+ });
c[i][j] = temp;
- }
- }
+ });
+ });
// add matrix properties to the result
return KhanUtil.makeMatrix(c);
View
64 utils/qhints.js
@@ -0,0 +1,64 @@
+$.fn["qhintsLoad"] = function() {
+
+ var checkAnswer = function(parent, source) {
+ var feedback = parent.find(".qhint-feedback");
+
+ // if answer already revealed in the feedback, don't do anything
+ if (feedback.length) {
+ return;
+ }
+
+ // make a new feedback element
+ feedback = $("<p>", { "class": "qhint-feedback" });
+ var answer = $(parent.find(".qhint-answer")).text();
+ var input = parent.find(".qhint-input");
+ var userInput = "";
+
+ if (source) {
+ var type = source.attr("type");
+ if (type === "text" || type === "submit") {
+ userInput = $(parent.find("input:text")).val();
+ } else if (type === "button") {
+ userInput = $(source).val();
+ }
+ }
+
+ // hide input element and instead show the feedback element
+ input.hide();
+
+ if (!source) {
+ feedback.text(answer);
+ } else if (userInput === answer) {
+ feedback.text("Correct! The answer is " + answer + ".")
+ .addClass("correct");
+ } else {
+ feedback.text("Incorrect. The answer is " + answer + ".")
+ .addClass("incorrect");
+ }
+
+ parent.append(feedback);
+ };
+
+ var handleCheck = function(e) {
+ var parent = $(e.currentTarget).parents(".qhint");
+ checkAnswer(parent, $(e.currentTarget));
+ };
+
+ var selectors = ".qhint input:submit, .qhint input:button";
+ $("body").on("click", selectors, handleCheck);
+
+ // check hint when user presses enter
+ $("body").on("keydown", ".qhint input:text", function(e) {
+ // enter is pressed
+ if (e.keyCode === 13) {
+ handleCheck(e);
+ }
+ });
+
+ $(Khan).on("hintUsed", function() {
+ var lastQhElem = $(".qhint").last();
+ if (lastQhElem.length) {
+ checkAnswer(lastQhElem, null);
+ }
+ });
+};
Please sign in to comment.
Something went wrong with that request. Please try again.