An Archery problem

A FiveThirtyEight Riddler puzzle.

By Vamshi Jandhyala in Riddler mathematics

January 9, 2021

Riddler Classic

Robin of Foxley has entered the FiveThirtyEight archery tournament. Her aim is excellent (relatively speaking), as she is guaranteed to hit the circular target, which has no subdivisions — it’s just one big circle. However, her arrows are equally likely to hit each location within the target.

Her true love, Marian, has issued a challenge. Robin must fire as many arrows as she can, such that each arrow is closer to the center of the target than the previous arrow. For example, if Robin fires three arrows, each closer to the center than the previous, but the fourth arrow is farther than the third, then she is done with the challenge and her score is four.

On average, what score can Robin expect to achieve in this archery challenge?

Extra credit: Marian now uses a target with $10$ concentric circles, whose radii are $1, 2, 3,$ etc., all the way up to $10$ — the radius of the entire target. This time, Robin must fire as many arrows as she can, such that each arrow falls within a smaller concentric circle than the previous arrow. On average, what score can Robin expect to achieve in this version of the archery challenge?

Computational Solution

from random import random

runs = 1000000

def avg_score_challenge1():
    total_cnt = 0
    for _ in range(runs):
        prev_pos = random()
        cnt = 1
        while(True):
            cur_pos=random()
            cnt += 1
            if cur_pos < prev_pos:
                prev_pos = cur_pos
            else:
                break
        total_cnt += cnt
    return total_cnt/runs

def avg_score_challenge2():
    n = 10
    interval_to_circle = [(i,i**2/n**2, (i+1)**2/n**2) for i in range(n)]
    def number_to_circle(p):
        for i,s,e in interval_to_circle:
            if  s < p and p < e:
                return i

    total_cnt = 0
    for _ in range(runs):
        prev_pos = number_to_circle(random())
        cnt = 1
        while(True):
            cur_pos = number_to_circle(random())
            cnt += 1
            if  cur_pos < prev_pos:
                prev_pos = cur_pos
            else:
                break
        total_cnt += cnt
    return total_cnt/runs

print(avg_score_challenge1(), exp(1))
print(avg_score_challenge2())