quarta-feira, 30 de maio de 2012

Combinações de dígitos II

Eu queria enumerar todos os inteiros de n bits com k dígitos 1. Uma olhadela nos números revelou que uma solução recursiva seria a melhor maneira de atacar o problema. Depois de gastar um pouco de fósforo, encontrei esta singela solução em Perl

sub choose {
  my $n=shift;
  my $k=shift;
  my $callback=shift;
  my @rest=@_;
  
  if($k>0) {
    for my $m ($k..$n) {
      choose($m-1, $k-1, $callback, $m, @rest); 
      &$callback($m, @rest) if $k==1;
    }
  } 
}
A função choose() recebe 4 parâmetros: n é o total de bits; k é o número de dígitos 1; callback é a função que será executada para cada combinação; e rest é um array que contém os dígitos das recursões anteriores (e que assim possibilita termos toda a informação na ponta da recursão sem recorrer a variáveis globais).

A função callback() recebe uma lista com os índices dos bits 1 na iteração atual. Então, se ela recebe (1, 4), isso significa que o primeiro e o quarto bits são 1. Os outros são 0.

Pois bem, com o seguinte teste enumerei todos os números de 8 bits com 7 dígitos ligados:

sub to_number {
  my $total=0;
  map { $total+=2**($_-1) } @_;
  print "$total\n";
}

choose(8, 7, \&to_number);
Esse código imprime a seguinte seqüência: 127, 191, 223, 239, 247, 251, 253, 254. Alternativamente, se eu quisesse enumerar combinações de letras (não deveria haver um verbo eletrar?), eu poderia fazer o seguinte:

choose(4, 2, sub { 
  print map { ('A'..'D')[$_-1] } @_;
  print "\n";
});
Esse código apresenta todos os pares com as letras de A a D: AB, AC, BC, AD, BD, e CD.

quarta-feira, 16 de maio de 2012

etbjxntqrdke

Ontem havia duas reuniões sendo travadas ao meu redor; eu não participava de nenhuma, mas sofria com a gritaria das duas. Como no Brasil é falta de educação apontar a falta de educação dos outros, tive que me contentar com alterar a mensagem do MSN.

Então, um colega me apontou um sítio que vende uma camiseta com a seguinte linha de Perl:

perl -e '
"$a="etbjxntqrdke";
$a=~s/(.)/chr(ord($1)+1)/eg;
print "$a\n;"'
Claro, achei muito explicadinho e limpinho e resolvi arrumar as coisas para manter a má fama do Perl.

perl -e "map { print chr 1+ ord } 'etbjxntqrdke'=~/./g"
Achei o resultado esteticamente aprazível.

terça-feira, 8 de maio de 2012

Linux salva o dia

A mulher amada foi viajar com um notebook (um HP-530) da empresa que, infelizmente, tem um Windows XP cheio de restrições. Não sendo possível instalar o Skype nele, saí à procura de um Linux para resolver o problema de comunicação.

Há muitos Linux que rodam direto de um CD ou DVD, mas são raros os que incluem o Skype. Encontrei uma variação sueca do Ubuntu 12.04 chamada ExLight. Ele funcionou muito bem com a webcam da Genius (uma FaceCam 1000) e com o Wifi (Intel PRO/Wireless 3945ABG).

O boot é demorado se o micro não estiver ligado por cabo a uma rede que devolva logo um IP por DHCP, mas ainda é mais rápido que iniciar o Windows. Esse Linux é tão obscuro que sequer consta do DistroWatch, mas resolveu tão bem o problema em questão que não hesito em indicá-lo.