Как обсуждалось в комнате отдыха на переполнении стека:
Если вы не можете реализовать алгоритм Quicksort, указанный на en.wikipedia.org/wiki/Quicksort, на любом языке, на котором у вас минимальные знания, вы можете выбрать другую профессию. @sbi
но ВОО также отметил, что, возможно, BrainF *** был исключением.
Итак, вот загадка / задача: внедрить QuickSort в BrainF *** . Реализация должна
code-challenge
sorting
brainfuck
Рональд
источник
источник
Ответы:
BrainF * (697 байт)
Ниже приведена аннотированная версия. Чтобы отслеживать, что должно было происходить при разработке, я использовал примечание комментария, которое выглядит так:
|a|b=0|c=A0|@d|A0|A1|```|
Память размещена с растущим слева стеком разделов для обработки слева, пустым пространством в центре и массивом, отсортированным справа. Индексирование массива осуществляется путем перемещения «шины данных», содержащей индекс и рабочее пространство, через массив. Так, например, шина шириной 3
|i|data|0|A0|A1|A2
, станет|A0|i-1|data|0|A1|A2
после сдвига на единицу. Разбиение осуществляется путем удержания шины между верхним и нижним элементами.Вот полная версия:
источник
if (i<j) {} else {}
заняли несколько попыток, чтобы получить право. И крайние случаи - убийцы. Я не знаю, сколько раз я думал, что "только эта маленькая вещь осталась ...", а затем обнаружил контрольный пример, который заставил работать еще несколько часов. Я думаю, что могу уменьшить его на несколько десятков символов, но я не уверен, что хочу приложить усилия.Brainfuck (178 байт)
Даже если мозговитость громоздка, это помогает работать с зерном языка. Спросите себя "Должен ли я хранить это значение явно в ячейке?" Вы можете часто набирать скорость и краткость, делая что-то более тонкое. И когда значение является индексом массива (или произвольным натуральным числом), оно может не помещаться в ячейку. Конечно, вы можете просто принять это как ограничение вашей программы. Но разработка вашей программы для работы с большими значениями часто делает ее лучше другими способами.
Как обычно, моя первая рабочая версия была вдвое длиннее необходимой - 392 байта. Многочисленные модификации и два или три основных переписывания произвели эту сравнительно изящную 178-байтовую версию. (Хотя забавно, что сортировка по линейному времени составляет всего 40 байтов.)
Входные значения располагаются через каждые три ячейки: для каждой ячейки (V) alue существует (L) ячейка abel (используется для навигации) и еще одна ячейка для (S) промежуточного пространства. Общая схема массива
0 1 0 0 0 SVLSVL ... SVL 0 0 0 0 0 0 ...
Первоначально все ячейки L установлены в 1, чтобы пометить части массива, которые все еще нуждаются в сортировке. Когда мы закончим разделение подмассива, мы разделим его на более мелкие подмассивы, установив L-ячейку его сводной ячейки в 0, затем найдем крайнюю правую L-ячейку, которая по-прежнему равна 1, и разделим эту подмассив дальше. Как ни странно, это все, что нам нужно для правильной обработки рекурсивной обработки подмассивов. Когда все L ячеек были обнулены, весь массив сортируется.
Чтобы разделить подмассив, мы вытягиваем его самое правое значение в S-ячейку, чтобы он действовал как свод, и переносим его (и соответствующую пустую V-ячейку) влево, сравнивая его друг с другом в подмассиве и меняя местами при необходимости. В конце, пивот возвращается обратно, используя тот же код подкачки (который экономит 50 байтов или около того). Во время разделения две дополнительные ячейки L сохраняются равными 0, чтобы пометить две ячейки, которые, возможно, необходимо поменять местами друг с другом; в конце разбиения левый 0 слится с 0 слева от подмассива, а правый 0 в конечном итоге помечает свою точку поворота. Этот процесс также оставляет лишнюю 1 в ячейке L справа от подмассива; основной цикл начинается и заканчивается в этой ячейке.
источник