quinta-feira, 15 de setembro de 2016

Melhorias ao SQL

Lendo um relato sobre um pobre programador que apagou uma tabela inteira, porque esqueceu o where num delete, fiquei a pensar que o SQL deveria ter sintaxe diferente para alguns casos.

Os updates e os deletes de tabelas inteiras deveriam indicar a intenção explicitamente:

update my_table set my_column=0 all rows;
delete other_table all rows;

E se alguém esquecesse do all rows ou do where, seria um erro de sintaxe. Aposto que essa mudança evitaria muito sofrimento.

quarta-feira, 14 de setembro de 2016

Recuperando um roteador WR1043ND com um Raspberry Pi

Um amigo apresentou-me um desafio: recuperar um roteador cuja atualização do firmware dera errado. O roteador, um TP-Link WR1043ND, não funcionava mais. Esse equipamento tem uma interface serial na placa. É uma interface de 3,3V que é compatível com a interface serial do Raspberry Pi.

Infelizmente, não basta abrir a caixa: a interface serial não tem os pinos instalados. Comprei os pinos, um pouco de fio e conectores para construir um cabinho. Depois comecei a perceber que cabinhos com os conectores adequados estão por toda parte: os mouse Genius antigos os tem, assim como os cabos de som dos drives antigos de CD. Até mesmo o cabo de um drive de disquetes ou de HD IDE serviria com algumas modificações. Também aprendi que montar um cabo sem um crimpador é difícil.

No Raspberry Pi, os pinos 6, 8, e 10 servem a porta serial, sendo, respectivamente, o terra (G), a transmissão (Tx) e a recepção (Rx). Eles são vizinhos de dois pinos com 5V (o 2 e o 4), então é preciso ter cuidado. No roteador, para minha sorte, Rx e Tx estão trocados. Percebi isso apenas depois de ter montado o cabo com pinagem idêntica nas duas pontas. Sorte de principiante.

Como os pinos são muito pequenos e não tenho nenhuma prática com soldagem, pedi ajuda à esposa amada, que, embora também não soubesse soldar, tem mais habilidade. O resultado ficou além do esperado.



Do outro lado, os pinos:


São quatro pinos, porque não havia um conector de três disponível. O quarto pino é de energia (3,3V) e é desnecessário para este projeto.

As instruções para atualizar o firmware via a interface serial estão disponíveis na wiki do OpenWRT. Para esse modelo, há duas opções para carregar o arquivo: via tftp e via a própria interface serial. Como eu estava longe do roteador e usando um Raspberry Pi que não tem uma porta ethernet, resolvi executar tudo pela interface serial.

O primeiro passo é instalar o kermit (para enviar o arquivo) e o minicom (para interagir com o roteador):

sudo apt-get install kermit minicom

A porta serial aparece como o device /dev/serial0 (que é apenas um link para /dev/ttyAMA0). Então, para iniciar a comunicação, o comando é:

minicom -b 115200 -o -D /dev/serial0

E só depois liguei o roteador. Ele não dá muito tempo para interromper a sequência de boot. Assim que aparecer o texto "Autobooting in 3 seconds" é preciso digitar tpl para interromer o processo normal. Pode ser preciso desligar e religar o roteador várias vezes.

Pelo minicom, digitei um comando para limpar um bloco de memória e outro para carregar o arquivo novo:

erase 0xbf020000 +7c0000 
loadb 0x81000000

Depois, noutro terminal, iniciei o kermit sem parâmetros e digitei os seguintes comandos:

set line /dev/serial0
set speed 115200
set carrier-watch off
set handshake none
set flow-control none
robust
set file type bin
set file name lit
set rec pack 1000
set send pack 1000
set window 5
send wr1043nd.bin 

Isso deveria durar uns 20 minutos, mas houve muitos erros na transmissão e o envio levou duas horas. Os erros atribuo à qualidade do meu cabo.


Terminado o envio, dois comandos terminam o processo, copiando o arquivo para o flash e reiniciando o roteador:

cp.b 0x81000000 0xbf020000 0x7c0000
bootm 0xbf020000

Eu entendo que a interface serial esteja escondida, porque seria fácil usar uma interface de 5V (ou 12V) e queimar o equipamento, mas acho que foi economia demais não colocar os pinos (que custam centavos). De qualquer forma, o experimento foi um sucesso e várias habilidades novas foram adquiridas.

terça-feira, 6 de setembro de 2016

A linha mais comprida de um arquivo II (O Desafio)

Em janeiro, achei a linha mais comprida de um arquivo usando comandos do shell e usando perl (que resultou ser muito mais rápido).

O Linux pediu revanche, porque eu havia ignorado o awk. Perl provou mesmo ser eficiente.


$time perl -MData::Dumper -ne '$n{length($_)}++; END {print Dumper(%n)}' arquivao.txt
$VAR1 = '1088';
$VAR2 = 349647;

real    0m1.326s
user    0m0.814s
sys     0m0.371s

$time awk 'length($0) > max { max=length($0) } END { print max }' arquivao.txt
1087

real    0m21.400s
user    0m18.596s
sys     0m0.455s

Perl deixou o awk comendo poeira. A diferença nos números deve-se ao fato do awk já ignorar o caractere de fim de linha.

segunda-feira, 5 de setembro de 2016

Múltiplos dos primos

Há anos eu havia escrito um programa para encontrar inteiros candidatos a primos, pulando todos os que eu já sabia serem múltiplos de alguns poucos primos.

Resolvi brincar com o contrário: achar sequências de pulos que levariam a múltiplos dos primeiros primos.


#!/usr/bin/perl
my @primes=qw(
      2      3      5      7     11     13     17     19     23     29 
     31     37     41     43     47     53     59     61     67     71 
     73     79     83     89     97    101    103    107    109    113 
    127    131    137    139    149    151    157    163    167    173 
    179    181    191    193    197    199    211    223    227    229 
    233    239    241    251    257    263    269    271    277    281 
    283    293    307    311    313    317    331    337    347    349 
    353    359    367    373    379    383    389    397    401    409 
    419    421    431    433    439    443    449    457    461    463 
    467    479    487    491    499    503    509    521    523    541 
    547    557    563    569    571    577    587    593    599    601 
    607    613    617    619    631    641    643    647    653    659 
    661    673    677    683    691    701    709    719    727    733 
    739    743    751    757    761    769    773    787    797    809 
    811    821    823    827    829    839    853    857    859    863);

my @steps=(2);
my $product=1;
my @sub=@primes[0..5];
map { $product*=$_ } @sub;
for my $i (2..$product) {
  $found=0;
  for (@sub) {
    if ($i%$_==0) {
      $found=1;
      last;
    }
  }
  if($found) {
    push @steps, $s;
    $s=1;
  } else {
    $s++;
  }
}
print "@steps\n";

A série precisa ir até o produtório dos n primos. Para n=2 (2 e 3), ela vai até 6. Para n=3 (2, 3, e 5), vai até 30, e assim por diante. Os passos são sempre de 1 ou 2, porque um passo maior que 2, pularia um par.

Os primeiros resultados são:

n=1 
2
n=2 
2 1 1 2
n=3 
2 1 1 1 1 2 1 1 2 2 1 1 2 2 1 1 2 1 1 1 1 2
n=4 
2 1 1 1 1 1 1 1 1 2 2 1 1 2 2 1 1 2 1 1 1 1 2 2 1 1 1 1 2 1 1 2 2 1 1 2 1 1 1 1 2 1 1 1 1 2 2 1 1 1 1 2 1 1 
2 2 1 1 1 1 2 1 1 2 1 1 1 1 2 1 1 1 1 1 1 2 1 1 2 2 1 1 2 2 1 1 2 1 1 1 1 1 1 2 1 1 1 1 2 1 1 2 1 1 1 1 2 2 
1 1 2 1 1 1 1 2 2 1 1 1 1 2 1 1 1 1 2 1 1 2 2 1 1 2 1 1 1 1 2 2 1 1 1 1 2 1 1 2 2 1 1 2 2 1 1 1 1 1 1 1 1 2

A soma é igual ao produto, obviamente. Ademais, os inversos das médias são as sequência de frações da última investigação sobre primos. Isto é, para n=2, a média é 6/4 e os dois primos são fatores de 2/3 dos números inteiros. Além disso, as duas metades das sequências são espelhadas, o que podemos usar para economizar espaço e processamento.


quinta-feira, 1 de setembro de 2016

Renovação da habilitação

Parecia mais um dia normal de 2050. Zveg entrou em seu veículo elétrico multipassageiro e iniciou o sistema. Após a breve rotina de inicialização e verificação, o veículo indagou:

-Bom dia, Zveg. Sua habilitação expirará em 15 dias. Deseja executar o teste de renovação?

Zveg irritou-se, mas conformou-se a finalmente a executar o teste, ao menos para deixar de ter que responder a essa pergunta.

-Certo, vamos logo com isso.
-Iniciando teste de habilitação. Fase 1, teste de visão. Quais são as letras exibidas no parabrisas?
-T, P, E...
-Por favor, mantenha sua cabeça contra o encosto.
-Certo, então, T, P, E, V, e X.
-Resposta satisfatória. Tendo em vista o número de pontos acumulados, Zveg, é preciso executar o teste de simulação e sinalização e o escore mínimo é 73.

O veículo escureceu o ambiente e iniciou a simulação. Zveg estava um pouco preocupado; andava dirigindo com desatenção e agora precisava de um desempenho melhor para compensar as faltas.

Durante 20 minutos, o teste de simulação e sinalização correu. O veículo apresentava distintas situações de tráfego e expedia ordens. Em alguns casos, as ordens levariam a infrações e Zveg devia indicar a ação correta a ser tomada:

-Este local não é adequado para estacionar e tampouco posso fazer o retorno, então devo procurar outra rua.

Ao fim do teste, o veredito foi informado prontamente e sem rodeios:

-O resultado é 76. A próxima renovação será em 180 dias. Deseja repetir o teste de simulação e sinalização? Com 80 pontos, a renovação só será necessária em 365 dias.

Zveg já estava farto.

-Não!
-Enviarei os dados do teste para o registro central. Aguarde um insta..zuuuup.

O veículo escureceu e então as luzes piscaram violentamente por alguns segundos.

-Bom dia, Zveg. Sua habilitação expirará em 15 dias. Deseja executar o teste de renovação?