sexta-feira, 4 de fevereiro de 2022

Wordle

Wordle é a sensção do momento e com razão: o jogo é cativante. Ele surgiu em Outubro de 2021 e já existem inúmeras versões para todas as plataformas. Até mesmo os micros de 8 bits já têm suas versões.

Após jogar compulsivamente por alguns dias e chegar a uma tática bastante exitosa (iniciar sempre com as palavras AMBER e THUDS), resolvi analisar as palavras de 5 letras para entender melhor o problema.

Inicialmente, filtrei um dicionário para deixar apenas as palavras de 5 letras:


grep -Po "^[A-Za-z]{5}$" words.txt  | tr '[:upper:]' '[:lower:]'  > fives.txt

Depois analisei as frequências das letras:


fold -w 1 fives.txt  | sort | uniq -c | sort -nr
  12336 a
  10908 e
   8280 s
   7253 i
   7166 o
   7107 r
   6108 l
   5988 n
   5384 t
   4380 u
   3893 d
   3621 c
   3455 m
   3451 y
   3182 h
   2943 b
   2891 p
   2593 g
   2462 k
   1614 f
   1485 w
   1247 v
    760 z
    630 j
    459 x
    164 q
    
 

Então, filtrei as palavras com as 10 letras mais comuns:


grep -Po "^[aesiorlntu]+$" fives.txt  | wc -l
2089

São muitas, então filtrei as que não repetem letras:


grep -Po "^[aesiorlntu]+$" fives.txt  | grep -Ev '(.).*\1' | wc -l
888

Desta lista reduzida, podemos tirar algumas palavras interessantes. O desafio é selecionar duas palavras que juntas tenham as 10 letras mais frequentes.


join -j 2 best.txt best.txt \
 | grep a \
 | grep e \
 | grep s \
 | grep i \
 | grep o \
 | grep r \
 | grep l \
 | grep n \
 | grep t \
 | grep u \
 | sort | uniq | wc -l
2934

Tem muitas combinações de duas palavras com as 10 letras mais comuns em palavras de 5 letras, basta selecionar uma combinação. Por exemplo, "latin euros". O dicionário que escolhi talvez seja completo demais: ele inclui nomes próprios. Vasculhando um pouco, encontrei a dupla "nails route". Doravante, iniciarei as partidas com essa dupla.

Latin Euros vou guardar para o nome de meu grupo de Deep House Salsa.

quarta-feira, 13 de outubro de 2021

Chave Naturalizada

Ao analisar um conjunto novo de tabelas, encontrei algo pouco usual: uma chave estrangeira que também é primária.

Esse mecanismo só pode representar uma relação 1:1 ou 1:0..1. Sim, seria possível colocar tudo numa só tabela, mas há motivos razoáveis para separar: controle de acesso para informações sensíveis, desempenho, e economia de espaço (no caso de uma relação 1:0..1) .

Imaginei que essa configuração tivesse um nome, mas não pude encontrar. Então, tive que inventar um: chave naturalizada.

Ela é naturalizada porque é estrangeira, mas é parte fundamental na tabela secundária por ser primária também.

Outras ideias que me ocorreram: 

  • chave imigrante - descartada porque dá ideia de algo dinâmico;
  • chave agente duplo - descartada porque dá a ideia de conflito ou traição;

Então, essa construção rara será doravante conhecida como chave naturalizada.

segunda-feira, 30 de agosto de 2021

Como a Oracle rouba seu tempo

Tradicionalmente, a Microsoft tem a pior fama no reino da informática. Mas eu acho injusta essa posição. Acho que a Oracle deveria ser a campeã.

Apesar do histórico de práticas anticompetitivas, os produtos da Microsoft são razoáveis. Eles funcionam bem a maior parte do tempo.

A Oracle, entretanto, parece ter forjado um modelo de negócios a partir de bugs e manuais mal-escritos (ou simplesmente errados).

Nenhum software rouba tanto o meu tempo como os da Oracle.

Vou dar um exemplo que tem me ocupado nos últimos meses: o OAM - Oracle Access Manager. Em teoria, é um produto excelente (no marketing, a Oracle não economiza). O dia-a-dia, entretanto, é infernal.

O primeiro sinal de que a vida vai ser difícil começa logo na instalação. É preciso rodar um patch para o instalador funcionar. Não, o instalador não  deve ter sido testado. E não é que eu tenha usado um sistema operacional obscuro: usei o Oracle Linux Server 8.4.

$ java -jar fmw_12.2.1.4.0_idm.jar \\
  -prereqConfigLoc \\
  /tmp/31190532/prereq_metadata/oracle.as.install.oid.prerequisite/prereq

Então, para configurar uma regra de autenticação, encontrei uma sequência inacreditável de erros:

  1. A sintaxe não é completamente descrita no manual;
  2. O exemplo dado na documentação está errado desde a versão  11.1.2.2.0 (Doc ID 1928071.1);
  3. Na versão 12.2.1.4, o parser tem bug, então é preciso desabilitar a verificação da sintaxe (Doc ID 2664614.1).

Nunca atribua à malícia o que pode ser adequadamente explicado pela burrice, diz a Navalha de Hanlon, mas eu, no meio da minha revolta e angústia por perder tanto tempo com esse tipo de erro, fico a pensar que é muito conveniente para vender suporte esse tipo de falha.

O que sugiro é que quem possa evite ao máximo essa empresa. Use Linux, use Postgresql. Não há motivo são para uma empresa entrar hoje na seara da Oracle.

sábado, 20 de março de 2021

Lições sobre Teletrabalho em 2020

Em 2020, minha casa virou um escritório e uma escola. Ela não estava preparada. Aos poucos fui adaptando, cometi alguns erros e achei algumas soluções. Abaixo, seguem as principais lições. 

1. A melhor rede usa cabos 

Wifi pode ser prático, mas não funciona bem com uso pesado de várias pessoas. Mesmo após segmentar a casa com redes em canais diferentes, a solução mais eficaz foi a de usar um Powerline. Além disso, só cabear a casa toda melhoraria a rede. 

2. Compre uma impressora laser com impressão duplex 

Eu fiquei dividido entre uma impressora laser com Wifi e uma com impressão duplex. Escolhi a que tem Wifi, mas a prática revelou que o duplex teria sido mais prático. De qualquer forma, é muito melhor que usar uma impressoa a jato de tinta. As impressoras da Brother são muito boas e funcionam com o Linux.

3. Memória, memória, memória 

Quando iniciei 2020, nenhuma máquina tinha mais que 4GB de RAM. Agora, as que estão em uso contínuo têm de 8GB a 12GB de RAM. O notebook mais antigo tem um processador Core 2 Duo e iniciou o ano com apenas 2GB de RAM. Adicionei mais 1GB e ele rodou o MS Teams muito bem durante o ano todo. Ele roda Ubuntu Mate e usa um SSD. Se fosse Windows com HD, não tenho certeza que teria o mesmo sucesso. Nenhum micro é muito novo (os principais têm um Core i3 540 e um Athlon II X2 270), mas com bastante memória eles funcionam perfeitamente bem apesar de já terem uma década. Os maiores consumidores de memória são os navegadores.

4. Como prolongar a vida de máquinas antigas

Minhas máquinas são antigas, mas servem às minhas necessidades muito bem. Para atingir um desempenho ótimo, elas precisaram de 3 coisas: memória, placas de vídeo, e drive SSD (ao menos para o Sistema Operacional). A placa de vídeo não precisa ser a mais moderna; pode ser a mais antiga disponível (exceto se a intenção for jogar). Um micro usa uma Geforce GT210 e outro usa uma Geforce GT710. Além disso, o SSD também não precisa ser muito grande, basta usá-lo apenas para o Sistema Operacional. Então, com cerca de R$650,00 (R$300,00 por uma placa de vídeo, R$200,00 por um SSD, e cerca de R$150,00 por um pente de 4GB de RAM) é possível transformar um micro antigo numa estação com bom desempenho. Com R$1.000,00 é possível comprar um micro novo, mas ele não vai ter o mesmo desempenho.

O reaproveitamento de máquinas com mais de 10 anos de uso mostrou como o desenvolvimento dos micros tem desacelerado. Em 2021 alguns micros clássicos estão completando 40 anos. Em 1981, muitas pessoas compravam micros com apenas 1KB ou 2KB de RAM. Em 1985, o Amiga 1000 foi lançado com 256KB de RAM. Atualmente, máquinas com 10 ou até 15 anos servem para a maior parte dos casos de uso doméstico.

domingo, 3 de maio de 2020

Pequeno Princípio

Eu acho o livro O Pequeno Príncipe um dos livros mais incríveis já escritos. Acho, inclusive, que a introdução já vale ouro por si só.

A frase mais conhecida desse livro certamente é:


"Tu te tornas eternamente responsável por aquilo que cativas"


Eu sou fã de alguns princípios interessantes para o mundo do software, como o Princípio Greyhound:
"Leave the driving to us"


Ou o Príncipio Broadway:
"Don't call us. We'll call you"


Esses dois últimos descrevem os frameworks e servem para diferenciá-los de bibliotecas.

Eu adaptei a frase do Saint-Exupéri e criei um pequeno princípio para o desenvolvimento de software:
"Tu te tornas eternamente responsável pelo software que escreves" 


É uma lembrança de que o software não é como pão numa padaria: cada linha escrita vai exigir manutenção, suporte, e os erros voltam para nos assombrar.

Tenho pensado nisso porque tenho ouvido muito que "é preciso fazer mais com menos", mas penso que, pelo contrário, é preciso fazer menos. É preciso ater-se ao essencial; ao que realmente agrega valor ao negócio.

Além disso, é preciso dar tempo ao desenvolvimento para que os sistemas não acabem gerando mais suporte do que é possível oferecer. É fácil que a equipe de desenvolvimento acabe num ciclo vicioso de não ter tempo para agregar funções, porque está gastando todo o seu tempo com suporte.

Alguns clientes não essenciais da empresa ganham horas de desenvolvimento quase que por caridade. Existe a noção de que, para sermos justos, devemos dar um pouco de tempo do setor de informática para todo mundo. Mas todo tempo gasto com ações periféricas e não essenciais rouba tempo daquilo que é essencial; rouba tempo hoje e roubará mais adiante quando for preciso dar suporte.

Ademais, nem tudo precisa ser um software novo: muitas coisas podem ser resolvidas com processos e ferramentas de prateleira (ou até mesmo com notas de post-it).

sexta-feira, 17 de abril de 2020

Como Clonar Todos os Projetos de um Grupo do Git

O primeiro passo é criar um token de autenticação para poder usar a API. Então, em suas configurações, procure por Tokens de Acesso (Access Tokens) e crie um para usar a API em modo de leitura. Defina uma data de vencimento para manter sua conta segura.

Um vez criado o token, vá ao grupo que deseja clonar e anote o número (porque ele será usado na chamada à API).


 curl "https://git.acme.com/api/v4/groups/$GRUPO?private_token=$TOKEN" \
   | jq .projects[].ssh_url_to_repo \
   | tr -d '"' \
   | xargs -I{} git clone {}

Troque $GRUPO pelo número do grupo e $TOKEN pelo token criado para autenticar.

Um comando alternativo:

 curl "https://git.acme.com/api/v4/groups/$GRUPO/projects?private_token=$TOKEN" \
   | jq  .[].http_url_to_repo \ 
   | tr -d '"' \
   | xargs -I{} git clone {}
   

Separei o comando em 4 partes:
  • O curl busca um json que descreve o grupo e todos os projetos;
  • O jq extrai de cada projeto a url de acesso;
  • O tr retira as aspas que circundam a url do projeto;
  • O xargs executa o git clone para cada projeto.
Agora, para buscar alguma coisa em todos os projetos, pode-se usar o find.


find . -type f -exec grep -Pi "my_funny_var" /dev/null {} \; > search.txt

Neste caso, procuro por "my_funny_var". As opções usadas são:
  • -type f - analisa apenas arquivos;
  • -exec - executa esse comando para cada arquivo encontrado;
  • -Pi - usa expressões regulares do Perl (porque permitem agrupamentos, opções, etc) sem considerar a caixa.
  • /dev/null - é um nome de arquivo extra para obrigar o grep a imprimir o nome do arquivo antes da linha encontrada (como estamos pesquisando por vários arquivos, queremos identificar cada um nos resultados).

quarta-feira, 29 de janeiro de 2020

Teorema de Herão

O teorema de Herão é uma dessas coisas que, inexplicavelmente, não ensinam na escola. Ele permite calcular a área de um triângulo (e, consequentemente, de outras formas geométricas) usando apenas os comprimentos dos lados.

Dado um triângulo (a, b, c) com perímetro P (a+b+c) e semiperímetro S (P/2), podemos calcular a área A com:

A=sqrt[S(S-a)(S-b)(S-c)]

Dada uma maneira fácil de calcular A, podemos automatizar a busca por triângulos especiais. Por exemplo, todos aqueles cuja área é igual ao perímetro.


#!/bin/perl
use strict;
use warnings;

for my $a (1..1000) {
  for my $b ($a..1000) {
    for my $c ($b..1000) {
      my $P=($a+$b+$c);
      my $S=$P/2;

      my $A=$S*($S-$a)*($S-$b)*($S-$c);

      if($A>0) {
        $A=sqrt($A);
        print "($a, $b, $c) => $A\n" if int($A)==$A && $A==$P;
      }        
    }  
  }
}


(5, 12, 13) => 30
(6, 8, 10) => 24
(6, 25, 29) => 60
(7, 15, 20) => 42
(9, 10, 17) => 36
Ou então, todos cuja área é metade do perímetro: apenas (3,4,5) com área 6. Nenhum tem área menor que S.