domingo, 16 de junho de 2013

Resposta do problema da caixa


Programa 7 - Volume da caixa em C
  1. #include <stdio.h>

  2. // Programa que procura o volume máximo de uma caixa, restrito à uma dada área superficial..

  3. int main(){
  4.            int c=0,a=0;
  5. //"c" é o limite de iterações do While da linha 28; a é o auxiliar para diminuir o tempo de busca.

  6.            float area=0,x=0,y=0,z=0,v=0,vs=0,xs=0,ys=0,zs=0;
  7. // "area" é o valor que irá ser digitado. As variáveis x,y,z,v irão ser usadas na busca da solução. As variáveis xs,ys,zs,vs  irão armazenar o valor das melhores soluções.
  8.            
  9.            srand(time(NULL)); // Faz o rand() gerar valores distintos a cada execução.
  10.            
  11.            printf("Digite o valor da area superficial da caixa.\n");
  12.            scanf ("%f",&area);
  13.            
  14.            //area = 255,45; // Para testar a capacidade de achar uma solução ótima, define-se um valor arbitrário e executa o programa n vezes
  15.            
  16.            if(area<=1){a=1;}
  17.            if(area<=10){a=10;}
  18.            if(area<=100){a=100;}
  19.            if(area<=1000){a=1000;} // Otimizando o gasto computacional
  20.            if(area<=10000){a=10000;}
  21.            if(area<=100000){a=100000;}

  22.            while(c<1000){ // Quanto maior o limite de c, maior o gasto computacional, porém melhor é o resultado.
  23.                           x=rand()%a;
  24.                           y=rand()%a;
  25.               
  26.                           while(x>area){x=rand()%a;} // "a" reduz o tempo de busca pois limita a busca a valores próximos do esperado..
  27.                           while (2*x*y>area){y=rand()%a;}
  28.                           z=( (area/2)-(x*y) )/(x+y);  // Lembrar que Área superficial = 2(xy+xz+yz)
  29.               
  30.                           v=x*y*z; // Cálculo do volume..
  31.                           if(v>vs){vs=v;xs=x;ys=y;zs=z;} // Se a solução é melhor, substitui valores..
  32.                           c++;
  33.                          }// Fim While
  34.               
  35.            printf ("\n\nVolume maximo: %f \n\nAs medidas sao x=%.2f\ty=%.2f\tz=%.2f\n\n",vs,xs,ys,zs);
  36. //Nessa linha, o código %.2f ordena imprimir até as 2 primeiras casa decimais do resultado.
  37.            
  38.            system("pause");
  39.            }// Fim Main

       Nesse programa é interessante observar a tática usada para diminuir o tempo de busca do computador. Nas linhas 19 até 24, "a" é determinado de acordo com cada área superficial dada. Ou seja, quando nas linhas 27 e 28 efetua-se  x=rand()%a e  y=rand()%a obtemos valores menores que a área superficial, e ainda, provavelmente mais próximos da solução ideal. Lembrar que esse programa é aleatório. Se você executá-lo várias vezes, poderá obter resultados diferentes, entretanto satisfatórios em sua maioria. Esse é o princípio da busca aleatória, que é feita em programas de otimização.

       Novamente vemos as linhas rand () e srand(time(NULL)). Ambas são funções e fazem parte da biblioteca padrão de C. A linha rand() gera um número randômico qualquer. A linha srand(time(NULL)) faz com que esse número seja diferente a cada execução do programa, pois estabelece uma relação com o relógio do computador.

       Bem, por hoje é só. No próximo post, alguns exercícios de C, do estilo dos que eu fiz quando fazia a disciplina de algoritmos no IFET, e que podem cair em provas. Para quem está fazendo a disciplina, é uma boa.

Boa semana à todos!

quarta-feira, 12 de junho de 2013

Estruturas de repetição (2)

       Boa noite! Hoje o post é a continuação das estruturas de repetição. Vou falar do "For infinito", do While e aproveitando o gancho, sobre o conceito de programação estocástica (aleatória). Esse tipo de programação consiste na aproximação do resultado ideal, por uma busca aleatória. No final um desafio, que devo postar a resposta em breve...Vou considerar o For infinito uma extrapolação do uso convencional do for convencional. Lembrando, o for convencional tem a seguinte forma : For(inicialização;limite;incremento){Comandos;} . O For infinito pode se dar de algumas formas: 

                       
For( ; ; ){Comandos;}

                       For(inicialização ; ;){Comandos;
                       
For(; ; incremento){Comandos;}

                       For(inicialização ; ; incremento){Comandos;}

       Note: no primeiro caso, nada se estabelece para o For, ou seja, ele irá executar o comando indefinidamente, até que alguma condição seja atendida e o loop seja encerrado, ou até o programa "dar pau". Digo isso, pois não conheço a fundo as implicações desse uso do For, podem haver erros inesperados em sua execução. Já o segundo tipo, possui um início e um padrão de crescimento/decrescimento, porém não possui um limite.

       Para sair de um For infinito, como eu já mencionei, é preciso impor uma condição de saída, com um comando que encerre o loop. Veja a seguir:

Trecho 1
  1. int i;
  2. for(;;){

  3.           i++;
  4.           if(i>50)break; // Condição e comando de saída 
  5.           printf("%d",i);
  6.           
  7.          }
Trecho 2
  1. int i;
  2. for(i;;){

  3.           i++;
  4.           if(i>50)break; // Condição e comando de saída 
  5.           printf("%d",i);
  6.           
  7.          }
Trecho 3
  1. int i;
  2. for(;;i++){

  3.           if(i>50)break; // Condição e comando de saída 
  4.           printf("%d",i);
  5.           
  6.          }
Trecho 4
  1. int i;
  2. for(i;;i++){

  3.           if(i>50)break; // Condição e comando de saída 
  4.           printf("%d",i);
  5.           
  6.          }
      Como você imagina as saídas desses programas? São iguais? A resposta é não. Os trechos 1 e 2 irão fazer uma contagem de 1 a 50, enquanto que os trechos 3 e 4 de 0 a 50.
      
      Quanto ao While: seu uso, como eu disse no post Estruturas de repetição (1), é para algo que você sabe onde irá acabar, ou ao menos para que se atinja um valor esperado. Imagine o seguinte: você tem um problema muito grande de Programação Linear (otimização), que te dá milhões de possibilidades de soluções. Logo, para percorrer todo o cenário de respostas possíveis, o tempo de operação do computador é muito grande, acredite.

      O que você faz? Faz o que chamamos de busca aleatória. Você escolhe pontos por onde procurar a solução, e, por exemplo, com o uso do While, estabelece um pré valor esperado para sua solução, por exemplo Lucro = 5000 Reais. Feito isso, a primeira solução que o programa encontrar que te dê R$ 5000 ou mais de lucro, ele apresenta à você. A ideia é simples assim. Entretanto sua aplicação nem tanto. Conheço vários professores  e alunos daqui da UFJF, que estudam esse estilo de programação, tanto em C,C++,Matlab,etc... é um assunto interessante que irei retomar em um próximo post.

      Basicamente o While se dá assim: While(Condição){Comandos;}. Veja:

Programa 6 - Busca aleatória do lucro em C.
  1. #include <stdio.h>

  2. int main () {

  3. int lucro=0,x=0,y=0,contador=0;
  4. srand(time(NULL)); // Essa linha é responsável pelo rand() abaixo, gerar números diferentes a cada execução.
  5. while(lucro<5000){
  6.                            contador++; // Número de iterações.
  7.                            x=rand(); // x = Número aleatório.
  8.                            x=x%1000; // x = Resto da divisão de x por 1000.
  9.                            y=rand(); // y = Número aleatório.
  10.                            y=y%1000; // y = Resto da divisão de y por 1000.
  11.                            lucro = 2*x + 4*y; // Função Objetivo
  12.                           }
  13. printf("\n\nx=%d\n\ny=%d\n\nLucro=%d\n\nIteracoes=%d\n\n",x,y,lucro,contador);

  14.          
  15. system("pause");
  16. return(0); }
Observações: 

      Nesse post, inseri alguns comandos ( rand e srand ) que você podia não conhecer. São comandos da biblioteca padrão de C. Não se preocupe muito com a forma com que eles funcionam por enquanto, só saiba que eles funcionam e são de grande valia na programação. Num próximo post, irei abordar detalhes destes.

      Também apresentei uma parte do conceito de programação estocástica. Esse é um tema vasto, com inúmeras aplicações reais em problemas da matemática, engenharia, estatística e de empresas. Vários softwares já foram desenvolvidos com base nesse conceito e ainda rola muita pesquisa em universidades à respeito disso. É outro assunto que voltarei a falar numa próxima oportunidade. É uma boa pra se informar.


Proposta: Mexa no Programa 6. Rode várias vezes e observe as variações de solução. Mude as condições, e a equação objetivo do problema. Dificulte o trabalho do programa para achar a solução. Tente algo para que o número de iterações aumente bastante. Tente algo para que o número de iterações caia bastante também. Isso pode ser feito mexendo nas linhas 10 e 12, mudando o divisor da divisão, aumentando o lucro,etc...

Desafio: Esse eu considero realmente um desafio. Não se preocupe se não conseguir. 


Programa 7 - Volume da caixa em C.

Dada uma determinada caixa, de dimensões X, Y e Z;
sua área superficial é descrita por 2(XY+XZ+YZ).
Proposta: Com base em um valor qualquer de área superficial,encontrar o 
máximo volume que pode ser obtido e quais as dimensões da caixa de maior volume.
Ou seja, maximizar a capacidade da caixa, com menos material gasto...

Obs: Faça para áreas superficiais de até 100.000 unidades.

Boa semana à todos!

domingo, 2 de junho de 2013

Resposta do problema de programação linear


Programa 5 - Otimização Barcos
  1.  #include <stdio.h>
  2. int main(){
  3.     
  4.     int a,b,c,l=0,ra,rb,rc,rl=0;// a = jangadas, b = canoas , c = arcas
  5.     
  6.     for (a=0;a<5;a++){
  7.          for (b=0;b<9;b++){
  8.                 for (c=0;c<4;c++){
  9.                           if (a+b+c<11){ // restringe o máximo de capitães
  10.                           if(a+2*b+3*c<19){ // restringe o máximo de funcionários
  11.                                   l=(50*a)+(70*b)+(100*c); if(l>rl){ rl=l ; ra = a; rb = b ; rc = c;}
  12. // Faz o teste, se o lucro encontrado na equação é maior que o lucro armazenado, se sim troca as respostas para arcas, canoas, jangadas e lucro.
  13. // As variáveis que começam com r estão armazenando a resposta.
  14.                                 } 
  15.                                                  }
  16.                                              }
  17.                                         }
  18.                                    }
  19.     
  20.     printf ("Solucao: \n\nJangadas = %d\nCanoas = %d\nArcas = %d\nLucro = %d\n\n\n",ra,rb,rc,rl);
  21.     system("pause");
  22.     return 0;
  23.            }