Last active
January 3, 2020 03:08
-
-
Save jejones3141/d05687912c85bf859987a1f02dfe0ee0 to your computer and use it in GitHub Desktop.
solution to 09/20/19 Riddler Express--it's like the 10/12/18 Riddler Classic, just changing the function we're looking for a zero of.
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
import math | |
from scipy.optimize import brentq | |
import scipy.integrate as integrate | |
import matplotlib.pyplot as plt | |
# Solve the 09/20/19 Riddler Express problem on fivethirtyeight.com. | |
# This is much like the 10/12/18 Riddler Classic problem with the goatn | |
# and the circular pen; perhaps the new Riddler thinks it not all that | |
# hard, especially with the earlier problem as a guide. | |
# | |
# The problem: overlap two discs D1 and D2 of equal radius symmetrically | |
# so that the areas of D1 \ D2, D2 \ D1, and D1 ∩ D2 are all equal. | |
# | |
# So, let's place D1 and D2 in the plane. | |
# | |
# WLOG... | |
# 1. let's give them radius 1 (specified in the problem statement). | |
# 2. If d is the distance between the centers, let's put them on the plane | |
# such that the centers are at (-d/2, 0) and (d/2, 0), so they're symmetric | |
# around the X-axis. | |
# | |
# Clearly d must be greater than 0 and less than 2. | |
# | |
# Given that, note that the circles bounding the discs are precisely those | |
# you draw to construct the perpendicular bisecotor of the segment joining | |
# the centers, and therefore that perpendicular bisector is the Y-axis. They're | |
# symmetric about the Y-axis, too. | |
# | |
# From that symmetry, clearly we need only assure that the portions of the | |
# regions above the X-axis have equal area. If we just look at the first | |
# quadrant, we can see that it should suffice to show that the part of the | |
# intersection in the first quadrant has half the area of the other part. | |
# | |
# It turns out that to let everything be done with the same function to | |
# integrate, it's better to find the area of the entire region in the first | |
# quadrant and check that the area of the portion of the intersection is | |
# one-third of that. (That's trivially equivalent to the previous condition.) | |
# | |
# Once the smoke clears, the area of the whole first quadrant hunk is the | |
# integral from -d/2 to 1 of sqrt(1 - x^2) dx | |
# and that of the portion of the intersection in the first quadrant is the | |
# integral from d/2 to 1 of sqrt(1 - x^2) dx | |
# | |
# We'll pass on https://www.integral-calculator.com/ and use scipy.integrate | |
# this time--we really should have done that for the goat problem, too; | |
# it's not all that much slower, and clearer to the reader. That gets us back | |
# to scipy.optimize.brentq again. | |
# For a given choice of d, return the difference between the area of the first | |
# quadrant region as a whole and three times that of the portion of the | |
# intersection in the first quadrant. | |
def delta(d): | |
def circleY(x): return math.sqrt(1 - x**2) | |
firstQuadWhole, err1 = integrate.quad(circleY, -d / 2, 1) | |
firstQuadIntersect, err2 = integrate.quad(circleY, d / 2, 1) | |
return firstQuadWhole - 3 * firstQuadIntersect | |
def centerSeparation(): | |
return brentq(delta, 0.2, 1.8) | |
# Plot the solution. | |
def plotsoln(): | |
d = centerSeparation() | |
fig, ax = plt.subplots() | |
ax.add_artist(plt.Circle((-d / 2, 0), 1, color='#f0000060')) | |
ax.add_artist(plt.Circle((d / 2, 0), 1, color='#0000f060')) | |
plt.grid(True) | |
plt.xlim(-(1 + d / 2) - 0.25, 1 + d / 2 + 0.25) | |
plt.ylim(-1.25, 1.25) | |
plt.title('solution to 9/20/19 Riddler Express: d={0:.5f}'.format(d)) | |
plt.show() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment