def ideal_spectrum(peptide: list, cyclic: bool) -> list:
    """Finds the ideal spectrum of a peptide

    :param peptide: the peptide (with amino masses in order)
    :type peptide: list (of ints)
    :param cyclic: whether to include cyclic sub-peptides
    :type cyclic: bool
    :returns: all observed weights in the ideal spectrum, least->greatest
    :rtype: list (of ints)
    """

    cum_mass = [0]
    mass_len = 1
    # fill cum_mass with the cumalitive mass of peptide prefixes
    for mass in peptide:
        cum_mass.append(cum_mass[mass_len - 1] + mass)
        mass_len += 1

    # the empty peptide is included in the spectrum
    spect = [0]
    # for every pair of cum_mass values, add difference to spect
    spect += [cum_mass[j] - cum_mass[i]
             for i in range(mass_len) for j in range(i + 1, mass_len)]

    if cyclic:
        # the final cumalative mass value is simply the total mass
        total_mass = cum_mass[mass_len - 1]
        # for every pair of cum_mass values that doesn't contain an end
        # add the cyclic peptide, or the total mass minus the above difference
        spect += [total_mass - (cum_mass[j] - cum_mass[i])
                  for i in range(1, mass_len)
                  for j in range(i + 1, mass_len - 1)]

    spect.sort()
    return spect