Algoritmo de Permutação e Expressões Regulares

permutar (dicionário Priberam)

permutar | v. tr. | v. tr. e int.

Conjugar

do Lat. permutare

v. tr.,

dar reciprocamente;

trocar uma coisa por outra;

cambiar;

v. tr. e int.,

trocar reciprocamente os lugares.

Em matemática, estuda-se a análise combinatória apenas no segundo ano do Ensino Médio (sinceramente, acho isso tão errado quanto não ensinarem a fórmula de Heron ao invés de b.h/2), mas por ser muito útil nas olimpíadas de matemática, acabei aprendendo antes. A permutação que o meu programa faz é com elementos repetidos. Dando a ele um limite de números (naturais) e o número de algarismos de cada saída, ele imprime todas as possibilidades na tela.

Permutação

#include <stdio .h>

#define NMAX 101 //Esta é uma constante que define o tamanho do vetor
#define NIVELMAX 5 //Esta constante define o número de níveis (número de caracteres numa permutação)
#define NUMEROS 2 //Esta constante define o número de números pelo qual a permutação passa.

int n[NMAX]; //Define o vetor "n" que contém os números pelo qual a permutação vai passando.

void permuta(int nivel) { //Inicia função que faz a permutação
        int i; //Define a variável i (contadora)

        if (nivel< =NIVELMAX) { //Se o nível for menor ou igual o nível
                for (i=1; i<=NUMEROS; i++) { //Laço para chamar uma função para cada valor diferente desse.
                        n[nivel]=i; //Define o número atual para i (o valor do laço)
                        permuta(nivel+1); //Chama a função (continua a recursão)
                } //Fim-para
        } else { //Senão
                //Imprime todas os números
                for (i=1; i<=NIVELMAX; i++) { //Laço para pegar os números de todas as funções
                        printf("%d", n[i]);
                } //Fim-para
                printf("n"); //Pula uma linha
        } //Fim-se
} //Fim da função

int main(void) { //Começa a função "main"
        int i; //Define a variável i (contadora)

        //Primeiro, zeramos o vetor "n" que contém os números que vão ser escritos.
        for (i=1; i<=NIVELMAX; i++) { //Laço
                n[i]=1;
        } //Fim-para

        //Chama a função com nível 1.
        permuta(1);
} //Fim-função

Esse código tá tão comentado que tá até difícil de entender…

O que você dá para o programa são as três constantes nas linhas 3, 4 e 5.

Gostei de fazer esse programa. Eu tive que pensar um pouco até na hora de escolher trabalhar com vetores, pois fazer permutações parece uma coisa mais simples mas é difícil. Fiz vários rascunhos de algoritmos no papel, mas aí só tá implementado em C. (eu nunca digito meus algoritmos… :blink: )

Comecei a estudar mais expressões regulares (para desenvolver um novo sistema de bbcodes e sintaxe colorida) e estou achando super legal. É um pouco complicado, mas tem muita lógica e tem muitas coisas úteis que dá pra fazer com elas, principalmente na construção de sites interativos em PHP. Estou lendo o livro do Aurélio que está disponível em guia-er.sourceforge.net. É muito bom! :)

Esse cara é um pouco maluco, mas o que ele faz com expressões regulares é muito legal! Desde setembro/2004, eu utilizo um programa em Bash dele chamado Funções ZZ. As funções ZZ são vários aplicativos simples que utilizam expressões regulares para facilitar tarefas do dia-a-dia. Por exemplo, o conceito de permutação que eu utilizei acima foi de um dicionário on-line das funções ZZ.

Consultando as estatísticas hoje, fiquei feliz ao ver meu blog citado em projetando.blogspot.com. Nunca sei se meus textos estão sendo compreendidos e por isso acho legal quando vejo que alguém linkou para meu site.

Novos problemas lógicos da OBI99 resolvidos!

Baixei a prova da OBI99. Ao invés de ficar demorando nos difíceis, resolvi procurar os mais fáceis mas tentar fazer mais para não ter que pensar muito pois estava meio cansado. A prova de 1999 é muito boa. Os códigos que é preciso fazer pra maioria dos problemas são bastante simples, mas exigem bastante lógica. Precisa parar pra pensar mesmo…

Bom… Resolvi os três que achei mais fácil lendo o enunciado (depois farei o resto):

Trem ou Caminhão?

//Trem ou Caminhão? - OBI1999
#include <stdio.h>

int main() {
	int peso, teste=1;
	float caminhao[2], trem[2];

	while (scanf("%d", &peso)&&peso) {
		printf("Teste %d\n", teste++);
		scanf("%f %f %f %f", &caminhao[0], &caminhao[1], &trem[0], &trem[1]);
		if (caminhao[0]+caminhao[1]*peso<trem[0]+trem[1]*peso-1) {
			printf("envie por caminhao");
		} else {
			printf("envie por trem");
		}
		printf("\n\n");
	}
}

Restaurante

//Restaurante - OBI1999

#include <stdio.h>
#define NMAX 5001

int main() {
	int e[NMAX], s[NMAX], n, i, teste=1, pessoas;

	while (scanf("%d", &n)&&n) {
		for (i=0; i<n; i++) {
			scanf("%d", &s[i]);
		}
		for (i=0; i<n; i++) {
			scanf("%d", &e[i]);
		}
		pessoas=0;
		for (i=0; i<n; i++) {
			if (e[i]>s[n-i-1]&&(n-i)>pessoas) {
				pessoas=n-i;
			}
		}

		printf("Teste %d\npessoas: %d\n\n", teste++, pessoas);
	}
}

Sequências

//Sequências - OBI1999

#include <stdio.h>

int main() {
	char car, inutil;
	int v[3], teste=1;

	v[0]=0;
	v[1]=0;
	v[2]=0;
	while (scanf("%c", &car)) {
		if (car!='#') {
			if (v[2]==2) {
				v[2]=0;
			}
			//printf("%d%d%d\n", v[0], v[1], v[2]);
			v[0]=v[1];
			v[1]=v[2];
			if (car=='0') {
				v[2]=0;
			} else if (car=='1') {
				v[2]=1;
			} else {
				v[2]=2;
			}
		} else {
			if (v[2]==2) {
				break;
			} else {
				printf("Teste %d\n", teste++);
				if (!v[2]&&!v[1]) {
					printf("sim");
				} else {
					printf("nao");
				}
				printf("\n\n");
				v[0]=0;
				v[1]=0;
				v[2]=0;
			}
		}
	}
}

Não usei a entrada e a saída em arquivos como foi usado naquele ano, pois é uma coisa que não vale a pena perder tempo fazendo (não que seja complexo, mas só é ruim e mais demorado ficar escrevendo fscanf ao invés de scanf). Já coloquei a solução dos três na área de scripts e depois colocarei os outros três.

Já fiz a prova das OBIs de 2000 a 2004, e acho que não teve antes de 1999, então essa seria a última prova. Acho que ela tá bem difícil em relação as novas (o que é estranho, pois a partir de 2002 o nível foi aumentando).

O problema Palavras Cruzadas é muito interessante. Eu cheguei a começar a fazer mas ficou um código muito complicado e desisti (depois eu faço).

Fiquei com saudade da simplicidade do meu Slackware e formatei novamente minha partição Linux! Tirei o Debian e já estou configurando o Slackware. Dessa vez não vou compilar o Kernel 2.6 nem atualizar algumas coisas como KDE, Gnome, etc. pois da outra vez meu sistema acabou ficando “instável”. O Slackware 10.1 saiu e já estou pegando download (via bittorrent) para depois instalar. Parece estar bem bom… Várias coisas atualizadas! Só espero que seja estável…

Minhas aulas começam segunda-feira e minha banda (Zibian) vai fazer um show no meio da aula. Hoje ensaiamos e tá ficando legal (embora ainda não esteja bom pra tocar segunda). Já fiz um layout básico no TeX para meus cadernos, configurei Vim, Bash, Firefox, aMSN, etc. no Slack além de trocar splash do KDE, wallpaper, screensaver, configurar o X, LiLo, etc. Já tô ficando acostumado em configurar Linux de forma rápida por causa de tanta formatação… :lol:

OBS.: Acabei de constatar que meu site é o segundo resultado no Google quando se procura por “tableless” em português. :) Está atrás apenas de www.tableless.com.br.

© 2005–2020 Tiago Madeira