Сортировка массива чисел как «Белл», «Кривая» и «Волна»

Учитывая этот список значений:

print samples

[5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0]

Мне нужно сгенерировать n количество значений для новой длины массива n . Это может быть достигнуто именно так.

for i in range(n):
        My_array.append(random.choice(samples))

Теперь My_array требуется сортировка в 5 направлениях: увеличение, уменьшение, «колокол», «кривая», «волна»,

Первые 2 могут быть достигнуты путем

print sorted(My_array,reverse=False)
[5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.0, 9.0, 9.0, 10.0]


print sorted(My_array,reverse=True)
[10.0, 9.0, 9.0, 8.0, 8.0, 7.5, 7.0, 6.5, 6.0, 5.5]

Как насчет остальных трех?

В приведенном выше примере «Белл» должен выглядеть следующим образом:

[5.5,6.5,7.0,8.0,9.0,10.0,9.0,8.0,7.5,6.0]

в то время как «Кривая» должна быть такой:

[9.0,8.0,7.0,6.5,5.5,6.0,7.5,8.0,9.0,10.0]

и «Волна» должна быть такой (это действительно неважно, если это cos-like или синусоидальная волна):

[5.5,7.0, 8.0, 10.0, 9.0,7.5, 6.0, 6.5, 8.0, 9.0]
2
добавлено отредактировано
Просмотры: 1
de
Не могли бы вы показать образец вывода для Wave с большим количеством элементов? Я имею в виду, должны ли волны всегда иметь два «колокола», или «колокола» имеют фиксированный размер и увеличиваются с количеством элементов?
добавлено автор Bakuriu, источник
Wave [9.0, 9.0, 8.5, 7.5, 6.5, 6.5, 6.0, 5.0, 5.0, 5.0, 5.5, 7.5, 7.5, 9.0, 10.0, 10.0, 10.0, 10.0, 8.5, 6.5, 6.0, 5.5, 5.0, 5.0, 5.0, 8.0, 9.0, 9.5, 9.5, 10.0] Я действительно не забочусь о формировании волны, просто нужно иметь «пики» и «минимумы»,
добавлено автор poscaman, источник

3 ответы

Для Волны вы можете следовать идее Alex L: вы делите отсортированный массив на подмассивы d , сортируете некоторые из них в порядке возрастания и другие в порядке убывания, а затем складываете их вместе:

def wave_sort(array, num_peaks=None, start_ascending=True):
    """Sorts the elements of `array` in a sine or cosine manner.

    :param array: The array to be sorted.
    :param num_peaks: The number of (low and high) peaks in the resultant array
    :param start_ascending: If True the result is sin-like, otherwise cos-like.
    """
    if num_peaks is None:
        num_peaks = len(array)//6
    sorted_ar = sorted(array)
    subarrays = [sorted_ar[i::num_peaks] for i in range(num_peaks)]
    for i, subarray in enumerate(subarrays, start=int(not start_ascending)):
        if i % 2:
            # subarrays are in ascending order already!
            subarray.reverse()
    return sum(subarrays, [])

Другим способом достижения этого было бы разделение отсортированного массива на подмассивы d/2 и для каждого подмассива получить Bell с использованием решения Alex L, а затем собрать их вместе.

3
добавлено

«Белл» может быть двумя вспомогательными массивами, один из которых сортируется, а другой уменьшается. Продолжайте эту идею по другим проблемам.

2
добавлено

Идея для Bell/Curve:

>>> ss = sorted(samples)
[5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0]
>>> ss[::2]
[5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
>>> ss[-2::-2]
[9.5, 8.5, 7.5, 6.5, 5.5]
>>> ss[-2::-2] + ss[::2]
[9.5, 8.5, 7.5, 6.5, 5.5, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]

Кроме того, если вы хотите изменить порядок массива образцов, а не ваш метод (который будет дублировать элементы)

for i in range(n):
        My_array.append(random.choice(samples))

Вы можете использовать:

>>> samples
[5.0, 5.5, 6.0, 6.5, 7.0, 7.5, 8.0, 8.5, 9.0, 9.5, 10.0]
>>> shuffled = samples
>>> random.shuffle(shuffled)
>>> shuffled
[10.0, 6.0, 5.0, 6.5, 7.5, 7.0, 8.0, 8.5, 5.5, 9.0, 9.5]

или понимание списка:

My_array = [random.choice(samples) for _ in range(n)]    
2
добавлено
Забыл добавить «образцы» в My_array.append (random.choice (образцы)). Я исправил это сейчас. My_array должен содержать n количество выборок. Кроме того, я тестирую ваш подход, и он работает. Благодаря!
добавлено автор poscaman, источник