Просмотр полной версии : [Вопрос] Упорядочить массив
Как переставить нули в конец массива? Для этого нужен двойной цикл?
Сделал так, но сомневаюсь, что правильно
main() {
const
size = 5;
static
m[size] = {0, 8, 0, 3, 1};
for (new i = 0; i < size; i++)
{
if (m[i] == 0)
{
for (new j = i; j < size; j++)
{
if (m[j] != 0)
{
m[i] = m[j];
m[j] = 0;
break;
}
}
}
printf("%i", m[i]);
}
}
new arr[] = {1,0,6,2,1,0,0,1,1,2};
new cnt = 0, i = 0, c;
while (i<sizeof(arr)) {
c = arr[i++];
if (c == 0)
continue;
arr[cnt++] = c;
}
while (cnt < n) {
arr[cnt++] = 0;
}
Возможно поможет алгоритмы сортировки (https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%81%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B8)
Возможно поможет алгоритмы сортировки (https://ru.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D1%81%D0%BE%D1%80%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%BA%D0%B8)
Действительно, можно сделать сортировку по убыванию. Однако на сортировку уходит достаточно приличное время, чем на код, который я предоставил выше.
Daniel_Cortez
05.02.2019, 00:27
new arr[] = {1,0,6,2,1,0,0,1,1,2};
new cnt = 0, i = 0, c;
while (i<sizeof(arr)) {
c = arr[i++];
if (c == 0)
continue;
arr[cnt++] = c;
}
while (cnt < n) {
arr[cnt++] = 0;
}
Код в целом оптимальный, но первый цикл можно было скомпоновать чуть удачнее:
do {
if ((c = arr[i++]) != 0)
arr[cnt++] = c;
} while (++i < sizeof(arr));
Во-первых, do-while подходит больше, т.к. размер массива не может быть меньше 1. Бонусом вместо 3 джампов (1-й в самом начале цикла, после проверки условия выхода, 2-й в виде continue и 3-й в конце тела цикла while) получаем всего 2 (1-й в виде if и 2-й после проверки условия выхода из do-while).
Во-вторых, присваивание в переменную 'c' перемещено в выражение внутри if, чтобы вместо 2 обращений к 'c' (запись в 'c', затем оттуда же чтение) было всего 1 (сначала запись значения в 'c', а затем "повторное использование" того же значения в проверке на равенство нулю, вместо того чтобы заново считывать его из 'c').
(На самом деле даже это не самый удачный вариант цикла, просто те 2 оптимизационных приёма было проще всего объяснить.)
Делаю, чтобы из диалогового окна пропадал выбранный вариант. Для этой задачи этого может хватить. Игрок не может сразу выбрать 2 пункта.
main()
{
const
size = 5;
new
m[size] = {1, 8, 2, 0, 3},
index_i;
for (new i = 0; i < size; i++)
{
if (m[i] == 0)
{
index_i = i == size - 1 ? 0 : 1;
m[i] = m[i+index_i];
m[i+index_i] = 0;
}
printf("%i", m[i]);
}
}
Код в целом оптимальный, но первый цикл можно было скомпоновать чуть удачнее:
do {
if ((c = arr[i++]) != 0)
arr[cnt++] = c;
} while (++i < sizeof(arr));
Во-первых, do-while подходит больше, т.к. размер массива не может быть меньше 1. Бонусом вместо 3 джампов (1-й в самом начале цикла, после проверки условия выхода, 2-й в виде continue и 3-й в конце тела цикла while) получаем всего 2 (1-й в виде if и 2-й после проверки условия выхода из do-while).
Во-вторых, присваивание в переменную 'c' перемещено в выражение внутри if, чтобы вместо 2 обращений к 'c' (запись в 'c', затем оттуда же чтение) было всего 1 (сначала запись значения в 'c', а затем "повторное использование" того же значения в проверке на равенство нулю, вместо того чтобы заново считывать его из 'c').
(На самом деле даже это не самый удачный вариант цикла, просто те 2 оптимизационных приёма было проще всего объяснить.)
Можно было вообще вот так сделать:
while ((i < sizeof(arr)) && (c = arr[i++]))
arr[cnt++] = c;
Запихивать операцию присваивания в условый оператор - не лучшая затея. А вообще плохо, что компилятор глуп на такие оптимизации.
Daniel_Cortez
06.02.2019, 16:36
А вообще плохо, что компилятор глуп на такие оптимизации.
Это простой компилятор для простого скриптового языка, а не какой-то там "комбайн" на основе LLVM. Абсолютно ничего необычного.
Это простой компилятор для простого скриптового языка, а не какой-то там "комбайн" на основе LLVM. Абсолютно ничего необычного.
И без LLVM компиляторы пишутся. Причем такая конструкция проста для простого компилятора для простого скриптового языка. В нем же поддерживаются шаблоны инструкций для оптимизации.
Daniel_Cortez
06.02.2019, 19:04
Делаю, чтобы из диалогового окна пропадал выбранный вариант. Для этой задачи этого может хватить. Игрок не может сразу выбрать 2 пункта.
main()
{
const
size = 5;
new
m[size] = {1, 8, 2, 0, 3},
index_i;
for (new i = 0; i < size; i++)
{
if (m[i] == 0)
{
index_i = i == size - 1 ? 0 : 1;
m[i] = m[i+index_i];
m[i+index_i] = 0;
}
printf("%i", m[i]);
}
}
Так а зачем нужно тратить время на перестановку элементов, когда можно одним циклом найти ноль, а другим просто скопировать последующие элементы на место предыдущего и обнулить последний элемент?
main()
{
static arr[] = {1, 8, 2, 0, 3};
new i = 0;
do {
if (arr[i] == 0)
{
do {
arr[i] = arr[++i];
} while (i < sizeof(arr) - 1);
arr[sizeof(arr) - 1] = 0;
break;
}
} while (++i < sizeof(arr) - 1);
}
И без LLVM компиляторы пишутся. Причем такая конструкция проста для простого компилятора для простого скриптового языка. В нем же поддерживаются шаблоны инструкций для оптимизации.
Новые оптимизации никто не добавит - боятся сломать хаки в чьём-нибудь инклуде. Собственно, слова про "ничего необычного" были про сам компилятор, про развиваемый сообществом SA-MP форк (https://github.com/pawn-lang/compiler) разговор отдельный.
Powered by vBulletin® Version 4.2.0 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot