Skip to content

Instantly share code, notes, and snippets.

@armollica
Last active February 2, 2018 11:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save armollica/635bdcac377f2ac721854ccb5b66e257 to your computer and use it in GitHub Desktop.
Save armollica/635bdcac377f2ac721854ccb5b66e257 to your computer and use it in GitHub Desktop.
Missing square puzzle
height: 361

From the Nautilus magazine article The Impossible Mathematics of the Real World:

Then there’s the missing-square puzzle. In this one (above), a right triangle is cut up into four pieces. When the pieces are rearranged, a gap appears. Where’d it come from? It’s a near miss. Neither “triangle” is really a triangle. The hypotenuse is not a straight line, but has a little bend where the slope changes from 0.4 in the blue triangle to 0.375 in the red triangle. The defect is almost imperceptible, which is why the illusion is so striking.

Also see the Wikipedia page: Missing square puzzle.

<html>
<head>
<style>
svg { display: block; margin: 40px auto; }
.triangle--0 { fill: #66c2a5; stroke: rgb(71, 136, 115); }
.triangle--1 { fill: #fc8d62; stroke: rgb(176, 99, 69); }
.triangle--2 { fill: #8da0cb; stroke: rgb(99, 112, 142); }
.triangle--3 { fill: #e78ac3; stroke: rgb(162, 97, 137); }
.axis .domain { display: none; }
.axis .tick line { stroke: #ddd; }
</style>
</head>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var n = 15,
m = 7,
cellSize = 40,
width = n * cellSize,
height = m * cellSize;
var triangleData = [
{
offset: { a: [1, 1], b: [6, 3] },
vertices: [[0, 0], [8, 3], [8, 0]]
},
{
offset: { a: [9, 4], b: [1, 1] },
vertices: [[0, 0], [5, 2], [5, 0]]
},
{
offset: { a: [9, 2], b: [6, 1] },
vertices: [[0, 0], [0, 2], [5, 2], [5, 1], [2, 1], [2, 0]]
},
{
offset: { a: [9, 1], b: [9, 1] },
vertices: [[0, 0], [0, 1], [2, 1], [2, 2], [5, 2], [5, 0]]
}
];
var xScale = d3.scaleLinear().domain([0, n]).range([0, width]),
yScale = d3.scaleLinear().domain([0, m]).range([height, 0]);
var xAxis = d3.axisTop(xScale).tickValues(d3.range(0, n + 1)),
yAxis = d3.axisLeft(yScale).tickValues(d3.range(0, m + 1));
var line = d3.line()
.x(function(d) { return xScale(d[0]); })
.y(function(d) { return yScale(d[1]); });
var svg = d3.select('body').append('svg')
.attr('width', width + 1)
.attr('height', height + 1);
function translate(key) {
return function(d) {
var offset = d.offset[key],
tx = xScale(offset[0]),
ty = yScale(offset[1]);
return 'translate(' + tx + ',' + ty + ')';
};
}
function translateX(key) {
return function(d) {
var offsetX = d.offset[key],
offsetY = d.offset[key === 'a' ? 'b' : 'a'],
tx = xScale(offsetX[0]),
ty = yScale(offsetY[1]);
return 'translate(' + tx + ',' + ty + ')';
};
}
var key = 'a';
var triangle = svg.append('g').attr('class', 'triangles')
.attr('transform', 'translate(0,' + (-height) + ')')
.selectAll('.triangle').data(triangleData)
.enter().append('path')
.attr('class', function(d, i) { return 'triangle triangle--' + i; })
.attr('d', function(d) { return line(d.vertices); })
.attr('transform', translate(key));
svg.append('g').attr('class', 'axis axis--x')
.call(xAxis)
.selectAll('.tick line')
.attr('y2', height);
svg.append('g').attr('class', 'axis axis--y')
.call(yAxis)
.selectAll('.tick line')
.attr('x2', width);
function update() {
triangle
.transition()
.duration(500)
.delay(function(d, i) { return i * 750; })
.attr('transform', translateX(key))
.transition()
.duration(500)
.attr('transform', translate(key));
}
setTimeout(function() {
key = key === 'a' ? 'b' : 'a';
update();
d3.interval(function(d) {
key = key === 'a' ? 'b' : 'a';
update();
}, 5000);
}, 1000);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment