import math

def total_horizontal_displacement(alpha0, speeds, widths, boundary_normal_angle):
    """
    Given an initial angle alpha0 (radians, measured relative to the layer normal),
    propagate the refraction (using Snell’s law) through the layers and compute
    the total horizontal displacement.
    
    The layers have a width (measured along the normal) given by widths[i].  
    The absolute travel direction in layer i is (boundary_normal_angle - alpha[i]).
    """
    n = len(speeds)
    alpha = [0.0] * n
    alpha[0] = alpha0
    # Propagate using Snell’s law: v_i * sin(alpha_i) = v_(i+1) * sin(alpha_(i+1))
    for i in range(n - 1):
        ratio = (speeds[i] / speeds[i+1]) * math.sin(alpha[i])
        if abs(ratio) > 1:
            return 1e9  # No real solution in this branch.
        alpha[i+1] = math.asin(ratio)
        
    horiz = 0.0
    for i in range(n):
        # Distance traveled in layer i
        L = widths[i] / math.cos(alpha[i])
        # Absolute travel angle relative to horizontal:
        theta = boundary_normal_angle - alpha[i]
        horiz += L * math.cos(theta)
    return horiz

def total_time(alpha0, speeds, widths, boundary_normal_angle):
    """
    Compute total travel time given the initial angle alpha0.
    """
    n = len(speeds)
    alpha = [0.0] * n
    alpha[0] = alpha0
    for i in range(n - 1):
        ratio = (speeds[i] / speeds[i+1]) * math.sin(alpha[i])
        if abs(ratio) > 1:
            return 1e9
        alpha[i+1] = math.asin(ratio)
        
    time = 0.0
    for i in range(n):
        L = widths[i] / math.cos(alpha[i])
        time += L / speeds[i]
    return time

def solve_snell(speeds, widths, boundary_normal_angle, target):
    """
    Uses binary search on alpha0 so that the total horizontal displacement equals the target.
    Returns the optimal alpha0 (in radians) and the corresponding total travel time.
    """
    def f(alpha0):
        return total_horizontal_displacement(alpha0, speeds, widths, boundary_normal_angle) - target
    
    low = 0.0
    high = math.radians(10)  # Start with a small guess.
    # Increase high until f(high) > 0 (i.e. horizontal displacement exceeds target)
    while f(high) < 0:
        high *= 2
        if high > math.radians(89):  # safeguard
            break
            
    # Binary search for alpha0
    for _ in range(100):
        mid = (low + high) / 2.0
        if f(mid) > 0:
            high = mid
        else:
            low = mid
    alpha_opt = (low + high) / 2.0
    t_opt = total_time(alpha_opt, speeds, widths, boundary_normal_angle)
    return alpha_opt, t_opt

def main():
    # Speeds in each layer:
    # Layers 0 and 6 represent terrain outside the marsh (10 leagues/day),
    # layers 1-5 are inside the marsh.
    speeds = [10, 9, 8, 7, 6, 5, 10]
    
    # Each layer has width 10 leagues measured along the normal to the boundaries.
    widths = [10] * 7
    
    # The marsh boundaries are oriented at 45° relative to horizontal.
    # Thus the boundary normal is at 45°.
    boundary_normal_angle = math.radians(45)
    
    # We require that the total horizontal displacement equals 100 leagues.
    target = 100.0
    
    alpha_opt, t_opt = solve_snell(speeds, widths, boundary_normal_angle, target)
    
    print("Optimal initial angle (relative to normal) = {:.6f} degrees".format(math.degrees(alpha_opt)))
    print("Total travel time = {:.13f} days".format(t_opt))
    
if __name__ == "__main__":
    main()