Descobrir o ramal de uma pessoa é muito fácil. A intranet os tem todos. Mas algumas pessoas mais antigas (mesmo que de espírito) gostam do velho hábito de usar a telefonista. Como elas não existem mais, alguém vai cumprir o papel, mesmo que involuntariamente!
Então, em nome da paz no ambiente de trabalho, uma técnica pavloviana e pacífica deve ser usada para treinar os preguiçosos chamadores.
A técnica é simples e consiste em, inicialmente, fazer o chamador pensar que a chamada será redirecionada para o alvo pretendido. O treinador deve dizer que "vou passar a ligação para o ramal XYZ", mas deve colocar ênfase e repetir o número com "se a ligação cair, o ramal é XYZ". Então, aperta-se o botão para transferir e coloca-se o telefone no gancho, para que a ligação caia.
Se o chamador insistir, basta repetir a operação. É garantido o resultado em, no máximo, três chamadas (exceto para alguns casos extremos, geralmente restritos a peixes dourados).
quarta-feira, 17 de agosto de 2011
sexta-feira, 12 de agosto de 2011
Força superior
O usuário aproximou-se com um ar otimista e afirmou que "precisamos disponibilizar este software na intranet". A prática me levou a temer esses arroubos dos usuários. Fiz uma cara amigável e perguntei se o programa era para desktop ou para web.
Era desktop, claro. Mas isso é ruim? O diretor autorizou a publicação do sistema na intranet. Já está tudo aprovado.
Ah bom! Se o diretor aprovou a publicação na intranet, então não temos nada a temer. Vou retornar o workflow com um pedido de esclarecimentos.
Era desktop, claro. Mas isso é ruim? O diretor autorizou a publicação do sistema na intranet. Já está tudo aprovado.
Ah bom! Se o diretor aprovou a publicação na intranet, então não temos nada a temer. Vou retornar o workflow com um pedido de esclarecimentos.
segunda-feira, 25 de julho de 2011
Jangada de pasto
Numa bela manhã, um vivente levantou-se ao inusitado som do mar. Sim, porque ele havia ido dormir com a certeza inabalável de que, assim como o havia sido por toda sua vida, acordaria com o silêncio do campo. Achou que seria brincadeira do piá e pôs-se de pé já de mau humor. Esquentou água, preparou a cuia e foi olhar o sol nascer sobre o Alegrete.
Os butiás saltaram um a um dos bolsos do gaudério! Ao abrir a porta, avistou a praia de Mostardas e o Rio Grande a afastar-se. Desta vez, o piá fora longe demais!
Algumas semanas depois, mesmo sob os protestos do prefeito e das ligações constantes ao Palácio do Piratini e ao Palácio da Alvorada, o Alegrete continuava à deriva. Embretado entre a França e a Inglaterra, todos acharam que nunca mais veriam o céu celeste sobre o campo.
Mas, como o leitor já deve ter percebido, essa história não está limitada pela realidade física. Nos dias que se seguiram, o Alegrete despertou-se nos lugares menos esperados.
Os pobres paisanos tiveram que suportar frio, calor, secura e umidade. Ou seja, um dia normal no Rio Grande do Sul.
Os butiás saltaram um a um dos bolsos do gaudério! Ao abrir a porta, avistou a praia de Mostardas e o Rio Grande a afastar-se. Desta vez, o piá fora longe demais!
Algumas semanas depois, mesmo sob os protestos do prefeito e das ligações constantes ao Palácio do Piratini e ao Palácio da Alvorada, o Alegrete continuava à deriva. Embretado entre a França e a Inglaterra, todos acharam que nunca mais veriam o céu celeste sobre o campo.
Mas, como o leitor já deve ter percebido, essa história não está limitada pela realidade física. Nos dias que se seguiram, o Alegrete despertou-se nos lugares menos esperados.
O código dessa brincadeira é simples, como se pode ver abaixo. Entretanto, as coordenadas ocupam muito espaço. Então, se alguém quiser replicar o experimento com seu próprio município, basta pedi-las!
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0px; padding: 0px }
div { float: left }
</style>
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?sensor=true">
</script>
<script type="text/javascript">
var coordenadas=[...];
function getCoords() {
var coords=new Array();
var bounds = new google.maps.LatLngBounds();
for(var i=0; i<coordenadas.length; i+=2) {
var c=new google.maps.LatLng(-coordenadas[i+1],-coordenadas[i]);
coords.push(c);
bounds.extend(c);
}
coords.bounds=bounds;
coords.center=bounds.getCenter();
return coords;
}
var lat=-29.7640;
var lng=-55.8861;
function init() {
var map = new google.maps.Map(document.getElementById("map"), {
zoom: 6,
center: new google.maps.LatLng(lat, lng),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var alegrete = new google.maps.Polygon({paths: getCoords(),
strokeColor: '#000000', strokeWeight: 1, strokeOpacity: 1,
fillColor: '#00AA00', fillOpacity: 0.4, clickable: false });
alegrete.setMap(map);
google.maps.event.addListener(map, 'center_changed', function() {
var point=map.getCenter();
alegrete.setMap(null);
var path=alegrete.getPath();
path.forEach(function(p,i) {
path.setAt(i, new google.maps.LatLng(p.lat()-(lat-point.lat()),
p.lng()-(lng-point.lng())));
});
lat=point.lat();
lng=point.lng();
alegrete.setPath(path);
alegrete.setMap(map);
});
}
</script>
</head>
<body onload="init()">
<div id="map" style="width:400px; height:400px"></div>
</body>
</html>
A navegação é a original do Google Maps. A cada mudança de centro do mapa (indicada pelo evento center_changed), o código corrige as coordenadas do Alegrete. Pode-se notar claramente que a forma distorce-se nas aproximações aos polos; é defeito da projeção.
quinta-feira, 7 de julho de 2011
Segundas intenções
Um amigo, passeando por Portugal, achou-se perdido e resolveu pedir ajuda a um paisano. Com a obtusidade típica dos brasileiros, disse "Eu queria ir a Braga". Luso-descendentes, como eu, logo compreendem o erro do pobre tupiniquim e não têm muita dificuldade para imaginar a resposta: "Pois vá".
Essa forma direta de dialogar dos portugueses gera uma infinitude de piadas no Brasil, muitas das quais são baseadas em fatos. Creio que seja uma injustiça e que engraçados sejamos nós, os brasileiros. Nossa forma indireta de perguntar e responder gera muitas confusões. Já que as pessoas perguntam por segunda intenção, os interrogados passam a interpretar os questionamentos e daí só podem surgir dificuldades.
Há pouco tempo, pedi a um pintor que pintasse uma parede em azul até 123cm e em azul celeste dali até o teto. A ordem não podia ser mais clara. No entanto, ele deu-se ao trabalho de interpretar a minha ordem, já que sabia que eu queria colocar uma faixa ornamentada com bichinhos para meu filho. Ele colocou a faixa com a base em 123cm, quando a metade dela deveria estar nessa altura. Se o pintor fosse português, tenho certeza que minha ordem, mais que clara, não seria (mal) interpretada.
Noutro incidente recente, atendi uma ligação para uma colega. A pessoa que chamou disse "Fulano, a Beltrana...". Fiquei suspenso por uns segundos esperando um verbo. A Beltrana morreu? A Beltrana esqueceu de vir para a reunião? A Beltrana está? A Beltrana pediu para avisar que vai chegar tarde? A Beltrana pediu alguma coisa? Enquanto o analisador sintático esperava pelo complemento, o subsistema de previsão de intenções lançou um aviso: essa criatura provavelmente quer falar com a Beltrana. Encaminhei a ligação e torci pelo melhor.
Imagino o horror se os programadores brasileiros levassem essa filosofia para seu código. Por exemplo, um método para indicar se há fundos necessários para efetuar uma retirada poderia ser escrito da seguinte forma:
Ou seja, o método, se houver fundos, retorna o status da conta (encerrada ou bloqueada, por exemplo), mas se não houver fundos, lança uma exceção para indicá-lo. Não dá para complicar mais uma coisa tão simples.
Outro defeito grave da comunicação tupiniquim é a falta de cortesia básica. É comum caminhar pela rua e ser surpreendido com um "Que horas são?" ou "Onde fica a rua da Ladeira?". Faltam "Bom dia", "Por favor" e "Com licença", cujos propósitos, antes de mais nada, são os de permitir ao cidadão mudar de contexto e preparar-se para iniciar um diálogo.
Se o TCP/IP tivesse sido projetado por um brasileiro, não haveria o handshake (SYN, SYN-ACK, ACK), mas surgiria a necessidade de uma mensagem HEIN, para quando o servidor não estiver preparado para iniciar uma conexão.
Os mal-entendidos cotidianos devem custar um bocado ao Brasil, então é de se espantar que os personagens principais das piadas ainda sejam o Manoel e o Joaquim.
Essa forma direta de dialogar dos portugueses gera uma infinitude de piadas no Brasil, muitas das quais são baseadas em fatos. Creio que seja uma injustiça e que engraçados sejamos nós, os brasileiros. Nossa forma indireta de perguntar e responder gera muitas confusões. Já que as pessoas perguntam por segunda intenção, os interrogados passam a interpretar os questionamentos e daí só podem surgir dificuldades.
Há pouco tempo, pedi a um pintor que pintasse uma parede em azul até 123cm e em azul celeste dali até o teto. A ordem não podia ser mais clara. No entanto, ele deu-se ao trabalho de interpretar a minha ordem, já que sabia que eu queria colocar uma faixa ornamentada com bichinhos para meu filho. Ele colocou a faixa com a base em 123cm, quando a metade dela deveria estar nessa altura. Se o pintor fosse português, tenho certeza que minha ordem, mais que clara, não seria (mal) interpretada.
Noutro incidente recente, atendi uma ligação para uma colega. A pessoa que chamou disse "Fulano, a Beltrana...". Fiquei suspenso por uns segundos esperando um verbo. A Beltrana morreu? A Beltrana esqueceu de vir para a reunião? A Beltrana está? A Beltrana pediu para avisar que vai chegar tarde? A Beltrana pediu alguma coisa? Enquanto o analisador sintático esperava pelo complemento, o subsistema de previsão de intenções lançou um aviso: essa criatura provavelmente quer falar com a Beltrana. Encaminhei a ligação e torci pelo melhor.
Imagino o horror se os programadores brasileiros levassem essa filosofia para seu código. Por exemplo, um método para indicar se há fundos necessários para efetuar uma retirada poderia ser escrito da seguinte forma:
public Status podeRetirar(double valor) throws FundosInsuficientesException { if(saldo-valor<0) { throw new FundosInsuficientesException(); } return getStatus(); }
Ou seja, o método, se houver fundos, retorna o status da conta (encerrada ou bloqueada, por exemplo), mas se não houver fundos, lança uma exceção para indicá-lo. Não dá para complicar mais uma coisa tão simples.
Outro defeito grave da comunicação tupiniquim é a falta de cortesia básica. É comum caminhar pela rua e ser surpreendido com um "Que horas são?" ou "Onde fica a rua da Ladeira?". Faltam "Bom dia", "Por favor" e "Com licença", cujos propósitos, antes de mais nada, são os de permitir ao cidadão mudar de contexto e preparar-se para iniciar um diálogo.
Se o TCP/IP tivesse sido projetado por um brasileiro, não haveria o handshake (SYN, SYN-ACK, ACK), mas surgiria a necessidade de uma mensagem HEIN, para quando o servidor não estiver preparado para iniciar uma conexão.
Os mal-entendidos cotidianos devem custar um bocado ao Brasil, então é de se espantar que os personagens principais das piadas ainda sejam o Manoel e o Joaquim.
sexta-feira, 1 de julho de 2011
Coundown Sort II
O Countdown Sort foi otimizado! Infelizmente, a melhoria custou um if adicional. Mesmo assim, como o algoritmo agora está quatro vezes mais rápido, acho que valeu a pena.
O algoritmo original percorria todo o array subtraindo 1 de cada elemento e anexando os que chegavam a 0 a um array ordenado. Evidentemente, não é preciso percorrer os elementos que já chegaram a 0, então resolvi tirá-los da jogada.
Agora, sempre que encontrar um 0, o algoritmo o troca pelo último elemento do array original e diminui em uma posição a abrangência da busca. Se justamente o último elemento é que chegou a 0, então basta subtrair 1 do índice que aponta para o fim do array (representado no código pela variável last).
Isso significa que o array original será destruído, mas, como o método retorna uma versão ordenada dos números, o problema não é grave.
Paira ainda no ar a dúvida sobre se algo realmente útil pode advir deste algoritmo.
O algoritmo original percorria todo o array subtraindo 1 de cada elemento e anexando os que chegavam a 0 a um array ordenado. Evidentemente, não é preciso percorrer os elementos que já chegaram a 0, então resolvi tirá-los da jogada.
public static short[] countdownSort(short in[]) {
short[] order=new short[in.length];
int index=0;
short delta=0;
int last=in.length-1;
do {
for(int i=last; i>=0; i--) {
if(in[i]-delta==0) {
order[index]=in[i];
index++;
if(i<last) {
in[i]=in[last];
}
last--;
}
}
delta++;
} while(last>=0);
return order;
}
Agora, sempre que encontrar um 0, o algoritmo o troca pelo último elemento do array original e diminui em uma posição a abrangência da busca. Se justamente o último elemento é que chegou a 0, então basta subtrair 1 do índice que aponta para o fim do array (representado no código pela variável last).
Isso significa que o array original será destruído, mas, como o método retorna uma versão ordenada dos números, o problema não é grave.
Paira ainda no ar a dúvida sobre se algo realmente útil pode advir deste algoritmo.
segunda-feira, 27 de junho de 2011
Chocolate e Jurupiga
O chocolate é a bebida sagrada do Novo Mundo, enquanto a Jurupiga é o vinho vira-latas da Europa. São opostos que combinam muito bem. O álcool traz o otimismo para a criação e o amargo do chocolate ajuda na concetração. A combinação é divina. Com a ajuda deles, escrevi um pouco de Javascript para juntar dois mapas antípodas do Google Maps numa só tela. Quando se muda a posição ou a ampliação do mapa da esquerda, o da direita ajusta-se automaticamente para que seu centro seja o antípoda do centro do outro.
Infelizmente, o antípoda do Rio Grande do Sul está no meio do mar entre o Japão e a China. Por outro lado, esta deve ser a única região da Ásia tão despovoada quanto o Pampa.
O código foi testado no Chrome, no Firefox e no IE. Em todos funciona, mas é no Chrome que ele roda mais rápido.
Infelizmente, o antípoda do Rio Grande do Sul está no meio do mar entre o Japão e a China. Por outro lado, esta deve ser a única região da Ásia tão despovoada quanto o Pampa.
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0px; padding: 0px }
div { float: left }
</style>
<script type="text/javascript"
src="http://maps.google.com/maps/api/js?sensor=true">
</script>
<script type="text/javascript">
function init() {
var lat=-29.683889;
var lng=-53.806944;
var here = new google.maps.Map(document.getElementById("here"), {
zoom: 8,
center: new google.maps.LatLng(lat, lng),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
var there = new google.maps.Map(document.getElementById("there"), {
zoom: 8,
center: new google.maps.LatLng(-lat, 180-Math.abs(lng)),
mapTypeId: google.maps.MapTypeId.ROADMAP
});
google.maps.event.addListener(here, 'zoom_changed', function() {
there.setZoom(here.getZoom());
});
google.maps.event.addListener(here, 'center_changed', function() {
var point=here.getCenter();
var sign=point.lng()<0?1:-1;
there.setCenter(new google.maps.LatLng(-point.lat(),
sign*(180-(Math.abs(point.lng())))));
});
}
</script>
</head>
<body onload="init()">
<div id="here" style="width:400px; height:400px"></div>
<div id="there" style="width:400px; height:400px"></div>
</body>
</html>
O código foi testado no Chrome, no Firefox e no IE. Em todos funciona, mas é no Chrome que ele roda mais rápido.
segunda-feira, 20 de junho de 2011
Countdown Sort
Resolvi tentar melhorar o Sleep Sort contando alguma coisa diferente e mais rápida que o tempo. A minha primeira idéia foi contar números e usar os próprios elementos desordenados como medida. Então, cheguei ao Countdown Sort.
A idéia é muito simples: subtraio 1 de cada elemento e a ordenação ocorre naturalmente ao passo que os números forem alcançando o zero. O desempenho é terrível, mas o algoritmo é meu e está pago. Além disso, ele não faz nem comparações nem trocas de elementos e isso já é interessante por si só.
Eis o código em Java:
Um pequeno teste mostra que o algoritmo funciona mesmo com elementos repetidos:
A idéia é muito simples: subtraio 1 de cada elemento e a ordenação ocorre naturalmente ao passo que os números forem alcançando o zero. O desempenho é terrível, mas o algoritmo é meu e está pago. Além disso, ele não faz nem comparações nem trocas de elementos e isso já é interessante por si só.
Eis o código em Java:
public static short[] countdownSort(short in[]) {
short[] order=new short[in.length];
int index=0;
short delta=0;
do {
for(int i=in.length-1; i>=0; i--) {
if(in[i]-delta==0) {
order[index]=in[i];
index++;
}
}
delta++;
} while(index<in.length);
return order;
}
Um possibilidade interessante é a de implementá-lo em código de máquina, já que todas as CPUs têm instruções para subtrair 1 e comparar com 0. Parece-me que o código seria bem pequeno.Um pequeno teste mostra que o algoritmo funciona mesmo com elementos repetidos:
public static void main(String... args) {
short[] ordered=countdownSort(new short[] {
2, 40, 33, 1, 100, 4, 2, 0, 0, 1024
});
for(short v: ordered) {
System.out.printf("%d,", v);
}
}
%java CountdownSort
0,0,1,2,2,4,33,40,100,1024,
Agora, tenho que achar uma maneira de acelerar a contagem.
Assinar:
Postagens (Atom)


