A spherical cap is a portion of the sphere’s surface bounded by a circle. Given a sphere of radius $R$, how many randomly-placed caps are needed on average to cover the sphere? Assume each cap measures $R/2$ across its curved surface. (See the original framing in terms of bites of an apple at the link below.)

(fivethirtyeight)

Solution

This seems to be an explored, but unsolved problem in math, and so perhaps a wee bit unfair to pose as a “Riddle!” There are published results about bounds and limits, but rather than dig into those, let’s just do a simulation and get a ballpark answer.

The simulation makes two simplifications: first, that there are a finite number of points on the surface (in particular, $500^2$), and second, that the surface is not a sphere at all but a 2-dimensional flat, square space that is wrapped around like a cylinder, except in both dimensions (like a torus topologically), so that a circle placed on it that goes past the right (or top) edge covers also part of the left (or bottom) part of the square. This surface is like a sphere in that apart from an arbitrary (in this case $(x,y)$) coordinate system, there really are no distinguished points, but its geometry is different (e.g., familiar Euclidean principles are true of its triangles, unlike those on a sphere). This makes things simpler because, unlike on a sphere, there is a very natural way to evenly populate this surface with $500^2$ points, i.e., in a $500 \times 500$ grid, and also because we can drop circles on it rather than three-dimensional caps.

We’ll randomly drop circles onto this surface, where the ratio of the area of a circle to that of the surface is the same as that of a cap to the sphere as specified in the problem.

Using the code below, the $10,000$-repetition average was about $565.4$ (and not very stable at that many reps). Surprisingly high!

from random import randint
from math import sqrt,pi,cos

resolution = 500
reps = 10000

pointsList = [(x,y) for x in range(resolution) for y in range(resolution)]

def distance(p1,p2):
  return sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)

r = sqrt((1-cos(.25))*resolution**2/(2*pi))

deltas = set([])
for x in range(int(-r),int(r+1)+1):
  for y in range(int(-r),int(r+1)+1):
    if distance((x,y),(0,0)) <= r:
      deltas.add((x,y))

accum = 0

for rep in range(reps):
  remainingPoints = set(pointsList)
  nBites = 0
  while bool(remainingPoints):
    nBites += 1
    x,y = randint(0,resolution), randint(0,resolution)
    for delta in deltas:
      pointToNuke = ( (x+delta[0])%resolution, (y+delta[1])%resolution )
      remainingPoints.discard(pointToNuke)
  accum += nBites
print("Average bites in",reps,"reps:",accum/reps)