Resposta do Desafio do dia / 2

20 04 2007

Resposta do Desafio do dia / 2

Vamos por partes:

Um dos objetivos deste desafio era demonstrar que blocos de códigos podem ser utilizados em qualquer parte, e não apenas em estruturas de controle, decisão, etc. O seguinte trecho de código é perfeitamente válido e funcional (apesar de “estranho”)

<?php
  
{
      
$foo ‘foo’;
      echo 
$foo;
  }

Como pode se observar no desafio, coloquei o código em diversos blocos, mas apenas para isso: Demonstrar que é possível utilizar em qualquer lugar. Para resolução do desafio, é indispensável conhecimento de operações bit-a-bit. Como não é todo mundo que tem esse conhecimento, um outro objetivo do desafio era despertar a curiosidade de quem não soubesse e quisesse resolver e também falar um pouco sobre isso (na resposta). Segue agora então o mesmo código, comentado, com a resposta do desafio:


<?php
  
// desafio2.php

  // para acompanhar, segue alguns numeros binarios:
  //
  // 000 0
  // 001 1
  // 010 2
  // 011 3
  // 100 4
  // 101 5
  // 110 6
  // 111 7
  // iniciamos $x com valor 2
  $x 2;
  {
    
// aqui temos também um pequeno truque:
    // print é utilizado para exibir uma mensagem,
    // e sempre retorna 1. Logo, sera exibida a
    // mensagem ‘Iniciando ‘ e $x sera incrementado
    // em 1. Neste momento temos:
    // $x = 3
    
$x += print(‘Iniciando ‘);
    {
        
// aqui sera exibido ‘desafio 2’
        
echo ‘desafio 2’;
        
        
// aqui temos a primeira operacão bit-a-bit,
        // um ‘left shift’ de $x em 1 passo. Vejamos
        // o que tinhamos e o que sera retornado para $y
        // 
        // $x = 011 (3)
        //
        // deslocando 1 bit a esquerda teremos 110 (6)
        //
        // nesse momento temos:
        //
        // $x = 3 (nao modificamos $x)
        // $y = 6
        
$y $x << 1;
    }
    
// aqui são feitas várias operações. Vamos começar
    // pelas mais internas e com maior prioridade:
    //
    // $y^$x
    //
    // Aqui temos um $y xor $x. XOR – exclusive or – retornará
    // os bits que estão ativos em $y e os que estão ativos
    // em $x,  mas não os que estão ativos em ambos: veja:
    //
    // $x = 011
    // $y = 110
    // —- 101
    //
    // observe que como o segundo bit estava ativo em ambos,
    // ele nao estara ativo na saída. Entao após esta operação, 
    // o retorno será 5 (101)
    //
    // logo após esta operação, temos um “not”:
    //
    // ~($y^$x), ou seja ~(5) ou ~5.
    //
    // aqui ocorre uma inversão de cada bit: Os que estão ativos
    // serão desativados e os que estão desativados serão ativados:
    //
    // 5 – 101
    // — 010
    //
    // o resultado desta operação então seria 2 (010)
    //
    // Mas tem um pequeno “problema”: A operacao deve ser feita em
    // todos os bits. Logo, ~5 = 11111111111111111111111111111010 e
    // 11111111111111111111111111111010 = -6
    //
    // temos entao que o resultado da operacao ~($y^$x) = -6
    // o resultado disso tudo é retornado por sprintf.
    // 
    // Aproxima operação, por ordem dos operadores, é $y + (-6), ou 
    // seja $y + sprintf(‘%d’,~($y^$x)). Isso porque o operador ‘+’ tem
    // precedência ante ao ‘|’. Então temos
    //
    // $6 + (-6) = 0
    //
    // apos isto, temos “$x | 0”. Aqui o os bits que estão ativos ou 
    // em $x ou em 0 (ou ambos, diferentemente do xor) estarão ativos na
    // saída. Como 0 não tem bits ativos, o resultado da operação sera o
    // própio valor de $x:
    //
    // $x = 011
    // 0  = 000
    // —- 011 (3)
    //
    // finalmente, temos que $y = 3
    //
    // ao final disso entao:
    //
    // $x = 3
    // $y = 3
    
$y $x $y sprintf(‘%d’,~($y^$x));

    // apenas exibimos um “\n”. O $z não é utilizado mais
    
$z = print(“\n”);
    
    
// verificamos se $x é menor do que $y (não é)
    
if ($x $y) {
        
$x ^= $x;
    
// observe que aqui não temos um else. Então esse trecho
    // será executado de qualquer forma (mesmo que o if anterior
    // fosse verdadeiro. Foi utilizado apenas para “confundir” : )
    
} {
        
// Fazemos um xor de $y em $y. Lembre-se que no xor, o retorno
        // são os bits que estão ativos ou em um ou em outro número, mas
        // não em ambos. Como o xor está sendo feito no mesmo número, o que
        // estiver ativo em um também estará ativo em outro. Logo, o retorno
        // será 0 (este tipo de operação é bastante utilizada em assembly, 
        // quando se deseja zerar o valor de algum registrador: “xor eax, eax”
        // “xor ebx, ebx”, …)
        //
        // $y = 011
        // $y = 011
        // —- 000
        //
        //
        
$y ^= $y;
    
// novamente utilizamos um bloco, que será executado de qualquer forma
    
} {
        
// verificamos se $x (3) é maior do que $y (0). Como sabemos que é,
        // será exibido ‘$y menor do que $x’
        
if ($x $y) {
            echo 
‘$y menor do que $x’;
        
// e este trecho será ignorado : )
        
} else {
            echo 
‘$y maior do que $x’;
        }
    }
  }
  
// finalmente, exibimos um último “\n”
  
echo “\n”;
?>

Ao final disso, temos então:

Iniciando desafio 2
$y menor do que $x

É isso, espero que tenha aprendido um pouco sobre bitwise operations neste desafio.

Anúncios

Ações

Information

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s




%d blogueiros gostam disto: