Página 1 de 1
Trocar Valores entre 2 var.... Testando a lógica!
#14
Postou 18 outubro 2008 - 21:20
Acredito que a idéia do desafio deve ser: trocar dois valores sem utilizar uma terceira variável e utilizando um algoritmo eficiente.
Dessa forma, como a imensa maioria dos algoritmos aqui apresentados não são nada eficientes, não devem ser consideradas como solução.
Pior é quando se usam funções para realizar a operação de troca. Chamada de função ocorre em tempo de execução maior e, para piorar, são criadas mais variáveis pela função chamada (assim, não houve economia de variáveis, e sim um aumento delas).
Além do que chamar uma função que resolve um problema nem sempre é resolver o problema. Na verdade quem resolveu o problema foi a função, não vocês.
A solução "boa" apresentada aqui foi:
já que ela só utiliza duas variáveis de fato (não existem funções criando outras variáveis), não há chamadas a funções, o algoritmo só utiliza três operações básicas de atribuição e retorna o valor esperado. Parabéns MadeInNordeste
Uma solução melhor é através de operadores bit-a-bit XOR.
Suponha que $a e $b sejam inteiros e que suas representações em binário sejam, respectivamente, 1001 e 0011.
O operador && (OR não bit-a-bit) é bastante conhecido. Ele converte os operandos um booleanos e faz a comparação
neste exemplo, $a é convertido pra true, $b pra true e TRUE AND TRUE = TRUE, logo, $c = TRUE.
Usamos && muito em if.
Um operador bit-a-bit é parecido, só que ele não faz a conversão para booleano. Ele compara os valores bit-a-bit.
Exemplo:
nesse exemplo, $c = 0001, pois realizamos a operação com cada um dos bits de $a e $b
olhando pro 1º algarismo de $a e $b, 1 & 0 = FALSE (0); pro segundo, 0 & 0 = 0; pro terceiro, 0 & 1 = 0; pro último, 1 & 1 = TRUE (1).
O operador XOR (^) é parecido com o OR (|), só que só retorna true se os bits comparados forem, ou o 1º TRUE, ou o segundo TRUE, mas não os dois ao mesmo tempo (por isso é chamado de OU EXCLUSIVO). Assim, 0^0=0, 1^1=0, 0^1=1, 1^0=1.
Demonstra-se matematicamente que o operador comuta ($a^$b=$b^$a), é associativo ($a^$
^$c = $a^($b^$c) e que $a^$a^ = operador identidade, isto é, $a^$a^$b = I($
= $b, isto é, é como se não existisse $a^$a^. Para entender a última propriedade, basta ver que $a ^ $a = 0, para todo $a, e que 0^$b=$b, para todo $b.
Ver este link, do site PHP.net
Além disso, a utilização desse operador é mais rápido que os operadores + e -, o que faz o algoritmo apresentado a seguir ser mais eficiente do que o algoritmo que eu falei inicialmente, mostrado por MadeInNordeste.
Essa solução pode ser até de difícil compreensão, mas está correta e é eficiente.
Agora, uma dica pra vcs. Embora seja fácil ver que a solução do MadeInNordeste está correta, sempre é bom demonstrar (e não dá um exemplo), pois tem algoritmos ineficazes que funcionam somente para alguns exemplos. Demonstrando, sabemos q o algoritmo funciona para todos os casos.
Demonstrando o algoritmo do MadeInNordeste:
Vlw galera pelo interessante problema.
-----------
Rarylson Freitas
2º Ano
Instituto Militar de Engenharia
Dessa forma, como a imensa maioria dos algoritmos aqui apresentados não são nada eficientes, não devem ser consideradas como solução.
Pior é quando se usam funções para realizar a operação de troca. Chamada de função ocorre em tempo de execução maior e, para piorar, são criadas mais variáveis pela função chamada (assim, não houve economia de variáveis, e sim um aumento delas).
Além do que chamar uma função que resolve um problema nem sempre é resolver o problema. Na verdade quem resolveu o problema foi a função, não vocês.
A solução "boa" apresentada aqui foi:
Quote
$b = $b - $a;
$a = $b + $a;
$b = $a - $b;
$a = $b + $a;
$b = $a - $b;
já que ela só utiliza duas variáveis de fato (não existem funções criando outras variáveis), não há chamadas a funções, o algoritmo só utiliza três operações básicas de atribuição e retorna o valor esperado. Parabéns MadeInNordeste
Uma solução melhor é através de operadores bit-a-bit XOR.
Suponha que $a e $b sejam inteiros e que suas representações em binário sejam, respectivamente, 1001 e 0011.
O operador && (OR não bit-a-bit) é bastante conhecido. Ele converte os operandos um booleanos e faz a comparação
Quote
$c = $a && $b;
neste exemplo, $a é convertido pra true, $b pra true e TRUE AND TRUE = TRUE, logo, $c = TRUE.
Usamos && muito em if.
Um operador bit-a-bit é parecido, só que ele não faz a conversão para booleano. Ele compara os valores bit-a-bit.
Exemplo:
Quote
$c = $a & $b; // usamos só um & quando desejamos utilizar o operador bit-a-bit
nesse exemplo, $c = 0001, pois realizamos a operação com cada um dos bits de $a e $b
Quote
1001 &
0011 =
0001
0011 =
0001
olhando pro 1º algarismo de $a e $b, 1 & 0 = FALSE (0); pro segundo, 0 & 0 = 0; pro terceiro, 0 & 1 = 0; pro último, 1 & 1 = TRUE (1).
O operador XOR (^) é parecido com o OR (|), só que só retorna true se os bits comparados forem, ou o 1º TRUE, ou o segundo TRUE, mas não os dois ao mesmo tempo (por isso é chamado de OU EXCLUSIVO). Assim, 0^0=0, 1^1=0, 0^1=1, 1^0=1.
Demonstra-se matematicamente que o operador comuta ($a^$b=$b^$a), é associativo ($a^$
Ver este link, do site PHP.net
Além disso, a utilização desse operador é mais rápido que os operadores + e -, o que faz o algoritmo apresentado a seguir ser mais eficiente do que o algoritmo que eu falei inicialmente, mostrado por MadeInNordeste.
$a = $a^$b; $b = $a^$b; // b passa a ser ($a^$b)[novo valor de $a] ^$b = $a^($b^$b)= $a^0 = $a $a = $a^$b; // a passa a ser ($a^$b)[novo valor de $a, associado na 1ª linha] ^ $a[novo valor de $b, após a segunda linha] = $a^($b^$a) = $a^($a^$b) (pela propriedade da comutatividade) = ($a^$a)^$b= 0^$b = $b
Essa solução pode ser até de difícil compreensão, mas está correta e é eficiente.
Agora, uma dica pra vcs. Embora seja fácil ver que a solução do MadeInNordeste está correta, sempre é bom demonstrar (e não dá um exemplo), pois tem algoritmos ineficazes que funcionam somente para alguns exemplos. Demonstrando, sabemos q o algoritmo funciona para todos os casos.
Demonstrando o algoritmo do MadeInNordeste:
Quote
$b = $b - $a;
$a = $b + $a; // $a = ($b-$a)[$b depois da primeira linha] + $a = $b + ($a-$a) = $b
$b = $a - $b; // $b = $b[novo valor de $a, após a segunda linha] - ($b-$a)[$b depois da primeira linha] = $b-$b+$a = $a
$a = $b + $a; // $a = ($b-$a)[$b depois da primeira linha] + $a = $b + ($a-$a) = $b
$b = $a - $b; // $b = $b[novo valor de $a, após a segunda linha] - ($b-$a)[$b depois da primeira linha] = $b-$b+$a = $a
Vlw galera pelo interessante problema.
-----------
Rarylson Freitas
2º Ano
Instituto Militar de Engenharia
#16
Postou 22 outubro 2008 - 23:39
Valew Math Man por ter colocado a solução usando XOR em uma forma mais compacta. Se ficou um pouco complicado o código dele pra alguém, vou colocar outro com praticamente a mesma velocidade de execução que é bem claro.
Vale salientar que
apresenta alguns problemas. Imagine, por exemplo, um programa em C que utiliza inteiros de 8 bits.
Sejam também
Usei $ (embora não seja o padrão do C) para manter a sintaxe do PHP.
Lembrar que em C o primeiro algarismo se refere ao sinal, assim,
Ao realizar a primeira operação, executa-se o código da direita para a esquerda e
Daí, o número resultante é maior que o maior inteiro que pode ser armazenado, o que ocorrerá em um erro.
Um erro deste tipo não acontece usando o algoritmo que usa XOR, já que o valor atribuído para $b continuará a ter 8 algarismos.
Outra observação relevante é que este algoritmo também serve para trocar variáveis de outros tipos (como string, float) sem nenhum problema.
$a ^= $b; $b ^= $a; $a ^= $b;
Vale salientar que
Quote
$b = $b - $a;
$a = $b + $a;
$b = $a - $b;
$a = $b + $a;
$b = $a - $b;
apresenta alguns problemas. Imagine, por exemplo, um programa em C que utiliza inteiros de 8 bits.
Sejam também
Quote
$a = 01111111
$b = 11001111
$b = 11001111
Usei $ (embora não seja o padrão do C) para manter a sintaxe do PHP.
Lembrar que em C o primeiro algarismo se refere ao sinal, assim,
Quote
$a = -1111111
$b = +1001111
$b = +1001111
Ao realizar a primeira operação, executa-se o código da direita para a esquerda e
Quote
-$a = +1111111
$b - $a = (+1111111) + (+1001111)
$b - $a = (+1111111) + (+1001111)
Daí, o número resultante é maior que o maior inteiro que pode ser armazenado, o que ocorrerá em um erro.
Um erro deste tipo não acontece usando o algoritmo que usa XOR, já que o valor atribuído para $b continuará a ter 8 algarismos.
Outra observação relevante é que este algoritmo também serve para trocar variáveis de outros tipos (como string, float) sem nenhum problema.
#20
Postou 25 fevereiro 2009 - 14:40
É a coisa mais fácil do mundo fazer isso..xD
<?php
$a = 100;
$b = 20;
$a = $b;
$b = $a;
?>
<?php
$a = 100;
$b = 20;
$a = $b;
$b = $a;
?>
David Ramires, em 09/02/2007 - 10:06, disse:
Galera.. beleza...
Bom tomara q ninguém me critique por colcoar esse desafio.. mas é bem interessante
dado os valores:
a = 100;
b = 20;
----------------
trocar os valores sem usar uma terceira variável... e claro o resultato é:
a = 20;
b = 100;
t+
Bom tomara q ninguém me critique por colcoar esse desafio.. mas é bem interessante
dado os valores:
a = 100;
b = 20;
----------------
trocar os valores sem usar uma terceira variável... e claro o resultato é:
a = 20;
b = 100;
t+
#28
Postou 22 outubro 2009 - 11:02
na verdade ele não conta como uma variavel, o primeiro modelo que eu fiz contava, pois eu colocava o array dentro da variavel, e jogava a variavel no list()
ai não listei os valores delimitados pelo array(), que pode ser chamado de função nativa auxiliar no caso.
ai não listei os valores delimitados pelo array(), que pode ser chamado de função nativa auxiliar no caso.
#30
Postou 22 outubro 2009 - 12:06
e mais a estrutura pode aderir mais de uma forma
no caso se eu tivesse feito
$var[] = $b
$var[] = $a
ai sim iria guardar na memória
mais como só usei
list($a,$B ) = array($b,$a);
pracitamente não guardei na memória, porque não atribui a nenhuma variavel, array(); não é uma variavel que guarda valores
tanto que eles seriam perdidos na hora, diferentemente do primeiro exemplo que sim, seria um array na variavel que estaria guardando espaço temporario na memoria
no modo que usei, utilizei a estrutura basica do array, seus indices.
no caso se eu tivesse feito
$var[] = $b
$var[] = $a
ai sim iria guardar na memória
mais como só usei
list($a,$B ) = array($b,$a);
pracitamente não guardei na memória, porque não atribui a nenhuma variavel, array(); não é uma variavel que guarda valores
tanto que eles seriam perdidos na hora, diferentemente do primeiro exemplo que sim, seria um array na variavel que estaria guardando espaço temporario na memoria
no modo que usei, utilizei a estrutura basica do array, seus indices.
#31
Postou 22 outubro 2009 - 16:41
você está se referindo ao script PHP.
Quando isso é compilado, em linguagem de máquina, o array ocupa, sim, espaço na memória. Caso contrário, seria impossível armazenar os valores. Você teria de salvá-los em cache ou em registradores do processador, o que não é possível fazer com PHP.
Quando isso é compilado, em linguagem de máquina, o array ocupa, sim, espaço na memória. Caso contrário, seria impossível armazenar os valores. Você teria de salvá-los em cache ou em registradores do processador, o que não é possível fazer com PHP.
#32
Postou 06 novembro 2009 - 12:45
Quote
pracitamente não guardei na memória, porque não atribui a nenhuma variavel, array(); não é uma variavel que guarda valores
Defina Array:
_________________________________________________________
PS: Sempre tive a visão de que um array era um espaço alocado na memória do sistema...podendo conter vários índices.
PS2: Variável "$a" é um array.
PS3: Variável é array ,logo , Array é variável.
$txt = 'abc'; echo $txt[1];//Mostra a
#33
Postou 07 novembro 2009 - 10:58
Bom, falando de arrays e troca de valores me lembrou de ordenação, então:
Saída:
function qsort( array &$m , $l = 0 , $r = null ){
$r = $r == null ? count( $m ) - 1 : $r;
$i = (int) $l; $j = (int) $r;
$p =& $m[ floor( ( $l + $r ) / 2 ) ];
if ( $i < $j ){
while ( $m[ $i ] < $p ) ++$i;
while ( $m[ $j ] > $p ) --$j;
if ( $i <= $j ){
if ( $m[ $i ] != $m[ $j ] ) $m[ $i ] ^= $m[ $j ] ^= $m[ $i ] ^= $m[ $j ];
$i++; $j--;
}
}
if ( $j > $l ) qsort( $m , $l , $j );
if ( $i < $r ) qsort( $m , $i , $r );
}
$arr = array( 1 , 8 , 3 , 5 , 7 , 2 , 6 , 9 , 4 ); qsort( $arr ); var_dump( $arr );
Saída:
Quote
array(9) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
[5]=>
int(6)
[6]=>
int(7)
[7]=>
int(8)
[8]=>
int(9)
}
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
[3]=>
int(4)
[4]=>
int(5)
[5]=>
int(6)
[6]=>
int(7)
[7]=>
int(8)
[8]=>
int(9)
}
Página 1 de 1


Entrar
Cadastre-se
Ajuda


Quote




