This repository has been archived by the owner on May 11, 2021. It is now read-only.
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add exercise: Fundamental theorem of arithmetic
Reviewers: emily Reviewed By: emily Differential Revision: http://phabricator.khanacademy.org/D82
- Loading branch information
Showing
2 changed files
with
329 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,268 @@ | ||
<!DOCTYPE html> | ||
<html data-require="math math-format word-problems graphie interactive"> | ||
<head> | ||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> | ||
<title>The fundamental theorem of arithmetic</title> | ||
<script src="../khan-exercise.js"></script> | ||
</head> | ||
<body> | ||
<div class="exercise"> | ||
<div class="problems"> | ||
<div> | ||
<div class="vars"> | ||
<var id="PRIMES">[2, 3, 5, 7, 11, 13]</var> | ||
<var id="NUMBER">randFromArray([ | ||
4, 6, 8, 9, 10, 12, 14, 15, 16, 18, 20, 21, 22, 24, 25, 26, | ||
27, 28, 30, 32, 33, 35, 36, 39, 40, 42, 44, 45, 48, 49, 50, | ||
52, 54, 55, 56, 60, 63, 65, 66, 70, 72, 75, 77, 78, 80, 81, | ||
84, 88, 90, 91, 96, 98, 99]) | ||
</var> | ||
<var id="FACTORIZATION">getPrimeFactorization(NUMBER)</var> | ||
<var id="EXPONENTS">_.reduce(FACTORIZATION, function(exponents, base) { | ||
exponents[base] = exponents[base] + 1 || 1; | ||
return exponents; | ||
}, {}) | ||
</var> | ||
<var id="HAS_EXPONENTS">_.reduce(_.values(EXPONENTS), function(hasExponents, num) { | ||
return hasExponents || num !== 1; | ||
}, false) | ||
</var> | ||
<var id="EXPONENT_HINT">_.map(EXPONENTS, function(num, prime) { | ||
return cardinal(num) + " <code>" + prime + "</code>" + (num === 1 ? "" : "s"); | ||
}) | ||
</var> | ||
<var id="SOLUTION">_.reduce(PRIMES, function(factors, prime) { | ||
if (EXPONENTS[prime] > 1) { | ||
factors.push(prime + "^" + EXPONENTS[prime]); | ||
} else if (EXPONENTS[prime] === 1) { | ||
factors.push(prime); | ||
} | ||
return factors; | ||
}, []).join("\\cdot") | ||
</var> | ||
<var id="REMAINING">_.map(FACTORIZATION, function(factor, step){ | ||
var remain = NUMBER; | ||
_.each(FACTORIZATION.slice(0, step), function(n) { remain /= n; }) | ||
return remain; | ||
}) | ||
</var> | ||
<var id="GRAPHIE">null</var> | ||
</div> | ||
|
||
<p class="question"> | ||
Find the prime factorization of <code><var>NUMBER</var></code>. | ||
</p> | ||
|
||
<div class="problem"> | ||
<p> | ||
Use the arrows to change the exponent on each prime number below to see if you can find the | ||
prime factorization. | ||
</p> | ||
<div class="graphie"> | ||
// Save a reference to KhanUtil.currentGraph.graph to workaround the issue | ||
// of the custom validator depending on KhanUtil.currentGraph and | ||
// KhanUtil.currentGraph changing because of the second graphie element | ||
// in the hints. | ||
GRAPHIE = graph; | ||
|
||
init({ | ||
range: [[0, 10], [-11, 0]] | ||
}); | ||
addMouseLayer(); | ||
|
||
graph.primes = []; | ||
|
||
graph.computeTotal = function() { | ||
return _.reduce(PRIMES, function(total, prime) { | ||
return total * pow(prime, graph.primes[prime].exponent); | ||
}, 1); | ||
}; | ||
|
||
graph.totalLabel = label([7, -10], 1, "right", {fontSize: 25}); | ||
graph.updateTotal = function() { | ||
this.totalLabel.remove(); | ||
this.totalLabel = label([7, -10], graph.computeTotal(), "right", {fontSize: 25}); | ||
|
||
var answerPreview = _.reduce(PRIMES, function(answer, prime) { | ||
if (graph.primes[prime].exponent > 1) { | ||
answer.push(prime + "^" + graph.primes[prime].exponent); | ||
} else if (graph.primes[prime].exponent === 1) { | ||
answer.push(prime); | ||
} | ||
return answer; | ||
}, []).join("\\cdot"); | ||
answerPreview += " = " + graph.computeTotal(); | ||
|
||
$("#answer-preview code").text(answerPreview); | ||
MathJax.Hub.Queue(["Reprocess", MathJax.Hub, $("#answer-preview")[0]]); | ||
}; | ||
|
||
_.each(PRIMES, function(prime, y) { | ||
var yCoord = -y * 1.5 - 1; | ||
graph.primes[prime] = { | ||
exponent: 0, | ||
baseLabel: label([2, yCoord], prime, "left", {fontSize: 25, color: "#aaa"}), | ||
expLabel: label([2, yCoord + 0.3], 0, "center", {fontSize: 20, color: "#aaa"}), | ||
expandLabel: label([3, yCoord], 1, "right", {fontSize: 20, color: "#aaa"}), | ||
factorLabel: label([7, yCoord], 1, "right", {fontSize: 25, color: "#aaa"}), | ||
upArrow: addArrowWidget({ | ||
coord: [2, yCoord + 0.7], | ||
direction: "up" | ||
}), | ||
downArrow: addArrowWidget({ | ||
coord: [2, yCoord - 0.1], | ||
direction: "down" | ||
}), | ||
update: function() { | ||
this.expLabel.remove(); | ||
this.expandLabel.remove(); | ||
this.factorLabel.remove(); | ||
|
||
this.expLabel = label([2, yCoord + 0.3], this.exponent, "center", {fontSize: 20}); | ||
this.factorLabel = label([7, yCoord], pow(prime, this.exponent), | ||
"right", {fontSize: 25}); | ||
if (this.exponent === 0) { | ||
this.baseLabel.css({color: "#aaa"}); | ||
this.expLabel.css({color: "#aaa"}); | ||
this.expandLabel = label([3, yCoord], "1", "right", {fontSize: 20, color: "#aaa"}); | ||
this.factorLabel.css({color: "#aaa"}); | ||
} else { | ||
this.baseLabel.css({color: "black"}); | ||
this.expandLabel = label([3, yCoord], | ||
getPrimeFactorization(pow(prime, this.exponent)).join("\\cdot"), | ||
"right", {fontSize: 20}); | ||
} | ||
|
||
if (this.exponent >= 5 || (prime >= 11 && this.exponent >= 3)) { | ||
this.upArrow.hide(); | ||
} else { | ||
this.upArrow.show(); | ||
} | ||
|
||
if (this.exponent <= 0) { | ||
this.downArrow.hide(); | ||
} else { | ||
this.downArrow.show(); | ||
} | ||
} | ||
}; | ||
graph.primes[prime].upArrow.onClick = function() { | ||
graph.primes[prime].exponent += 1; | ||
graph.primes[prime].update(); | ||
graph.updateTotal(); | ||
}; | ||
graph.primes[prime].downArrow.onClick = function() { | ||
graph.primes[prime].exponent -= 1; | ||
graph.primes[prime].update(); | ||
graph.updateTotal(); | ||
}; | ||
|
||
label([2.5, yCoord], "=", "right", {color: "#ccc"}); | ||
label([6.5, yCoord], "=", "right", {color: "#ccc"}); | ||
graph.primes[prime].downArrow.hide(); | ||
}); | ||
|
||
line([0, -9.25], [8, -9.25]); | ||
label([0, -9], "\\times", "above right", {fontSize: 25}); | ||
</div> | ||
</div> | ||
|
||
<div class="solution" data-type="custom"> | ||
<div class="instruction"> | ||
Click the orange arrows to change your answer. | ||
<p id="answer-preview"><code>=1</code></p> | ||
</div> | ||
<div class="guess">GRAPHIE.computeTotal()</div> | ||
<div class="validator-function"> | ||
if (guess === 1) { | ||
return ""; | ||
} | ||
return guess === NUMBER; | ||
</div> | ||
<div class="show-guess"> | ||
_.each(PRIMES, function(prime) { | ||
GRAPHIE.primes[prime].exponent = 0; | ||
}); | ||
_.each(getPrimeFactorization(guess), function(prime) { | ||
GRAPHIE.primes[prime].exponent += 1; | ||
}); | ||
_.each(PRIMES, function(prime) { | ||
GRAPHIE.primes[prime].update(); | ||
}); | ||
GRAPHIE.updateTotal(); | ||
</div> | ||
<div class="show-guess-solutionarea"> | ||
_.each(PRIMES, function(prime) { | ||
GRAPHIE.primes[prime].exponent = 0; | ||
}); | ||
_.each(getPrimeFactorization(guess), function(prime) { | ||
GRAPHIE.primes[prime].exponent += 1; | ||
}); | ||
GRAPHIE.updateTotal(); | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
<div class="hints"> | ||
<div> | ||
<div class="graphie" id="factor-tree" style="float: left;"> | ||
graph.cx = 0; | ||
graph.y = 0; | ||
graph.curr = NUMBER; | ||
init({ | ||
range: [[-1, FACTORIZATION.length + 1], [-2 * FACTORIZATION.length - 0.5, 1]], | ||
scale: [30, 30] | ||
}); | ||
label([graph.cx + 1, graph.y], graph.curr); | ||
</div> | ||
<p style="height: 60px">We can use a factor tree to break <code><var>NUMBER</var></code> into its prime | ||
factorization. Which of the prime numbers divides into <code><var>NUMBER</var></code>?</p> | ||
</div> | ||
<div data-each="FACTORIZATION.slice(0, -1) as I, FACTOR"> | ||
<div class="graphie" data-update="factor-tree"> | ||
path([[graph.cx + 1, graph.y - 0.5], [graph.cx, graph.y - 1.5]]); | ||
path([[graph.cx + 1, graph.y - 0.5], [graph.cx + 2, graph.y - 1.5]]); | ||
graph.y -= 2; | ||
graph.cx += 1; | ||
graph.curr = graph.curr / FACTOR; | ||
label( [graph.cx - 1, graph.y], FACTOR, {color: BLUE} ); | ||
circle( [graph.cx - 1, graph.y], 0.5); | ||
graph.lastLabel = label( [graph.cx + 1, graph.y], graph.curr ); | ||
</div> | ||
<p style="height: 38px"> | ||
<code><var>REMAINING[I]</var></code> is divisible by <code class="hint_blue"><var>FACTOR</var></code>, | ||
leaving us with <code><var>REMAINING[I] / FACTOR</var></code>. | ||
</p> | ||
</div> | ||
<div> | ||
<div class="graphie" data-update="factor-tree"> | ||
circle( [graph.cx + 1, graph.y], 0.5); | ||
graph.lastLabel.remove(); | ||
label( [graph.cx + 1, graph.y], graph.curr, {color: BLUE} ); | ||
</div> | ||
<p> | ||
<code class="hint_blue"><var>FACTORIZATION[FACTORIZATION.length-1]</var></code> | ||
is prime, so we're done factoring. | ||
</p> | ||
</div> | ||
<div> | ||
<p> | ||
The prime factorization of <code><var>NUMBER</var></code> is: | ||
</p> | ||
<p><code class="hint_blue"> | ||
\qquad<var>FACTORIZATION.join("\\space\\color{black}{\\cdot}\\space")</var> | ||
</code></p> | ||
<div data-if="HAS_EXPONENTS"> | ||
<p> | ||
Because there <var>FACTORIZATION[0] === FACTORIZATION[1] ? "are" : "is"</var> | ||
<var>toSentence(EXPONENT_HINT)</var>, we can use exponents to write the prime factorization as: | ||
</p> | ||
<p><code>\qquad\blue{<var>SOLUTION</var>} = <var>NUMBER</var></code></p> | ||
</div> | ||
</div> | ||
</div> | ||
|
||
</div> | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters