Впорядкування масиву негативних, нульових та позитивних цілих чисел з однією ітерацією


9

Візьміть масив цілих чисел, що містять від’ємні числа, додатні числа та нулі. Згрупуйте її за допомогою однієї ітерації та встановіть на місці так, щоб першими були негативні числа, за ними всі нулі, а за ними всі додатні числа.

Приклад:

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

Зауважте, що цифри не потрібно повністю сортувати: просто сортувати за знаком.

Отже, остаточний масив буде виглядати приблизно так: -, -, ..., -, -, 0, 0, ..., 0, 0, +, +, ..., +, +

Правила

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

Переможцем стане людина, яка подасть найкоротший код (рахується в байтах), який змінює початковий масив у правильний формат (як описано вище).



@PeterTaylor Thx, тепер я розумію, у чому завдання!
randomra

Саме цей codegolf.stackexchange.com/questions/504/… окрім використання 1 ітерації та обмеження на 1 масив.
Оптимізатор

Вбудовані функції сортування заборонені, правда?
KSFT

1
@KSFT Виклик sort(...)не є гарним, оскільки, ймовірно, робить більше, ніж одну ітерацію.
Ionică Bizău

Відповіді:


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;
}

Я спробував це в Code Blocks і він не компілюється, є 3 помилки. Що ви склали? x * не визначено, і ви зробили змінні до {.
bacchusbeale

@bacchusbeale Ви можете компілювати його з gcc у режимі за замовчуванням (C89). CodeBlocks не є компілятором, тому я не можу сказати, який компілятор ви використовуєте, але він працює з gcc. Причиною, що вона може працювати не з усіма компіляторами, є декларації у стилі K&R, які не відповідають стандарту ANSI.
feersum

1

СТАТА 242

Точно дотримується сторінки вікіпедії. Дякуємо @PeterTaylor

Вводить введення як розділений пробілом набір чисел від std у та виводить як такий, а також для виведення std.

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
}

1

Пітон 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

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;}

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);

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]

Насправді, якщо не потрібно було повертати масив (тобто просто модифікувати), тоді ви можете збрити ще один знак.


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;
}

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/

Пояснення:

Це ще одна реалізація алгоритму з wikipedia, використовуючи 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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.