Упорядочение массива целых чисел с отрицаниями, нулями и положительными числами за одну итерацию

9

Возьмите массив целых чисел, содержащий отрицательные числа, положительные числа и нули. Сгруппируйте его с одной итерацией и поместите так , чтобы все отрицательные числа шли первыми, за которыми следовали все нули, а затем все положительные числа.

Пример:

Input:  5, 3, 0, -6, 2, 0, 5
Output: -6, 0, 0, 3, 2, 5, 5

Обратите внимание, что числа не должны быть полностью отсортированы: просто отсортированы по знаку.

Итак, окончательный массив будет выглядеть так: -, -, ..., -, -, 0, 0, ..., 0, 0, +, +, ..., +, +

правила

  • Вы можете использовать только входной массив и постоянный объем дополнительной памяти (т.е. вы не можете создавать больше массивов)
  • Вы можете использовать только один цикл, который может выполняться только столько раз, сколько длина массива. Вы не можете использовать встроенные функции, которые скрывают какой-либо цикл. Это включает в себя встроенные функции сортировки.
  • Результат должен быть в формате, который я описал

Победителем станет тот, кто предоставит самый короткий код (в байтах), который изменит исходный массив в правильный формат (как описано выше).

Ионика Бизэу
источник
@PeterTaylor Спасибо, теперь я понимаю, в чем задача!
рандома
Именно этот codegolf.stackexchange.com/questions/504/… кроме использования 1 итерации и 1 предела массива.
Оптимизатор
Встроенные функции сортировки не допускаются, верно?
KSFT
1
@KSFT Вызов sort(...)не подходит, поскольку, вероятно, он выполняет более одной итерации.
Ионика Бизэ

Ответы:

3

С 92

Вероятно, это может быть уменьшено как минимум на 10 байт; Есть много выражений, которые пропадают.

Первый аргумент должен указывать на начало массива; вторая должна указывать после конца массива.

*x;f(b,e)int*b,*e;{for(x=b;x<e;x++)*x>0&&--e-x?*x--^=*e^=*x^=*e:*x<0?b-x?*x^=*b=*x:0,b++:0;}

Развернутый с генератором случайных испытаний:

*x;
f(b,e)int*b,*e;{
    for(x=b;x<e;x++) {
        if(*x<0) {
            if(b == x)
                b++;
            else
                *b++ = *x, *x=0;
        } else if(*x>0 && x != --e) {
            *x^=*e^=*x^=*e;
            x--;
        }
    }
}

int main()
{
    int a[999];
    srand(time(0));
    int n = rand() % 50;
    int i;
    for(i = 0; i < n; i++) printf("%d ", a[i] = rand() % 9 - 4);
    f(a, a+n);
    puts("");
    for(i = 0; i < n; i++) printf("%d ", a[i]);
    return 0;
}
feersum
источник
Я пробовал это в Code Blocks, и он не компилируется, есть 3 ошибки. Что вы скомпилировали? x * не определен, и вы сделали переменные до {.
bacchusbeale
@bacchusbeale Вы можете скомпилировать его с помощью gcc в режиме по умолчанию (C89). CodeBlocks не является компилятором, поэтому я не могу сказать, какой компилятор вы используете, но он работает с gcc. Причина, по которой он может работать не со всеми компиляторами, - объявления в стиле K & R, которые не соответствуют стандарту ANSI.
feersum
1

STATA 242

Точно следует за страницей википедии. Спасибо @PeterTaylor

Принимает ввод как разделенный пробелами набор чисел из стандартного ввода и выводит их как таковые, а также выводит стандартный вывод.

di _r(a)
token $a//converts to array (kind of)
loc i=0
loc j=0
loc q=wordcount($a)
loc n=`q'-1
while `j'<=`n' {
loc t=``j''
if `t'<0{
loc `j'=``i''
loc `i'=`t'
loc ++i
loc ++j
}
else if `t'>0{
loc `j'=``n''
loc `n'=`t'
loc --n
}
else
loc ++j
}
//used only to output
forv x=1/`q'{
di ``x'' _c
}
bmarks
источник
1

Python 2: 116 байт

a=input();i=j=0;n=len(a)
while j<n:b=a[j];r,s=b<0,b>0;c=i*r+n*s-s+j*(b==0);a[c],a[j]=b,a[c];i+=r;n-=s;j+=b<1
print a

Это переведенный на Python перевод голландского национального флага с псевдокодом.

Возможные 112 байтов

Не уверен, если это разрешено. Создает второй массив размером 3 (постоянный объем дополнительной памяти!).

a=input();i=j=0;n=len(a)-1
while j<=n:b=a[j];k=(i,j,n)[cmp(b,0)+1];a[k],a[j]=b,a[k];i+=b<0;n-=b>0;j+=b<1
print a
Jakube
источник
1

С, 90

Простая реализация алгоритма в статье в википедии согласно комментарию Питера Тейлора по этому вопросу.

Ожидает найти данные в массиве, называемом aкак другой ответ C. n, pИ zявляются указателями для вставки отрицательных и положительных чисел и нулей. nи pпринимаются в качестве аргументов, указывающих на первый и последний элементы данных.

f(n,p){int t,z;for(z=n;p-z;z++)(t=a[z])?a[z]>0?a[z]=a[p],a[p--]=t:(a[z]=a[n],a[n++]=t):0;}
Уровень реки St
источник
1

ECMAScript 157 байт

Принимает числа как разделенные пробелами или запятыми набор из диалогового окна приглашения и возвращает результат с диалоговым окном предупреждения.

for(v=prompt().split(/,?\s+/),s=function(j,n){t=v[j],v[j]=v[n],v[n]=t},i=j=0,n=v.length-1;j<=n;)
!(~~v[j]<0&&!s(i++,j++)||~~v[j]>0&&!s(j,n--))&&j++;alert(v);
fxdapokalypse
источник
0

PHP (146)

function f($s){for($i=0,$n=count($s)-1;$j++<=$n;)if($k=$s[$j]){$l=$k>0?n:i;$x=$s[$$l];$s[$$l]=$k;$s[$j]=$x;$k>0?$n--|$j--:$i++;}echo print_r($s);}

http://3v4l.org/ivRX5

Относительно многословный синтаксис PHP здесь немного болезненный ...

Стивен
источник
0

Реболь - 149 142 140

a: to-block input i: j: 1 n: length? a while[j <= n][case[a/:j < 0[swap at a ++ i at a ++ j]a/:j > 0[swap at a j at a -- n]on[++ j]]]print a

Это прямой порт голландского национального флага в псевдокоде Википедии. Ниже показано, как это выглядит безымянным:

a: to-block input
i: j: 1
n: length? a

while [j <= n] [
    case [
        a/:j < 0 [swap at a ++ i at a ++ j]
        a/:j > 0 [swap at a j at a -- n]
        on       [++ j]
    ]
]

print a

Пример использования:

rebol dutch-flag.reb <<< "5 3 0 -6 2 0 5"
-6 0 0 2 3 5 5

NB. Массивы Rebol (блоки) не используют запятые -[5 3 0 -6 2 0 5]

И если все в порядке, то это превращает это в функцию, которая принимает массив и модифицирует его на месте, тогда мы можем уменьшить его до 128 символов:

>> f: func[a][i: j: 1 n: length? a while[j <= n][case[a/:j < 0[swap at a ++ i at a ++ j]a/:j > 0[swap at a j at a -- n]on[++ j]]]n]

>> array: [5 3 0 -6 2 0 5]
== [5 3 0 -6 2 0 5]

>> print f array
-6 0 0 2 3 5 5

>> ;; and just to show that it as modified array

>> array
== [-6 0 0 2 3 5 5]

Фактически, если вам не нужно возвращать массив (т.е. просто изменять), вы можете сбрить еще 1 символ.

draegtun
источник
0

C ++

Решение без игры в гольф: n считает негативы, добавленные к передней части массива. Для каждого элемента, если отрицательный обмен с элементом в n, если нулевой обмен с элементом в n + 1, иначе обмен с последним элементом.

void p(int* k,int n)
{
for(int i=0;i<n;i++)
{
cout<<*(k+i)<<' ';
}
cout<<endl;
}

void s(int *x,int i,int j)
{
int t=*(x+j);
*(x+j)=*(x+i);
*(x+i)=t;
}
void f(int *x,int L)
{
int n=0;
int k;
for(int i=1;i<L;i++)
{
k=*(x+i);
if(k<0)
{
s(x,i,n);
n++;
}
else if(k==0)
{
s(x,i,n+1);
}
else if(k>0)
{
s(x,i,L-1);
}
}
}

int main()
{
int x[]={5,2,-1,0,-2,4,0,3};
f(x,8);
p(x,8);
return 0;
}
bacchusbeale
источник
0

CJam - 72 67

q~_,(:N;{_U=:B0>{U1$N=tNBtN(:N;}{B{U1$T=tTBtT):T;}{}?U):U;}?UN>!}gp

Вход: [5 3 4 0 -6 2 0 5]
Выход:[-6 0 0 4 2 3 5 5]

Попробуйте это на http://cjam.aditsu.net/

Объяснение:

Это еще одна реализация алгоритма из Википедии, использующая Tдля iи Uдля j(оба автоматически инициализируются в 0).

q~                    read and evaluate the array (let's call it "A")
_,(:N;                keep A on the stack and set N ← size of A - 1  
{                     do...  
    _U=:B             keep A on the stack and set B ← A[U] (also leaving B on the stack)  
    0>{               if B > 0
        U1$N=t        A[U] ← A[N]
        NBt           A[N] ← B
        N(:N;         N ← N - 1
    }{                else
        B{            if B ≠ 0
            U1$T=t    A[U] ← A[T]
            TBt       A[T] ← B
            T):T;     T ← T + 1
        }{            else (do nothing)
        }?            end if
        U):U;         U ← U + 1
    }?                end if
UN>!}g                ...while not (U > N)
p                     print representation of A
уйти, потому что SE это зло
источник