Dump email addresses from files

Suppose you have a lot of .doc, .docx, .xls, .xlsx, .gz, .bz2, .pdf and text in general (.csv, .txt etc.) files and want to dump all the (unique) email addresses from them. How would you do it? Here is a simple solution I’ve just implemented (and probably didn’t test enough, so tell me if you find any bug):

#!/bin/sh
tmp=$(tempfile)
while [ $# -gt 0 ]; do
    if [ -r "$1" ]; then
        ext=$(echo ${1#*.} | tr [A-Z] [a-z])
        case $ext in
            docx | xlsx)
                # requires: http://blog.kiddaland.net/2009/07/antiword-for-office-2007/
                cat_open_xml "$1" >> $tmp
                ;;
            doc)
                # requires: antiword
                antiword "$1" >> $tmp
                ;;
            xls)
                # requires: catdoc
                xls2csv "$1" >> $tmp
                ;;
            gz)
                cat "$1" | gunzip >> $tmp
                ;;
            bz2)
                cat "$1" | bunzip2 >> $tmp
                ;;
            zip)
                unzip -p "$1" >> $tmp
                ;;
            pdf)
                # requires: xpdf-utils
                t=$(tempfile)
                pdftotext "$1" $t
                cat $t >> $tmp
                rm $t
                ;;
            *)
                text=$(file -b --mime-type "$1" | sed -e 's//.*//')
                if [ "z$text" = "ztext" ]; then
                    cat "$1" >> $tmp
                fi
                ;;
        esac
    fi
    shift
done
cat $tmp | grep -o -E '\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}\b'
         | tr [A-Z] [a-z] | sort -u
rm $tmp

(the email regexp is explained here: regular-expressions.info/email.html)

Compras e Blog

Hoje, no Linuxmall, comprei um pequeno livro chamado Invasão de Redes: Ataques e Defesas e foi escrito por Tiago José Pereira Nogueira. Nunca vi nada desse cara, ninguém me recomendou esse livro e não conheço ninguém que já tenha lido ou comentado alguma coisa sobre ele. É um livro que parece ser novo e me deu vontade de comprar porque sempre quis saber trabalhar com redes no C. Ele aborda tópicos interessantes, como sockets e conexões, port scanners, DDoS, entre outras coisas. Só tô explicando pra vocês não pensarem que eu comprei porque decidi virar um cracker maligno invasor de redes… :lol: Aproveitei o frete pra comprar também um novo adesivo pro laptop, um Tux grande (de 11x13cm – eu medi antes pra ver se ficava legal no laptop) que custou R$ 2,00. A compra deve chegar quinta-feira. A propósito, alguém já ouviu falar de E-Sedex? Parece ser legal… Barato e rápido! Pedi essa compra com ele pra testar. Faz tanto tempo que não compro na internet que eu fico por fora dessas novidades!

Vou aproveitar o post pra postar os códigos que eu estou fazendo pra interpretação de BBCodes e estatísticas do blog que eu, o Hélio e o Gustavo começamos a desenvolver semana passada e queremos acabar até no máximo o final de novembro (pretendemos acabar perto do dia 15/11).

Expressões Regulares

<?php
/* A parte de regex de códigos precisa do GeSHi Highlighter. Includando-o... */
include("geshi.php");

/* Essa classe serve para ser usada com "extends", ela sozinha "não é nada". */
class Regex {

    /* Função que interpreta emoticons */
    function Emoticons() {
        $origem=Array(":)", ":(", ":D", ":P", ":O", ":S", ":lol:", ":blink:");
        $destino=Array("feliz.gif", "triste.gif", "sorriso.gif", "lingua.gif", "espantado.gif", "confuso.gif", "riso.gif", "confuso.gif");
        // EM DESENVOLVIMENTO!
    }

    /* Função que interpreta BBCodes...
     * Totalmente desenvolvida por mim. (nem parece de tão linda, né?) */
    function InterpretaBBCodes() {
        /* Vamos começar pelos [codes], porque só o que tá fora deles deve ser
           interpretado depois. */

        preg_match_all("/[code language=([a-z]+)](.*)[/code]/sU", $this->texto, $matches_com_linguagens);
        preg_match_all("/[code](.*)[/code]/sU", $this->texto, $matches_sem_linguagens);

        /* - A parte dos códigos é $matches_com_linguagens[$i][2] e $matches_sem_linguages[$i][1].
               - A parte que diz em que linguagem os códigos $matches_com_linguagens[$i][2] foi escrita
              é $matches_com_linguagens[$i][1].
           - Para facilitar os códigos abaixo, vou trocar matches_com_linguagens para mcl e
           matches_sem_linguagens para msl. Só não fiz em cima pra quem tá de fora entender o que
           eu tô fazendo nessa parte do código. ;)
        */

        $mcl=$matches_com_linguagens;
        $msl=$matches_sem_linguagens;

        $con=0;
        for ($i=0; $i<sizeof ($mcl[0]); $i++) {
            $g=new GeSHi($mcl[2][$i], $mcl[1][$i], "./geshi/");
            $geshi_mcl[$i]=$g->parse_code();
            $mcl_md5[$i]=md5(time()*$con++);
            $this->texto=str_replace($mcl[0][$i], $mcl_md5[$i], $this->texto);
        }
        for ($i=0; $i</sizeof><sizeof ($msl[0]); $i++) {
            /* Aqui, vocês vão perguntar: "Por que passar no GeSHi, se não sei highlightear essa linguagem?
               A resposta é que o GeSHi não só highlighta, mas formata o código de forma que ele fique
               legível (por exemplo, troca < por &lt. */
            $g=new GeSHi($msl[1][$i], "", "./geshi/");
            $geshi_msl[$i]=$g->parse_code();
            $msl_md5[$i]=md5(time()*$con++);
            $this->texto=str_replace($msl[0][$i], $msl_md5[$i], $this->texto);
        }

        /* Beleza, agora precisamos sempre lembrar de não highlightear o que estiver entre
           E também não podemos deixar nada fora dos padrões XHTML Strict. */

        $this->texto=str_replace("&", "&", $this->texto);
        $this->texto=str_replace("< ", "<", $this->texto);
        $this->texto=str_replace(">", ">", $this->texto);
        $this->texto=str_replace(""", """, $this->texto);

        // Aqui tá o meu "nl2br" semântico! =)
        $this->texto="<p>".$this->texto."</p>";
        $this->texto=preg_replace("/\n\n\n*/", "<p>", $this->texto);
              /* </p><p></p> vazios não são semânticos. Mas estive pensando depois de fazer isso e acho que
                  algumas pessoas podem querer dar um grande espaço entre os <p>, por isso estou
                  pensando em fazer uma ER que a cada n a mais de dois n's adicione 10px ao
                  margin-bottom do último </p><p>. O que vocês acham? */
        $this->texto=preg_replace("/\n/", "<br />\n", $this->texto);
        $this->texto=preg_replace("/</p></p><p>/", " </p>\n<p>", $this->texto);

        // Formatação básica (negrito, itálico, sublinhado, cores, cabeçalhos)
        $this->texto=preg_replace("/[b](.*)[/b]/sU", "<strong>\1</strong>", $this->texto);
        $this->texto=preg_replace("/[i](.*)[/i]/sU", "<em>\1</em>", $this->texto);
        $this->texto=preg_replace("/[u](.*)[/u]/sU", "<span style="text-decoration:underline;">\1</span>", $this->texto);
        $this->texto=preg_replace("/[color=([^]]+)](.*)[/color]/sU", "<span style="color:\1;">\2</span>", $this->texto);
        $this->texto=preg_replace("/[h([1-6])](.*)[/h\1]/sU", "<h \1>\2< /h\1>n", $this->texto);

        // Citações
        $this->texto=preg_replace("/[quote](.*)[/quote]/sU", "<q>\1</q>n", $this->texto);
        $this->texto=preg_replace("/[quote=([^]]+)](.*)[/quote]/sU", "<q>\2</q>n<cite>\1</cite>", $this->texto);

        // URLs
        $this->texto=preg_replace("/([^\"/=]])(www.[^[:blank:]\"< ]+)/", "\1<a href=\"http://\2\">\2", $this->texto);
        $this->texto=preg_replace("/([^\"=]])(http://[^[:blank:]\"< ]+)/", "\1<a href=\"\2\">\2", $this->texto);

        $this->texto=preg_replace("/[url]([^\"]*)[/url]/sU", "<a href=\"\1\">\1</a>", $this->texto);
        $this->texto=preg_replace("/[url=([^[:blank:]\"]+)[[:blank:]]+title=([^]\"]+)](.*)[/url]/sU", "<a href=\"\1\" title=\"\2\">\3</a>", $this->texto);
        $this->texto=preg_replace("/[url=([^\]\"]+)](.*)[/url]/sU", "<a href=\"\1\">\2</a>", $this->texto);

        preg_match_all("/<a href=\"([^\"]+)\">/U", $this->texto, $matches);

        for ($i=0; $i<count ($matches[0]); $i++) {
            $parse=parse_url($matches[1][$i]);
            $dominio=$parse["host"];
            $this->texto=str_replace($matches[0][$i], "<a href="".$matches[1][$i]."" title="Link Externo: $dominio">", $this->texto);
        }

        // Imagens
        $this->texto=preg_replace("/[img=([^]]+)]([^\"]*)[/img]/U", "<img src=\"\2\" alt=\"\1\" />", $this->texto);
        $this->texto=preg_replace("/[img]([^\"]*)[/img]/U", "<img src=\"\1\" alt=\"Imagem: \2\" />", $this->texto);

        // Listas
        $this->texto=preg_replace("/[list](.*)[/list]/sU", "<ul>\1</ul>", $this->texto);
        $this->texto=preg_replace("/[li](.*)[/li]/sU", "<li><p>\1</p></li>", $this->texto);

        // Limpando besteiras... Alguém tem alguma idéia melhor do que esse FOR feio?
        for ($count=0; $count<10; $count++) {
            $this->texto=preg_replace("/<br /></li>/", "", $this->texto);
            $this->texto=preg_replace("/<ul><br />/", "</ul><ul>", $this->texto);
              $this->texto=preg_replace("/< (/?)li><br />/", "< \1li>",  $this->texto);
              $this->texto=preg_replace("/<q><br />/", "</q><q>", $this->texto);
              $this->texto=preg_replace("/< /q><br />/", "</q>", $this->texto);
          }

          // Emoticons
          // $this->Emoticons();

          /* Lembram que o código tinha sido transformado em md5s com o tempo, pros
             bbcodes não entrarem em ação dentro deles? Então vamos transformar de
             volta em códigos agora... */

          for ($i=0; $i<sizeof ($mcl[0]); $i++) {
              $this->texto=str_replace($mcl_md5[$i], $geshi_mcl[$i], $this->texto);
          }

          for ($i=0; $i</sizeof><sizeof ($msl[0]); $i++) {
              $this->texto=str_replace($msl_md5[$i], $geshi_msl[$i], $this->texto);
          }

          // Limpando as besteiras que não precisam ser repetidas (e coloquei depois dos codes porque
          // aqui corrijo o negócio com os <pre>s.
          $this->texto=preg_replace("/<p>[[:blank:]]*<pre>(.*)< /pre>[[:blank:]]*< /p>/sU", "<\/pre><pre>\1<\/pre>", $this->texto);
          $this->texto=preg_replace("/</p><p>[[:blank:]]*<ul>(.*)< /ul>[[:blank:]]*< /p>/sU", "</ul><ul>\1</ul>", $this->texto);
          $this->texto=preg_replace("/</p><p>[[:blank:]]*<h (.)>(.*)< /h\1>[[:blank:]]*< /p>/sU", "</h><h \1>\2</h>", $this->texto);
          $this->texto=preg_replace("/< ([^>]+)>[[:blank:]]?< /\1>/", "", $this->texto);

          // E pra finalizar, o mais mala de todos... =)
          $this->texto.="\n";
      }
  }
  ?>

Tá bem comentado e queria pedir pra quem puder, dar uma testada com ele (coloquem uns BBCodes errados e coisas que vocês acham que eu não iria prever). Aí embaixo então a parte das estatísticas, para as quais estou usando um pouco do código do Shortstat. Ela tá assim por enquanto:

Estatísticas

<?php
class Estatisticas {
    var $ip, $pais, $codigopais, $referer, $url, $dominio, $res, $useragent, $navegador, $versaonavegador, $plataforma, $unixtime;

    /* Função que descobre o IP real do visitante
     * Copiada de: www.foo.com.br
     */
    function IpReal() {
        if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "desconhecido")) {
            $ip=getenv("HTTP_CLIENT_IP");
        } else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"), "desconhecido")) {
            $ip=getenv("HTTP_X_FORWARDED_FOR");
        } else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"), "desconhecido")) {
            $ip=getenv("REMOTE_ADDR");
        } else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'], "desconhecido")) {
            $ip=$_SERVER['REMOTE_ADDR'];
        } else {
            $ip="desconhecido";
        }

        return $ip;
    }

    /* Função para descobrir navegador, sistema operacional, etc. com base no User Agent.
     * "SI_parseUserAgent()" do Shortstat, levemente modificada.
     */
    function ParseUserAgent($ua) {
        $plataforma="Desconhecida";
        $navegador="Desconhecido";
        $versao="";

        if (eregi("Win", $ua)) {
            $plataforma="Windows";
        } else if (eregi("Mac", $ua)) {
            $plataforma="Macintosh";
        } else if (eregi("Linux", $ua)) {
            $plataforma="Linux";
        } else if (eregi("W3C", $ua)) {
            $plataforma="W3C Validator";
            $navegador="W3C Validator";
            $versao="-";
        } else if (eregi("Googlebot", $ua)) {
            $plataforma="Googlebot";
        } else if (eregi("msnbot", $ua)) {
            $plataforma="MSNBot";
        } else if (eregi("Cynthia", $ua)) {
            $plataforma="Cynthia";
            $navegador="Cynthia";
            $versao="0";
        }

        if (eregi("Mozilla/4", $ua)&&!eregi("compatible", $ua)) {
            $navegador="Netscape";
            eregi('Mozilla/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Mozilla/5", $ua)||eregi("Gecko", $ua)) {
            $navegador="Mozilla";
            eregi('rv(:| )([[:digit:].]+)', $ua, $b);
            $versao=$b[2];
        }
        if (eregi("Safari", $ua)) {
            $navegador="Safari";
            $plataforma="Macintosh";
            eregi('Safari/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("iCab", $ua)) {
            $navegador="iCab";
            eregi('iCab/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Firefox", $ua)) {
            $navegador="Firefox";
            eregi('Firefox/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Firebird", $ua)) {
            $navegador="Firebird";
            eregi('Firebird/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Phoenix", $ua)) {
            $navegador="Phoenix";
            eregi('Phoenix/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Camino", $ua)) {
            $navegador="Camino";
            eregi('Camino/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Chimera", $ua)) {
            $navegador="Chimera";
            eregi('Chimera/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Netscape", $ua)) {
            $navegador="Netscape";
            eregi('Netscape[0-9]?/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("MSIE", $ua)) {
            $navegador="Internet Explorer";
            eregi('MSIE ([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Opera", $ua)) {
            $navegador="Opera";
            eregi('Opera( |/)([[:digit:].]+)', $ua, $b);
            $versao=$b[2];
        }
        if (eregi("OmniWeb", $ua)) {
            $navegador="OmniWeb";
            eregi('OmniWeb/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }
        if (eregi("Konqueror", $ua)) {
            $navegador="Konqueror";
            $plataforma="Linux";
            eregi('Konqueror/([[:digit:].]+', $ua, $b);
            $versao=$b[1];
        }
        if (eregi('Crawl', $ua) || eregi('bot', $ua) || eregi('slurp', $ua) || eregi('spider', $ua)) {
            $navegador="Crawler/Search Engine";
            $versao="-";
        }
        if (eregi('Lynx', $ua)) {
            $navegador="Lynx";
            eregi('Lynx/([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
            $plataforma="Linux";
        }
        if (eregi('Links', $ua)) {
            $navegador="Links";
            eregi('(([[:digit:].]+)', $ua, $b);
            $versao=$b[1];
        }

        $array=Array($navegador, $versao, $plataforma);
        return $array;
    }

    /* Função para determinar o país do visitante
     * "SI_determineCountry()", do Shortstat, bem modificada por mim.
     */
    function DeterminarPais($ip) {
        global $BASE;
        $ip=sprintf("%u", ip2long($ip));

        $db=new $BASE['TYPE'];
        $db->Conecta();
        $db->Query("SELECT nome, codigo FROM ".$BASE['TABELA_PAISES']." WHERE ip_from < = $ip AND ip_to >= $ip");
        $array=$db->FetchRow();

        $db->Desconecta();

        /* Agora um monte de linhas por causa da incompetência do PHP 5.0.5... Hehehe... */
        $tmp1=preg_replace("/([A-ZxC0-xDF])/e", "chr(ord('\1')+32)", $array[0]);
        $tmp2=ucwords($tmp1);
        $array[0]=trim($tmp2);

        return $array;
    }

    /* Função para "increase stats"
     * O arquivo "inc.stats.php" do Shortstat, bem modificado por mim.
     */
    function IncStats() {
        global $BASE;
        $this->ip=$this->IpReal();
        list($this->pais, $this->codigopais)=$this->DeterminarPais($this->ip);
        $this->referer=$_SERVER["HTTP_REFERER"];
        $this->url=parse_url($this->referer);
        $this->dominio=eregi_replace("^www", "", $this->url["host"]);
        $this->resource=$_SERVER["REQUEST_URI"];
        $this->useragent=$_SERVER["HTTP_USER_AGENT"];
        list($this->navegador, $this->versaonavegador, $this->plataforma)=ParseUserAgent($this->useragent);
        $this->unixtime=time();

        $db=new $BASE['TYPE'];
        $db->Conecta();
        $db->Query("INSERT INTO ".$BASE['TABELA_ESTATISTICAS']." (ip, pais, codigopais, dominio,
        referer, resource, useragent, plataforma, navegador, versao, unixtime) VALUES ('{$this->ip}',
        '{$this->pais}', '{$this->codigopais}', '{$this->dominio}', '{$this->referer}', '{$this->resource}',
        '{$this->useragent}', '{$this->plataforma}', '{$this->navegador}', '{$this->versaonavegador}',
        '{$this->unixtime}')");
        $db->Desconecta();
    }
}
?>

Bom… Esses dois códigos estão em desenvolvimento ainda, mas acho que com o tempo vão melhorando. Tem umas coisas na parte de Regex que eu queria tornar mais simples mas ainda não descobri como! :blink: Quem quiser sugerir, sinta-se a vontade.

Expressões Regulares no C

Sem querer, visitando a página do cara que desenvolve as Funções ZZ com o Aurélio, o Thobias, acabei descobrindo que o C possue uma biblioteca para expressões regulares! Não sei porquê, mas sempre pensei que o C não tivesse esse suporte e nunca parei pra investigar…

Agora descobri que o C tem uma biblioteca chamada regex.h com quatro funções simples para ERs:

int regcomp(regex_t *preg, const char *regex, int cflags);
int regexec(const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
size_t regerror(int errcode, const regex_t *preg, char *errbuf, size_t errbuf_size);
void regfree(regex_t *preg)

Não vou aumentar muito esse assunto, mas deixar aqui o link do artigo do Thobias: thobias.org/doc/er_c.html.

A propósito… A página dele é muito legal! Você se sente usando Linux modo-texto… :lol:

E já que falei sobre ERs e Funções ZZ, vou por último falar de um patch que eu fiz pra função ZZCalcula dar as respostas em notação científica e com precisão maior, o que é extremamente importante para eu não precisar ficar contando zeros no novo grupo de estudo de física (que fiz com o prof. Valdir, o Ivo e o John) onde estamos estudando principaplmente astronomia e ter respostas precisas. O patch está disponível aqui e serve para a última versão das ZZ (5.9): Patch para Funções ZZ 5.9, para ZZCalcula resolver as operações com notações científicas e precisão mais alta (infelizmente esse patch foi perdido com o tempo). Para quem já modificou muito seu arquivo das funções, ou não gosta de patches, publiquei também no meu servidor somente o código inteiro da nova função ZZCalcula com esse recurso: zzcalcula.txt (infelizmente esse arquivo foi perdido com o tempo)

Hmmm… Eu resolvi começar a floodar mais aqui no blog, isso é, usar a idéia de assuntos diferentes em posts diferentes… Espero que ninguém que recebe e-mails sempre que eu publico uma coisa nova se estresse muito; mas se tiver chato eu dou um jeito de fazer um cron (meu novo servidor tem suporte a cronjobs! E já que eu nunca usei, seria muito legal aprender…) ;)

Novo site do Colégio!

Publiquei hoje o novo site do Colégio Salesiano Itajaí, um site totalmente administrável (até o título pode ser mudado via formulários) que usa a linguagem PHP e o banco de dados MySql. O site também segue os padrões web, mesmo com formulários rich text que às vezes deixam o site pouco semântico (é que os monitores do Colégio devem poder atualizar) e está disponível em: salesianoitajai.g12.br.

A notícia de estréia da página está disponível aqui e conta com um lindo screenshot do meu Fluxbox com Mrxvt e o Vim com três splits. Embora o site já esteja publicado, ainda tenho que arrumar alguns detalhes como por exemplo o Sitemap que eu cito nesta notícia.

Uma coisa bem legal que eu coloquei no site foi um JavaScript, usando a função addGlobalStyle do Dive into Greasemonkey, que nos Mozillas (ereg(“Gecko/”, $\SERVER[“HTTP_USER_AGENT”]))_ faz o site ficar maior se o usuário usar uma resolução igual ou maior a 1024×768. Dá pra fazer pra todos os navegadores, mas eu sou meio newbie em JavaScript e por isso só usei esse código do Greasemonkey, que só funciona nos Mozillas mesmo… Mas o resultado ficou ótimo! :)

Ontem o Sr. Paulo Matias me ensinou como trabalhar com operadores bit-a-bit no C. Achei muito massa! Agora comecei até a economizar fazendo:

numero = outronumero << 1;

… ao invés de simplesmente:

numero = outronumero * 2;

… para meus programas serem mais rápidos! Hehehe :D Fiz uma função que converte de decimal para binário, e depois vou postar aqui.

Observação: Tenho que descobrir porque os emoticons não funcionam quando tem código... Quer dizer, descobrir eu já descobri, mas preciso ver como eu faço pra resolver de forma boa essas expressões regulares...

Editado!

Corrigi o problema… Confira abaixo o novo trecho de ERs da função de emoticons, onde $o é o vetor de origem (com as carinhas originais), $d é o vetor de desgino (com o <img src…) e replace() é uma função que eu criei para substituir os emoticons:

<?php
if (!ereg("<code", $texto)) {
	$texto=replace($o, $d, $texto);
} else {
	preg_match_all("/</code>(.+)<code/sU", $texto, $mat1);
	for ($i=0; $i<sizeof($mat1[1]); $i++) {
		$texto=str_replace($mat1[1][$i], replace($o, $d, $mat1[1][$i]), $texto);
	}
	preg_match("/^(.+)<code/sU", $texto, $mat2);
	$texto=str_replace($mat2[1], replace($o, $d, $mat2[1]), $texto);
	$rev=strrev($texto); //Tenho medo do PHP5.0.5
	preg_match("/^(.+)>edoc/</sU", $rev, $mat3); //Nossa, que código louco!
	$rev=strrev($mat3[1]); //Repito... Tenho medo do PHP5.0.5
	$texto=str_replace($rev, replace($o, $d, $rev), $texto);
}
?>

Ficou feio, né? Não consegui pensar em outra coisa mais fácil que usar o strrev() ali… :blink:

Biologia, Torres de Hanói, Long Double, Mandriva e Expressões Regulares

Hoje fiz uma prova de biologia. Minha média em biologia estava em 7,93 (8 em um trabalho, 5,8 em uma prova, 10 em participação) e acho que com essa prova vai continuar na mesma, se não piorar. Acredito que eu vá tirar no mínimo 8,5 nessa prova e no máximo 9,5. Pelo menos foi melhor que na outra em que eu tirei 5,8. Bom, só pra não parecer que eu sou burro, minhas notas nas outras matérias nas provas que eu recebi essa semana foram:

  • 10 em inglês
  • 10 em português (e mais 10 numa redação)
  • 10 em matemática
  • 10 em geografia
  • 10 em história
  • 9,5 em química (e mais 10 num trabalho)
  • 9,5 em física

Hmmm… Acho que dá pra perceber que meu problema é biologia mesmo…

Sinceramente, eu odeio essa matéria. Nas outras disciplinas a gente aprende e desenvolve raciocínio lógico. Biologia é só uma decoreba. Não compreendo qual é a utilidade de saber a função das bactérias para nossa vida ou, como um enunciado da prova dizia, “Se você capturasse exemplares de piranhas no Pantanal Mato-grossense, o que você faria pra descobrir de que cadeia alimentar elas fazem parte com base somente nesses exemplares?” Qual a utilidade disso aí? Se eu quisesse ser biólogo até beleza, mas isso aí é inútil. Em matemática, aprendemos coisas úteis. Em biologia, só aprendemos coisas assim… Se ainda fosse como ano passado onde estudávamos atualidades biológicas como células-tronco, AIDS, DSTs, Gripe do Frango, etc., tava ótimo mas esse ano tá um “saco”.

Acho que essa gente que gosta de biologia só pensa no vestibular ao dizer que ela é útil… O básico dela até pode ser útil, mas metade do que a gente aprende na escola de biologia não é útil.

Bom, parando de falar sobre isso… Vamos para as Torres de Hanói

Ontem eu deixei o laptop a noite inteira fazendo as Torres de Hanói com 30 pinos. Utilizando o algoritmo que está implementado em torresdehanoi.c o programa ficou 728 minutos (12 horas) testando e não conseguiu chegar a um fim. Com outros testes, consegui os seguintes tempos:

  • 10 pinos – 0 s
  • 15 pinos – 1 s
  • 20 pinos – 20 s
  • 25 pinos – 20 min
  • 30 pinos – mais de 12 horas

É assombroso a maneira com que vai aumentando…

Bom, utilizando o tipo long double do C eu fiz a conta de 2^64 para ver o custo da “Lenda de Brama” (é esse o nome?)

2^64=18.446.744.073.709.551.616

Ou seja, 18 quinquilhões e meio… Isso é muita coisa.

O interessante é que eu nunca tinha usado o long double com números tão grandes e então fiz alguns testes. Eu cheguei ao resultado de 2^1000, 2^10000 e cheguei a conclusão de que o último número que ele consegue escrever sem dizer que é inf (infinito?) é 2^16383, ou seja, 2^(2^14-1). Saiu umas 40 linhas no console, é muito grande!

Hmmm, demonstrei mais alguns teoremas como a Relação Fundamental da Trigonometria (usando o teorema de Pitágoras – basta dividir os dois lados por a^2), fórmula de Bhaskara, o volume de um cubo inscrito numa esfera pode ser calculado através do raio da esfera, etc. (não lembro de todos). Na verdade, não fui eu que demonstrei. Demonstramos no treino da Olimpíada de Matemática. Eu, o Vavá e o Bruno.

A Mandrakesoft comprou a Conectiva, formando o Mandriva. Eu achei uma pena que uma distribuição importante do Brasil (a primeira) acabou assim. Ela foi muito importante no software livre do Brasil, da América Latina e do mundo. Porém, acredito que a distro Mandriva vai crescer e se popularizar. Quando sair alguma, eu queimo um CD pra testar.

Peguei a música Estrada do Sol (Tom Jobim) no piano (uma versão muito boa escrita por Paulo Jobim e disponível no site www.tomjobim.com.br) e estou pegando Falando de Amor. Assim que der tempo, eu queria gravar algumas músicas que eu toco pra colocar aqui…

Acabei de ler o livro do Aurélio sobre expressões regulares e aprendi bastante coisa interessante. Expressões Regulares são MUITO úteis!

© 2005–2020 Tiago Madeira