Mudanças no Site e Código do Blog

Atenção: os códigos desta postagem, além de inúteis, estão com muitos erros de sintaxe. Foram convertidos entre várias plataformas de blog e perderam muita coisa. Estão guardados aqui apenas para registro.

Ultimamente fiz várias alterações no site. Refiz quase que todas as páginas e deixei tudo um pouco mais leve e mais fácil para mudar depois. :D Depois de conhecer a POO, me viciei nela no final de semana e converti meu site inteiro para classes. E agora, que seu script tá um pouco melhor organizado, vou colocar aqui para quem quiser copiar, usar alguma idéia, saber como eu estou indo em POO, ver as besteiras que eu faço enquanto programo, etc. :lol: resolvi disponibilizar todo o código de meu blog aqui.

Já que meu blog tem alguns bugs (known bugs de pouca importância, como o caso de se alguém escreve CHARESPC no meio de um comentário ele deve criar um &;), peço somente que ninguém destrua-o sabendo disso. Se alguém descobrir algum bug, pode me enviar um e-mail que ficarei bastante grato. :)

Já que não passei a sessão de administração para POO não vou publicá-la aqui, mas depois de resolver alguns bugzinhos pretendo disponibilizar o código completo, inclusive com um arquivo de instalação que cria as tabelas no banco de dados, para todos poderem usar um sisteminha de blog simples e prático (só que acho que vai ser algo mais voltado a programadores, porque tem vantagens como o uso do GeSHi, e desvantagens como eu publicar todos os posts escrevendo em HTML – isso mesmo, até os & que eu escrevo são & que são & *e um loop infinito pela frente). Hmmm, aliás, quem quiser me ajudar a fazer parte desse projeto para tornar o meu blog um software livre, sinta-se livre para me mandar um e-mail também. :p

Então, uma última observação é que eu substituí todos os <code (note a ausência do > ) por tag code e todos os por tag /code, porque senão minhas expressões regulares do código dariam bug (quer saber por que? Então leia os códigos!)

Funções e classes “includadas” em todos os arquivos {#funcoeseclasses}

<?php
session_start();

// Syntax Highlight - GeSHi
if (!class_exists(GeSHi)) {
	include("geshi.php");
}

// Objeto de conexão do MySql
class MySql {
	var $host="servidor";
	var $usuario="usuario";
	var $senha="senha";
	var $db="bancodedados";
	var $conexao;

	function conecta() {
		$this->conexao=mysql_connect($this->host, $this->usuario, $this->senha);
		mysql_select_db($this->db);
	}

	function desconecta() {
		mysql_close($this->conexao);
	}
}

// Classe com as funções de expressões regulares
class Regex {
	function Replace($o, $d, $t, $codes=0) {
		for ($i=0; $i<sizeof($o); $i++) {
			$o[$i]=str_replace('(', '(', $o[$i]);
			$o[$i]=str_replace(')', ')', $o[$i]);
			$t=eregi_replace($o[$i], $d[$i], $t);
		}
		if ($codes==1) {
			$t="tag /code".$t."tag code";
		} else if ($codes==2) {
			$t.="tag code";
		} else if ($codes==3) {
			$t="tag /code".$t;
		}
		return $t;
	}

	function Emoticons() {
		$o[0]=":)";
		$d[0]="feliz";
		$o[1]=":(";
		$d[1]="triste";
		$o[2]=":o";
		$d[2]="bocaaberta";
		$o[3]=":p";
		$d[3]="lingua";
		$o[4]=":angry:";
		$d[4]="raiva";
		$o[5]=":s";
		$d[5]="confuso";
		$o[6]=":blink:";
		$d[6]="inacreditavel";
		$o[7]=";)";
		$d[7]="piscando";
		$o[8]=":lol:";
		$d[8]="rindo";
		$o[9]=":d";
		$d[9]="sorriso";
		$o[10]=":unsure:";
		$d[10]="semgraca";

		for ($i=0; $i<sizeof($d); $i++) {
			$d[$i]="<img src="/emoticon/".$d[$i].".gif" alt="".$o[$i]."" />";
		}

		if (!ereg("tag code", $texto)) {
			$this->texto=$this->Replace($o, $d, $this->texto);
		} else {
			preg_match_all("/</code>(.+)tag code/sU", $this->texto, $mat1);
			for ($i=0; $i<sizeof($mat1[1]); $i++) {
				$this->texto=str_replace($mat1[1][$i], $this->Replace($o, $d, $mat1[1][$i]), $this->texto);
			}
			preg_match("/^(.+)tag code/sU", $this->texto, $mat2);
			$texto=str_replace($mat2[1], $this->Replace($o, $d, $mat2[1]), $this->texto);
			$rev=strrev($this->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
			$this->texto=str_replace($rev, $this->Replace($o, $d, $rev), $this->texto); //Agora fuck PHP5.0.5!
		}
	}

	function GeshiHighlight($codigo, $linguagem) {
		$geshi=new GeSHi($codigo, $linguagem, "./geshi/");
		return $geshi->parse_code();
	}

	function Codigos() {
		preg_match_all("/tag code class=\"(.*)\">(.*)</code>/sU",
			$this->texto,
			$matches);
		for ($i=0; $i<sizeof($matches[1]); $i++) {
			$g=$this->GeshiHighlight($matches[2][$i], $matches[1][$i]);
			if (eregi("MSIE", $_SERVER["HTTP_USER_AGENT"])) {
				$g=ereg_replace("<pre>", "<pre class="alturamaxima">", $g);
			}
			$this->texto=str_replace($matches[0][$i],
				$g,
				$this->texto);
		}
	}

	function QuebraLinha() {
		$this->texto=nl2br($this->texto);
	}
}

// Objeto "Artigo"
class Artigo extends Regex {
	var $id;
	var $data;
	var $permalink;
	var $titulo;
	var $texto;
	var $comentarios;

	function Artigo($identificacao) {
		$this->id=$identificacao;

		$mysql=new MySql();
		$mysql->conecta();

		$query_post=mysql_query("SELECT data, permalink, titulo, texto FROM artigos WHERE id='{$this->id}'");
		$post=mysql_fetch_row($query_post);
		$this->data=date("d/m/Y", $post[0]);
		$this->permalink=$post[1];
		$this->titulo=$post[2];
		$this->texto=$post[3];

		$query_comentarios=mysql_query("SELECT count(id) FROM comentario WHERE idpost='{$this->id}'");
		$comentarios=mysql_fetch_row($query_comentarios);
		$this->comentarios=$comentarios[0];

		$mysql->desconecta();
	}

	function AppendGoogleAds($ads) {
		$this->texto.="nn".$ads;
	}

	function Mostra() {
		echo "<h2><a href=\"/post/{$this-?PHPSESSID=9ec34c96b02b3755051aa682d1e02001>permalink}\">{$this->titulo}</a></h2>\n";
		echo $this->texto."\n";
		echo "<h5>{$this->data} ";
    echo "<a href=\"/post/{$this-?PHPSESSID=9ec34c96b02b3755051aa682d1e02001>permalink}\" class=\"permalink\">permalink</a> ";
    echo "<a href=\"/post/{$this-?PHPSESSID=9ec34c96b02b3755051aa682d1e02001>permalink}#comentarios\" class=\"comentarios\">";
    echo "{$this->comentarios} comentário(s)</a></h5>\n";
	}

	function MostraComentarios() {
		if ($_POST["comenta"]&&(!$_SESSION["comentario"]||time()-30>$_SESSION["comentario"])) {
			$_SESSION["comentario"]=time();
			EscreveComentario($_POST["nome"], $_POST["email"], $_POST["texto"], $this->id);
		}
		$comentarios=new Comentarios($this->id);
		$comentarios->Mostra();
	}
}

// Objeto Artigos (serve para pegar vários artigos sem eu precisar fazer nada nas outras páginas)
class Artigos {
	var $id;
	var $titulo;
	var $texto;
	var $permalink;
	var $data;
	var $comentarios;

	function Artigos($n=20, $start=0, $emoticons=0, $codigos=0, $mostrar=0, $comentarios=0) {
		$mysql=new MySql();
		$mysql->conecta();
		$query=mysql_query("SELECT id FROM artigos ORDER BY data DESC, id DESC LIMIT $start,$n");
		$mysql->desconecta();
		for ($i=0; $array=mysql_fetch_array($query); $i++) {
			$artigo=new Artigo($array["id"]);
			if ($emoticons) {
				$artigo->Emoticons();
			}
			if ($codigos) {
				$artigo->Codigos();
			}
			if ($mostrar) {
				$artigo->Mostra();
			}
			if ($comentarios) {
				$artigo->MostraComentarios();
			}
			$this->id[$i]=$array["id"];
			$this->titulo[$i]=$artigo->titulo;
			$this->texto[$i]=$artigo->texto;
			$this->permalink[$i]=$artigo->permalink;
			$this->comentarios[$i]=$artigo->comentarios;
			$this->data[$i]=$artigo->data;
		}
	}
}

// Objeto Comentário
class Comentario extends Regex {
	var $id;
	var $data;
	var $nome;
	var $email;
	var $ip;
	var $useragent;
	var $texto;
	var $numero;

	function Comentario($identificacao, $numero) {
		$this->id=$identificacao;
		$this->numero=$numero;

		$mysql=new MySql();
		$mysql->conecta();

		$query=mysql_query("SELECT data, nome, email, ip, useragent, texto FROM comentario WHERE id='{$this->id}'");
		$comentario=mysql_fetch_row($query);

		$this->data=date("d/m/Y", $comentario[0]);
		$this->nome=$comentario[1];
		if ($_SESSION["tiagomadeira"]) {
			$this->email="</small> <span style=\"font-size:10px;\"><br />";
			if ($comentario[2]) $this->email.="<strong>E-mail:</strong> ".$comentario[2]."<br />n";
			if ($comentario[3]) $this->ip="<strong>IP:</strong> ".$comentario[3]."<br />n";
			if ($comentario[4]) $this->useragent="<strong>User Agent:</strong> ".$comentario[4];
			$this->useragent.="</span>";
		} else {
			$this->email="</small>";
		}
		$this->texto=$comentario[5];

		$mysql->desconecta();
	}

	function CharEspc($pos) {
		if ($pos==1) {
			$this->texto=preg_replace("/&([^;]+);/sU", "CHARESPC\1/CHARESPC", $this->texto);
		} else if ($pos==2) {
			$this->texto=preg_replace("/CHARESPC(.+)/CHARESPC/sU", "&\1;", $this->texto);
		}
	}

	function Mostra() {
		echo "<div class=\"comentario\" id=\"com{$this->id}\">\n";
    echo "\t <h4><a href=\"?PHPSESSID=9ec34c96b02b3755051aa682d1e02001#com{$this->id}\">#{$this->numero}</a> | ";
    echo "{$this->nome} ";
    echo "<small>{$this->data}{$this->email}{$this->ip}{$this->useragent}</h4>\n";
    echo "<p>{$this->texto}</p>";
    echo "</div>\n";
  }
}

// Objeto Comentários
class Comentarios {
  var $idpost;
  var $ids;
  var $tamanho;

  function Comentarios($idpost) {
    $this->idpost=$idpost;

    $mysql=new MySql();
    $mysql->conecta();

    $query=mysql_query("SELECT id FROM comentario WHERE idpost='{$this->idpost}' ORDER BY data ASC, id ASC");
    for ($i=1; $array=mysql_fetch_array($query); $i++) {
      $this->ids[$i]=$array["id"];
    }

    $this->tamanho=$i;
    $mysql->desconecta();
  }

  function Mostra() {
    echo "<h3 id="comentarios">Comentários</h3>\n";
    for ($i=1; $i<$this->tamanho; $i++) {
      $comentario=new Comentario($this->ids[$i], $i);
      $comentario->CharEspc(1);
      $comentario->Emoticons();
      $comentario->CharEspc(2);
      $comentario->QuebraLinha();
      $comentario->Mostra();
    }

    if ($this->tamanho <= 1) {
      echo "<p>Nenhum comentário cadastrado.</p>\n";
    }

    FormularioComentario($this->idpost);
  }
}

// Função para descobrir IP do visitante
function PegaIP() {
  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 que escreve o formulário para envio de comentário
function FormularioComentario($idpost) {
  $mysql=new MySql();
  $mysql->conecta();
  $query=mysql_query("SELECT permalink FROM artigos WHERE id='$idpost'");
  $row=mysql_fetch_row($query);
  $permalink=$row[0];
  $mysql->desconecta();
?>

<h3>
  Escreva um comentário
</h3>

<?php
}

// Função que cadastra um comentário
function EscreveComentario($nome, $email, $texto, $idpost) {
$ip=PegaIP();
$useragent=$_SERVER["HTTP_USER_AGENT"];
$nome=purifica($nome);
$email=purifica($email);
$texto=purifica($texto);
$data=time();
$mysql=new MySql();
$mysql->conecta();
  mysql_query("INSERT INTO comentario (id, idpost, nome, email, texto, data, ip, useragent) VALUES
    ('', '$idpost', '$nome', '$email', '$texto', '$data', '$ip', '$useragent')") or die(mysql_error());
  $mysql->desconecta();
  $email=($email)?$email:"contato@tiagomadeira.net";
  $mensagem="No post de id $idpost, o $nome ($email) comentou em ".date("d/m/Y", $time)." dizendo:";
  $mensagem.="nn";
  $mensagem.="$texto";
  mail("contato@tiagomadeira.net", "[tiagomadeira.net] Novo Comentário!", "$mensagem", "From: $nome <$email>");
}

// Função que cria escreve o título das seções
function titulo($titulo) {
  $tit="$titulo [tiagomadeira.net]";
  echo "n";
}

// Função para purificar os comentários depois do envio
function purifica($texto) {
  $t=ereg_replace("&", "&", $texto);
  $t=ereg_replace("%", "%", $t);
  $t=ereg_replace("<", "<", $t);
  $t=ereg_replace(">", ">", $t);
  $t=ereg_replace("[", "[", $t);
  $t=ereg_replace("]", "]", $t);
  $t=ereg_replace(""", """, $t);
  return $t;
}

// Função para editar artigos
function pra_textarea($texto) {
  $texto=ereg_replace("&", "&", $texto);
  $texto=ereg_replace("<", "<", $texto);
  $texto=ereg_replace(">", ">", $texto);
  $texto=ereg_replace(""", """, $texto);
  return $texto;
}
?>

E os arquivos que usam essas funções e classes…

/artigos (ou /blog)

<?php
  $artigosporpagina=10; //Artigos Por Página
  $p=($_GET["pg"])?$_GET["pg"]:1; //Página Atual

  $mysql=new MySql();
  $mysql->conecta();
  $query=mysql_query("SELECT count(id) FROM artigos");
  $row=mysql_fetch_row($query);
  $np=ceil($row[0]/$artigosporpagina);
  $mysql->desconecta();

  $paginacao="";
  for ($i=1; $i<=$np; $i++) {
    $paginacao.="<a href="/artigos/$i"";
    if ($i==$p) $paginacao.=" style="font-weight:bold; color:#c00;"";
    $paginacao.=">$i</a> ";
  }
  $paginacao="\n\n<p style=\"text-align:center;\"><span style=\"color:#aaa; font-size:11px;\">";
  $paginacao.="Ir para página:</span> $paginacao</p>\n\n";

  echo $paginacao;

  $artigos=new Artigos($artigosporpagina, ($p-1)*$artigosporpagina);
  echo " <ul>\n";
  for ($i=0; $i<count($artigos->id); $i++) {
      echo "<li><a href=\"{$artigos->permalink[$i]}\">{$artigos->titulo[$i]}</a><br />";
      echo "<small>{$artigos->data[$i]} ";
      echo "<a class=\"comentarios\" href=\"/post/{$artigos->permalink[$i]}#comentarios\">{$artigos->comentarios[$i]} comentário(s)</a>";
      if ($_SESSION["tiagomadeira"]) {
        echo " <a href="/admin-edita&id={$artigos->id[$i]}">[editar]</a>";
        echo " <a href="/admin-exclui&id={$artigos->id[$i]}">[excluir]</a>";
      }
      echo "</small></li>\n";
  }
  echo "</ul>n";
  echo $paginacao;
?>

/ (ou /ultimos)

<?php
	$artigos=new Artigos(5, 0, 1, 1, 1);
?>

Para finalizar… .htaccess

RewriteEngine On

#Diretórios
RewriteRule ^link/?$ http://tableless.tiagomadeira.net
RewriteRule ^post/?$ http://tableless.tiagomadeira.net/blog
RewriteRule ^script/?$ http://tableless.tiagomadeira.net/scripts
RewriteRule ^downloadscript/?$ http://tableless.tiagomadeira.net/scripts

#Blog: A grande excessão
RewriteRule ^blog/([0-9]+)$ http://tableless.tiagomadeira.net/index.php?l=blog&pg=$1
RewriteRule ^/link/blog/([0-9]+)$ http://tableless.tiagomadeira.net/index.php?l=blog&pg=$1
RewriteRule ^artigos/([0-9]+)$ http://tableless.tiagomadeira.net/index.php?l=blog&pg=$1
RewriteRule ^/link/artigos/([0-9]+)$ http://tableless.tiagomadeira.net/index.php?l=blog&pg=$1

#Links
RewriteRule ^link/(.+)$ http://tableless.tiagomadeira.net/index.php?l=$1
RewriteRule ^([^/.]+)$ http://tableless.tiagomadeira.net/index.php?l=$1

#Posts
RewriteRule ^post/([0-9]+)$ http://tableless.tiagomadeira.net/index.php?l=artigo&id=$1
RewriteRule ^post/(.+)$ http://tableless.tiagomadeira.net/index.php?l=artigo&permalink=$1

#Scripts
RewriteRule ^script/(.+)$ http://tableless.tiagomadeira.net/index.php?l=script&script=$1
RewriteRule ^downloadscript/(.+)$ http://tableless.tiagomadeira.net/downloadscript.php?script=$1

#Feeds
RewriteRule ^feed.rss$ http://tableless.tiagomadeira.net/rss.php
RewriteRule ^rss.xml$ http://tableless.tiagomadeira.net/rss.php
RewriteRule ^index.rss$ http://tableless.tiagomadeira.net/rss.php
RewriteRule ^sitemap.xml$ http://tableless.tiagomadeira.net/sitemap.php

De volta à resolução de problemas

Resultado do Superprime Rib

Hoje, depois de umas férias de dois meses, resolvi um problema lógico do USACO Training Gateway: o Superprime Rib é um problema bem simples em que precisa-se determinar os primos de N dígitos (com N máximo = 8 ) que, tirando o último dígito, continuam sendo primos. A solução é trivial, uma função recursiva bastante simples que se auto-explica no meu código:

//Superprime Rib - USACO Training Gateway - 2005

/*
ID: contato1
PROG: sprime
LANG: C
*/

#include <stdio.h>
#define NMAX 9
#define INFINITO 100000

int primos[NMAX][INFINITO], cont[NMAX];

int eh_primo(long int num) {
	int i;

	if (num==1||(!(num%2)&&num!=2)) {
		return 0;
	}

	for (i=3; i*i<=num; i+=2) {
		if (!(num%i)) {
			return 0;
		}
	}

	return 1;
}

void funcao(int n) {
	int i, j, num;

	cont[n]=0;

	if (n>1) {
		funcao(n-1);

		for (i=0; i<cont[n-1]; i++) {
			for (j=1; j<=9; j+=2) {
				num=primos[n-1][i]*10+j;
				if (eh_primo(num)) {
					primos[n][cont[n]++]=num;
				}
			}
		}
	} else {
		primos[1][0]=2;
		primos[1][1]=3;
		primos[1][2]=5;
		primos[1][3]=7;
		cont[1]=4;
	}
}

int main() {
	int n, i;

	FILE *in=fopen("sprime.in", "r");
	FILE *out=fopen("sprime.out", "w");
	fscanf(in, "%d", &n);
	fclose(in);

	funcao(n);

	for (i=0; i<cont[n]; i++) {
		fprintf(out, "%d\n", primos[n][i]);
	}
	fclose(out);

	return 0;
}

O problema passou de segunda porque na primeira, por falta de hábito, eu tinha colocado scanf e printf ao invés de usar o sistema da USACO onde deve-se usar arquivos de entrada e saída.

Agora para eu ir para a seção 2 do USACO Training Gateway falta só o programa Checker Challenge, que parece ser complicado.

Instalei os pacotes do Slackware 10.2, que saiu essa semana, no laptop. Não tem nenhuma grande mudança, mas é sempre bom estar com os programas atualizados…

O Paulo Matias (Thotypous) me convidou para fazer parte da equipe de desenvolvimento da distro Guaranix, consertando alguns bugs do XDirectFB (que eu citei aqui). Acho que irei pegar um trabalho com a Meetweb também (o Hugo Dias, para quem eu fiz o serviço da Coalizão Antituberculose me convidou) e estou acabando o site do Colégio Salesiano, que é totalmente administrável em PHP e usa um banco de dados MySql. Ele deve sair semana que vem…

Dia 24 é a segunda fase da Olimpíada Regional de Matemática. Essa semana fiz a folhinha de treinamento e dos seis problemas, consegui fazer cinco (na verdade, alguns problemas - ou todos - eram repetidos do ano anterior e por isso fica mais fácil, porque eu já lembrava o caminho).

Mensageiros Instantâneos, OBM, Novos Programas, Música

Em primeiro lugar, venho por meio deste post comunicar que não uso mais MSN Messenger. O mensageiro instantâneo da Microsoft saiu da minha lista de contas do CenterICQ para a entrada de dois novos e melhores: IRC e GoogleTalk/Jabber. Cheguei a conclusão de que quem quer falar comigo deve usar o que eu uso e não ao contrário, por um motivo óbvio: o meu é melhor que o deles.

Esta decisão fez com que eu perdesse centenas de contatos, mas acho que foi a decisão certa a ser tomada. Quem quiser me contatar agora, pode me adicionar no ICQ como 147330555, GoogleTalk como tmadeira em gmail.com e no IRC/Freenode, como tiagomadeira.

O segundo ponto importante deste post é o anúncio da OBM, Segunda Fase. A prova acontecerá no sábado que vem, dia 03 de setembro. Acho difícil eu conseguir medalha nesse ano (Terceira Fase é difícil!), mas vou tentar me esforçar o máximo possível… Esta semana tivemos o treino para olimpíadas com o Vavá, aprendi algumas coisas úteis. E ontem conversei com o César Kawakami no ICQ que me deu umas dicas interessantes também sobre Teoria dos Números. Vou tentar aprender alguma coisa sobre isso nos próximos dias…

As aulas de matemática dessa semana foram pouco produtivas porque eu andei faltando algumas para a divulgação do fórum do colégio. Então, só deu pra fazer dois problemas: a implementação da Máxima Subcadeia Comum (LCS/Programação Dinâmica):

//LCS - Longest Common Subsequence
//Programação Dinâmica - MSC - Maior Subcadeia Comum

#include <stdio.h>
#define SMAX 1001
#define DIAGONAL 1
#define LADO 2
#define CIMA 3


//n = tamanho de x
//m = tamanho de y

int c[SMAX][SMAX], b[SMAX][SMAX], n, m;
char x[SMAX], y[SMAX];

int lcs_recupera(int i, int j) {
	if (i==0||j==0) {
		return 0;
	}
	if (b[i][j]==DIAGONAL) {
		lcs_recupera(i-1, j-1);
		printf("%c", x[i]);
	} else if (b[i][j]==CIMA) {
		lcs_recupera(i-1, j);
	} else {
		lcs_recupera(i, j-1);
	}
}

int main() {
	int i, j;


	printf("LCS - Longest Common Subsequence\nPor Tiago Madeira\n\n");
	printf("Digite o tamanho da string X: ");
	scanf("%d", &m);
	printf("Digite o tamanho da string Y: ");
	scanf("%d", &n);

	scanf("%*c");
	printf("Digite a string X: ");
	for (i=1; i<=m; i++) {
		scanf("%c", &x[i]);
		c[i][0]=0;
	}
	scanf("%*c");
	printf("Digite a string Y: ");
	for (i=1; i<=n; i++) {
		scanf("%c", &y[i]);
		c[0][i]=0;
	}

	printf("\nPrograma raciocinando...\n");
	for (i=1; i<=m; i++) {
		for (j=1; j<=n; j++) {
			if (x[i]==y[j]) {
				c[i][j]=c[i-1][j-1]+1;
				b[i][j]=DIAGONAL;
			} else {
				if (c[i][j-1]>c[i-1][j]) {
					c[i][j]=c[i][j-1];
					b[i][j]=LADO;
				} else {
					c[i][j]=c[i-1][j];
					b[i][j]=CIMA;
				}
			}
		}
	}

/*	printf("\nMATRIX C\n");
	for (i=1; i<=m; i++) {
		for (j=1; j<=n; j++) {
			printf("%d ", c[i][j]);
		}
		printf("\n");
	}

	printf("\nMATRIX B\n");
	for (i=1; i<=m; i++) {
		for (j=1; j<=n; j++) {
			printf("%d ", b[i][j]);
		}
		printf("\n");
	}
*/

	lcs_recupera(m, n);
	printf("\n");
}

e um programa bem ridículo para calcular os termos e a soma de uma PA (é o que o prof. tá ensinando, aí achei bom pra fazer os exercícios mais rápido…):

//Aplicar as fórmulas das PAs

//Progressão Aritmética
//Programa desenvolvido por Tiago Madeira (c) 2005.

#include <stdio.h>
#define MAX 1000001

long double a[MAX], s[MAX];

int main() {
	long double r;
	int n;

	printf("Primeiro termo da PA: ");
	scanf("%Lf", &a[1]);
	printf("Razão da PA: ");
	scanf("%Lf", &r);

	//Eu podia fazer só pros que vão ser usados, mas não sei porquê, deu vontade de fazer assim... =)
	printf("\nAguarde o problema raciocinar tudo que ele tem para raciocinar...\n");
	for (n=2; n<MAX; n++) {
		a[n]=a[1]+r*(n-1);
		s[n]=(a[1]+a[n])*n/2;
	}

	printf("\nE agora, digite números para o programa dizer A e S dele.\n");
	do {
		printf("Número: ");
		scanf("%d", &n);
		if (!n) {
			break;
		}
		printf("Número na posição N = %.Lf\nSoma de 1 a N = %.Lf\n\n", a[n], s[n]);
	} while (n);

}

No começo do mês que vem é o Festival de Música de Itajaí. Acho que vou fazer oficina de Piano Popular avançado com o Prof. Michel Freidenson, que foi quem me deu aulas numa oficina semelhante há dois anos. A semana da música vai contar também com uns shows bem legais e o site oficial é este aqui.

Palíndromos Primos

Fiquei um bom tempo sem fazer o treinamento da USACO, porque há algum tempo tinha parado no programa Prime Palindromes, cujo objetivo é listar todos os palíndromos primos entre dois números (limites: 5, 10.000.000).

Esta demora aconteceu porque eu, além de ter ficado muito tempo sem entrar na USACO e já ter me esquecido do problema, estava testando todos os números, vendo se eles eram palíndromos, depois primos e então imprimia. Quando eu entrei na USACO essa semana (idéia do César Kawakami, que também vai pra UNICAMP mês que vem e foi um cara que também me ajudou nesse problema) vi que tinham Hints que eu nunca tinha visto antes. E elas diziam que eu devia gerar palíndromos. Com isso ficou fácil…

Eu ainda boiei um pouco, porque só depois eu descobri uma coisa lógica e muito simples (que eu nunca tinha pensado antes): Para descobrir se um número N qualquer é primo, basta ver se ele é divisível pelos primos (no caso, eu usei todos os números, não só primos) de 2 a raiz de N. Bom, isso é bem óbvio… Mas ninguém nunca tinha me dito e eu nunca tinha visto em lugar nenhum! Então tive que pensar (descobrir sozinho mesmo).

Prime Palindromes

Por preguiça de só fazer alguns for caso o mínimo fosse menor que X e maior que Y, meu programa, para qualquer caso, pega todos os palíndromos primos de 5 a 10000000! :blink: Eu não sabia se o tempo disso ia ser suficiente, então resolvi testar assim antes de fazer esses ifs antes do for e deu certo! Logo, nem precisa mais de nada… O tempo do meu programa para qualquer teste, no meu Linux, é 0,032 segundos. Na USACO apareceu como 0,05 segundos.

Código-fonte

//Prime Palindromes - USACO Training Gateway
//Tiago Madeira (c)

//Agora eu sei que dá pra fazer com custo bem menor,
//mas esse aí rolou na boa com 0.05 segundos.

/*
ID: contato1
PROG: pprime
LANG: C
*/

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>

int eh_primo(long int num) {
	int i;

	for (i=3; i*i<=num; i+=2) {
		if (!(num%i)) {
			return 0;
		}
	}

	return 1;
}

int main() {
	int i, j, k, l, cont=0;
	long int numero, min, max, v[10000];

	FILE *in=fopen("pprime.in", "r");
	FILE *out=fopen("pprime.out", "w");
	fscanf(in, "%d %d", &min, &max);
	fclose(in);

	v[cont++]=5;
	v[cont++]=7;
	for (i=1; i<=9; i+=2) {
		numero=i*10+i;
		if (eh_primo(numero)) {
			v[cont++]=numero;
		}
	}
	for (i=1; i<=9; i+=2) {
		for (j=0; j<=9; j++) {
			numero=i*100+j*10+i;
			if (eh_primo(numero)) {
				v[cont++]=numero;
			}
		}
	}
	for (i=1; i<=9; i+=2) {
		for (j=0; j<=9; j++) {
			for (k=0; k<=9; k++) {
				numero=i*10000+j*1000+k*100+j*10+i;
				if (eh_primo(numero)) {
					v[cont++]=numero;
				}
			}
		}
	}
	for (i=1; i<=9; i+=2) {
		if (i==5) {
			i=7;
		}
		for (j=0; j<=9; j++) {
			for (k=0; k<=9; k++) {
				for (l=0; l<=9; l++) {
					numero=i*1000000+j*100000+k*10000+l*1000+k*100+j*10+i;
					if (eh_primo(numero)) {
						v[cont++]=numero;
					}
				}
			}
		}
	}
	for (i=0; i<cont; i++) {
		if (v[i]>=min&&v[i]<=max) {
			fprintf(out, "%d\n", v[i]);
		} else if (v[i]>max) {
			fclose(out);
			return 0;
		}
	}
	fclose(out);
	return 0;
}

Agora vou prosseguir com o treinamento do USACO Training Gateway na seção 1.3, a começar pelo problema Mixing Milk.

O Homem que Calculava

Nos últimos dias não aconteceu nada demais. Só fiquei emocionado por ter recebido um 9,1 em biologia… :lol: E outra coisa legal também é que eu reli O Homem que Calculava e achei muito legal. Eu tinha lido na sexta série e acho que não tinha entendido direito tudo. O livro é muito bom e não é muito complicado não. O próximo que eu quero reler é O Diabo dos Números. Esse é mais “avançado” que o primeiro. Tô fazendo um trabalho de escola (de história) sobre (o filósofo) Pitágoras. É bem legal, o cara era muito bom. Na verdade, o trabalho tá virando de matemática, mas é bem interessante. É legal ter um professor de história que dá aula… ;) Não é igual ano passado, né? Tô achando bem legal os períodos da Grécia Antiga.

Ah, e vou finalizar citando um trecho d’O Homem que Calculava em homenagem ao Vavá, que não respira oxigênio… :D

Conta-se que o famoso rei Salomão, para demonstrar a finura e a sabedoria de seu espírito, deu à sua noiva, a rainha de Sabá – a famosa Belquiss – uma caixa com 529 pérolas. Por que 529? Sabe-se que 529 é o quadrado de 23, isto é, 529 é igual a 23 multiplicado por 23. E 23 era, exatamente, a idade da rainha.

Samba em Prelúdio

GeSHi Highlight funcionando! Página “oficial” de testes…

#include <stdio.h>
int main() {
   printf("Eu sem você");
}
program continuacao;

begin
   write('Não tenho porquê.');
end.
<?php
   echo "Porque sem você...";
?>
<p>
  Não sei nem chorar...
</p>
#!/bin/bash

echo "Sou chama sem luz..."
.jardim {
  sem: luar;
  luar: sem amor;
  amor: sem se dar;
}
document.write("Eu sem você...");
print 'Sou só desamor.'
INSERT INTO musica (letra) VALUES ('Um barco sem mar...');
<%
response.write("Um campo sem flor.");
%>
<?xml version="1.0">

<window id="janela" title="Continuação em XUL" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<text id="resto" value="Tristeza que vai, tristeza que vem" />
</window>

E por aí vai… Heheh…

© 2005–2020 Tiago Madeira