Ordenando uma matriz de números negativos, zero e positivos com uma iteração

9

Pegue uma matriz de números inteiros contendo números negativos, números positivos e zeros. Agrupe-o com uma iteração e no lugar para que todos os números negativos cheguem primeiro, seguidos por todos os zeros, seguidos por todos os números positivos.

Exemplo:

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

Observe que os números não precisam ser totalmente classificados: apenas classificados por sinal.

Portanto, a matriz final ficará assim: -, -, ..., -, -, 0, 0, ..., 0, 0, +, +, ..., +, +

Regras

  • Você só pode usar a matriz de entrada e uma quantidade constante de memória adicional (ou seja, você não pode criar mais matrizes)
  • Você pode usar apenas um loop, que pode executar apenas quantas vezes o comprimento da matriz. Você não pode usar funções internas que ocultam qualquer tipo de loop. Isso inclui funções de classificação internas.
  • O resultado deve estar no formato que descrevi

O vencedor será a pessoa que enviará o código mais curto (contado em bytes) que altera a matriz inicial para um formato correto (como descrito acima).

Ionică Bizău
fonte
6
Também conhecido como problema da bandeira nacional holandesa .
Peter Taylor
@ PeterTaylor Thx, agora entendo qual é a tarefa!
randomra
Exatamente este codegolf.stackexchange.com/questions/504/… diferente do uso 1 iteração e 1 limite da matriz.
Optimizer
Funções de classificação incorporadas não são permitidas, certo?
KSFT
11
A chamada @KSFT sort(...)não é boa, pois provavelmente faz mais de uma iteração.
Jonic Biz

Respostas:

3

C, 92

Provavelmente, isso pode ser reduzido em pelo menos 10 bytes; há muitas expressões desperdiçadas.

O primeiro argumento deve apontar para o início da matriz; o segundo deve apontar após o final da matriz.

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

Sem jogar com gerador de teste aleatório:

*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
fonte
Eu tentei isso no Code Blocks e ele não compila, há 3 erros. Com o que você compilou? x * não está definido e você criou variáveis ​​antes de {.
bacchusbeale
@bacchusbeale Você pode compilá-lo com o gcc no modo padrão (C89). O CodeBlocks não é um compilador, então não sei dizer qual compilador você está usando, mas funciona com o gcc. O motivo pelo qual ele pode não funcionar com todos os compiladores são as declarações no estilo K&R, que não estão em conformidade com o padrão ANSI.
feersum
1

STATA 242

Segue a página da Wikipedia exatamente. Obrigado @PeterTaylor

Leva a entrada como um conjunto de números separados por espaço, de entrada padrão e saída, como tal, para saída padrão.

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
}
marcações
fonte
1

Python 2: 116 bytes

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

Esta é uma tradução em Python do pseudo-código da bandeira nacional holandesa.

Possíveis 112 bytes

Não tenho certeza, se isso for permitido. Ele cria uma segunda matriz de tamanho 3 (quantidade constante de memória adicional!).

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
fonte
1

C, 90

Implementação direta do algoritmo no artigo da Wikipedia, de acordo com o comentário de Peter Taylor sobre a questão.

Espera encontrar os dados em uma matriz chamada acomo a outra resposta C. n, pe zsão indicadores para a inserção de números e zeros negativos e positivos. ne psão tomados como argumentos apontando para o primeiro e o último elementos dos dados.

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;}
Level River St
fonte
1

ECMAScript 157 Bytes

Pega os números como um conjunto separado por espaço ou por vírgula em um diálogo de prompt e retorna o resultado com um diálogo de alerta.

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
fonte
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

A sintaxe da variável relativamente detalhada do PHP é um pouco dolorosa aqui ...

Stephen
fonte
0

Rebol - 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

Esta é uma porta direta do pseudocódigo da wikipedia da bandeira nacional holandesa. Abaixo está como parece não-destruído:

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

Exemplo de uso:

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

NB Matrizes Rebol (blocos) não usam vírgulas -[5 3 0 -6 2 0 5]

E se estiver OK, envolva isso em uma função que pega uma matriz e a modifica no local, então podemos reduzi-lo para 128 caracteres:

>> 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]

De fato, se não for necessário retornar a matriz (ou seja, apenas modificar), você poderá cortar mais 1 caractere.

draegtun
fonte
0

C ++

Solução sem golfe: n conta os negativos adicionados à frente da matriz. Para cada elemento, se troca negativa com o elemento em n, se troca zero com o elemento em n + 1, troque com o último elemento.

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
fonte
0

CJam - 72 67

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

Entrada: [5 3 4 0 -6 2 0 5]
Saída:[-6 0 0 4 2 3 5 5]

Experimente em http://cjam.aditsu.net/

Explicação:

Esta é outra implementação do algoritmo da wikipedia, usando Tfor ie Ufor j(ambos inicializados automaticamente em 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
aditsu sair porque SE é MAU
fonte