terça-feira, 14 de junho de 2016

Repositório

Olá companheiros!

Agora já fizemos a implementação do projeto estamos disponibilizando o repositório dos códigos fonte tanto para o Arduino quanto para o bot do Telegram através do Bitbucket.


Até para comentar um pouco mais sobre a implementação considero válido passar uma experiência que tivemos com C. Durante o projeto tivemos a necessidade de tokenizar os dados que estão chegando no Arduino para que ele pudesse fazer o sequenciamento das notas que serão reproduzidas, o fato é que o Arduino não possui em sua biblioteca de manipulação de String uma função para isso e tivemos que implementar. Apenas para ficar mais claro o que acontece é o seguinte o dado chega pelo Raspberry como um texto que contém uma sequência de números seguido de uma vírgula, outra sequência de números e um espaço em branco, a primeira sequência de número é a frequência da noa que deve ser tocada e a segunda sequência é a duração em millisegundos, o desafio aqui era receber essa sequência de caracteres e dividir a mesma para que seja tocada uma nota por vez:
  Entrada: "123,1000 432,100 222,1000"
  Saída: tone(123, 1000);
             tone(432,100);
             tone(222,1000);

Inicialmente fizemos a implementação usando malloc e realloc pois tinha como idéia criar uma variável char* e conforme percorrêssemos a sequência principal iríamos acumulando a mesma na variável até que uma vírgula ou espaço fosse encontrado dessa forma o pseudo-código havia ficado assim:

char* nota;
char* duracao;
nota = (char*)malloc(nota, sizeof(char));
strcpy(nota,"");
duracao = (char*)malloc(duracao, sizeof(char));
strcpy(duracao, "");
char[] principal = "123,1000 432,100 222,1000";
para i de 1 ate N repita
   char cnota = principal[i];
   ...
   int lnota = strlen(nota);
   nota = realloc(nota, lnota+1);
   strcat(nota,cnota);
   ...
fim para


Bom o que aconteceu é que o código funcionava muito bem para pequenas cadeias, porém para cadeias grandes de caracteres começávamos a pegar sujeira da memória e com isso não tínhamos como transformar a informação em int para poder passar para a função tone. Perdemos muitas horas tentando fazer esse código funcionar até que chegamos num ponto de desistir e começar do zero com outra abordagem que foi o código abaixo que está disponível no bitbucket:



void tocar(const char *notas){
   int l = strlen(notas);
   int i = 0;
   int j;
   int indexComma = 0;
   int start = 0;
   for (i = 0; i < l; i++){
   char c = notas[i];
   if (c == ' ' || c == '\n' || c == '\0'){
      int lnota = indexComma - start;
      char nota[lnota];
      int k = 0;
      for(j = start; j < indexComma; j++){
         nota[k++] = notas[j];
      }
      nota[k] = '\0';
      int lduracao = i - indexComma;
      char duracao[lduracao];
      k = 0;
      for(j = indexComma+1; j < i; j++){
         duracao[k++] = notas[j];
      }
      duracao[k] = '\0';
      int inota = atoi(nota);
      int iduracao = atoi(duracao);
      tone(10,inota, iduracao);
      int pausaEntreNotas = iduracao;// * 1.30;
      delay(pausaEntreNotas);
      noTone(10);
      start = i+1;
   }else if (c == ','){
      indexComma = i;
      }
   }
}


O algoritmo acima funciona perfeitamente, porém sua função de complexidade é

   : f(n)=2n

pois ele percorre a cadeia de caracteres uma vez procurando pelos marcadores ("," e " ") e quando acha ele percorre de um ponto inicial a um final copiando os dados para as variáveis a que se destinam. Enquanto que o primeiro algoritmos ("caso tivesse dado certo") teria feito a mesma coisa com função de complexidade

   : f(n) = n

Pois ele já viria acumulando a cada passada por n nas variáveis a que se destinam.

O que aprendemos disso tudo foi existem mil maneiras de resolver um problema e quando uma não vai de jeito nenhum procure ver as alternativas a partir do zero.






Nenhum comentário:

Postar um comentário