Skip to content

Instantly share code, notes, and snippets.

@mimno
Last active July 14, 2017 13:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mimno/d6b34ad78b8038de05c7073c76aa438c to your computer and use it in GitHub Desktop.
Save mimno/d6b34ad78b8038de05c7073c76aa438c to your computer and use it in GitHub Desktop.
Monte Carlo sampling for 538 riddler (pizza slices)

A Monte Carlo approximation of the area of overlap between two circles, inspired by this 538 riddler question. Sample random points in a rectangle and see which circle(s) they fall into. If "both" is more than half of "left" or "right", chooose the middle slices.

<html>
<head>
<link href='http://fonts.googleapis.com/css?family=Open+Sans' rel='stylesheet' type='text/css'>
<script src="http://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<style>body { font-family: "Open Sans"; margin: 30px; } div#float { float: right; width: 20%; }
svg { background-color: #eee; }
</style>
</head>
<body>
<h3>Which pizza slice?</h3>
<div id="float">A Monte Carlo approximation of the area of overlap between two circles, inspired by <a href="https://fivethirtyeight.com/features/can-you-eat-more-pizza-than-your-siblings/">this 538 riddler question</a>. Sample random points in a rectangle and see which circle(s) they fall into. If "both" is more than half of "left" or "right", chooose the middle slices.</div>
<div><button id="sampleButton">Sample</button> <input type="text" id="numPoints" value="1000" /> points.</div>
<svg height="400" width="600"></svg>
<div>
<script>
var svg = d3.select("svg");
var height = svg.attr("height");
var width = svg.attr("width");
var categories = ["left", "right", "both", "neither"];
var xScale = d3.scaleLinear().domain([-0.3,3.3]).range([0, width]);
var yScale = d3.scaleLinear().domain([-0.3,2.3]).range([height, 0]);
var colorScale = d3.scaleOrdinal(d3.schemeCategory10).domain(categories);
var texts = svg.selectAll("text").data(categories).enter().append("text")
.attr("x", 5)
.attr("y", function (d, i) { return 20 + 20 * i; });
var randomPoint = function () {
return { x: Math.random() * 3, y: Math.random() * 2 };
};
var insideLeftCircle = function (point) {
var x = point.x - 1;
var y = point.y - 1;
return x * x + y * y < 1.0;
};
var insideRightCircle = function (point) {
var x = point.x - 2;
var y = point.y - 1;
return x * x + y * y < 1.0;
};
var counts = { "left": 0, "right": 0, "both": 0, "neither": 0 };
function sample() {
var numPoints = d3.select("#numPoints").property("value");
for (var i = 0; i < numPoints; i++) {
var point = randomPoint();
var inLeft = insideLeftCircle(point);
var inRight = insideRightCircle(point);
var hit = "neither";
if (inLeft && inRight) { hit = "both"; }
else if (inLeft) { hit = "left"; }
else if (inRight) { hit = "right" }
counts[hit] += 1;
svg.append("circle")
.attr("cx", xScale(point.x))
.attr("cy", yScale(point.y))
.attr("r", 2)
.style("opacity", 0.25)
.style("fill", colorScale(hit));
}
texts.text(function (d) { return d + ": " + counts[d]; });
}
d3.select("#sampleButton").on("click", sample);
</script>
</div>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment