<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def adjust_boxes(line_wave, box_widths, left_edge, right_edge, max_iter=1000, adjust_factor=0.35, factor_decrement=3.0, fd_p=0.75):
 """Ajdust given boxes so that they don't overlap. Parameters line_wave: list or array of floats Line wave lengths. These are assumed to be the initial y (wave length) location of the boxes. box_widths: list or array of floats Width of box containing labels for each line identification. left_edge: float Left edge of valid data i.e., wave length minimum. right_edge: float Right edge of valid data i.e., wave lengths maximum. max_iter: int Maximum number of iterations to attempt. adjust_factor: float Gap between boxes are reduced or increased by this factor after each iteration. factor_decrement: float The `adjust_factor` itself if reduced by this factor, after certain number of iterations. This is useful for crowded regions. fd_p: float Percentage, given as a fraction between 0 and 1, after which adjust_factor must be reduced by a factor of `factor_decrement`. Default is set to 0.75. Returns ------- wlp, niter, changed: (float, float, float) The new y (wave length) location of the text boxes, the number of iterations used and a flag to indicated whether any changes to the input locations were made or not. Notes ----- This is a direct translation of the code in lineid_plot.pro file in NASA IDLAstro library. Positions are returned either when the boxes no longer overlap or when `max_iter` number of iterations are completed. So if there are many boxes, there is a possibility that the final box locations overlap. References + http://idlastro.gsfc.nasa.gov/ftp/pro/plot/lineid_plot.pro + http://idlastro.gsfc.nasa.gov/ """

    # Adjust positions.
    niter = 0
    changed = True
    nlines = len(line_wave)

    wlp = line_wave[:]
    while changed:
        changed = False
        for i in range(nlines):
            if i > 0:
                diff1 = wlp[i] - wlp[i - 1]
                separation1 = (box_widths[i] + box_widths[i - 1]) / 2.0
            else:
                diff1 = wlp[i] - left_edge + box_widths[i] * 1.01
                separation1 = box_widths[i]
            if i < nlines - 2:
                diff2 = wlp[i + 1] - wlp[i]
                separation2 = (box_widths[i] + box_widths[i + 1]) / 2.0
            else:
                diff2 = right_edge + box_widths[i] * 1.01 - wlp[i]
                separation2 = box_widths[i]

            if diff1 < separation1 or diff2 < separation2:
                if wlp[i] == left_edge:
                    diff1 = 0
                if wlp[i] == right_edge:
                    diff2 = 0
                if diff2 > diff1:
                    wlp[i] = wlp[i] + separation2 * adjust_factor
                    wlp[i] = wlp[i] if wlp[i] < right_edge else \
                        right_edge
                else:
                    wlp[i] = wlp[i] - separation1 * adjust_factor
                    wlp[i] = wlp[i] if wlp[i] > left_edge else \
                        left_edge
                changed = True
            niter += 1
        if niter == max_iter * fd_p:
            adjust_factor /= factor_decrement
        if niter >= max_iter:
            break

    return wlp, changed, niter