EngenhariaTelecom / Projeto01_Prog

0 stars 0 forks source link

diario-julia_espindola #3

Open beatriz-paz opened 1 year ago

julia-e2002 commented 1 year ago

Diário de bordo - 27 de Março de 2023

Durante a aula de programação de segunda-feira foi iniciado um projeto que consiste em analisar preços de ações. O programa é dividido em duas partes: a sequência de dias com valores ascendentes e a probabilidade de cada quantidade de dias com valores ascendentes.

Para que a primeira parte do problema fosse possível ser resolvida, iniciamos o código abrindo o arquivo que contém a data e o preço, respectivamente, em cada linha. Além de pensar no possível erro de sua abertura.

Assim que abrisse, o programa iria ler a primeira linha, localizar o preço e armazenar em uma lista de preços.

Contamos com o arquivo tendo um formato padrão dos valores:

DD/MM/AAAA valor

Por isso criamos uma função que, após encontrar o primeiro espaço na linha, criasse uma string a partir dessa posição e a denominasse _precodia.

Finalizando o código dessa forma:

//função para obter a ultima string da frase do arquivo, na qual é o preco
string copia_ultima(const string & linha) {

    // encontra a posição do primeiro espaco
    int pos = linha.find(' ');
    //caso encontrar o espaço na frase:
    if (pos != string::npos) {
        //retorna a string contendo o trecho da linha posterior ao espaço
        return linha.substr(pos);
    }
    // caso não encontre o espaço, retorna uma string vazia

    return "";
}

int main(int argc, char * argv[]) {

    //criando um arquivo para leitura
    ifstream arq(argv[1]);

    //verifica se conseguiu abrir o arquivo
    if (! arq.is_open()){
        perror("Ao abrir ");
        return errno;
    }

    string linha, palavra, preco_dia;
    list<string>precos;

    //ler as linhas do arquivo, armazenando em uma lista de precos
    while (getline(arq, linha)){
        preco_dia = copia_ultima(linha);
        precos.push_back(preco_dia);
    }

Porém, notamos que a ideia de usar listas para esse caso não seria eficiente, então no próximo teste tentaremos usar structs, criando um novo tipo de dado para armazenar todas as informações necessárias, como o preço e os dias, deixando mais organizado e fácil de desenvolver.

Necessário para finalizar o projeto:

Projeto: Analisador de preços de ações Júlia, Beatriz e Leonardo.

julia-e2002 commented 1 year ago

28 de Março de 2023

Dia proposto para pesquisar soluções dos problemas encontrados em sala e compartilha-las no próximo encontro.

A struct criada será definida como Acoes.

struct Acoes{
    string data;
    double preco, preco_crescente, probabilidade_dias;
}

Dentro dela será possível acessar o preço e a data, que agora testamos armazenar dentro de um vetor. A escolha do vetor se deu pois cada local armazenado nele já tem uma ordem crescente, sendo mais fácil de localizar cada informação. Assim, dispensamos o uso da lista, já que não seria preciso trocar os dados de lugar nessa ocasião.

//criando um vetor do tipo Acoes que foi criado
    vector<Acoes>info_acoes;

    //cria uma variavel linha para conseguir armazenar a linha lida do arquivo no loop
    string linha;

    //ler as linhas do arquivo, armazenando em um vetor os precos
    while (getline(arq, linha)) {

        istringstream frase(linha);
        Acoes dados_acoes;

        frase >> dados_acoes.data >> dados_acoes.preco; // ler a linha do arquivo e armazena a data e o preço na struct criada através do operador de extração ">>"
        info_acoes.push_back(dados_acoes); //adiciona ao vetor a struct
    }

Depois disso, pensamos em armazenar essas informações em uma pilha.

julia-e2002 commented 1 year ago

29 de Março de 2023

Novamente na aula de programação, dedicamos o tempo para pensar na lógica do programa e como iria rodar o loop da pilha.

De início criamos uma pilha dessa forma:

//pilha para armazenar "o dia anterior mais próximo cujo preço de ação seja maior que o dia presente."
    stack<double>dias_preco_crescente;
    dias_preco_crescente.push(0);

Dentro da pilha seria possível contar os dias de preço crescente que é igual ao tamanho dela, pois antes de empilhar um dado de preço, é necessário saber se esse dado é maior que o preço do topo da pilha, se for, desempilha o do topo e empilha o atual, caso contrário só empilha. Alguns testes desse loop não deram certo, por isso teremos que revisar essa parte e ver onde estamos errando.

Além disso, recebemos ideias do professor de criar mais structs para ir armazenando os resultados de cada parte do projeto:

struct Acoes{
    string data;
    double preco;
};

struct ResultadoUm{
    string data;
    int dia_com_aumento_preco;
};

struct ResultadoDois{
    string data;
    double probabilidade_dias = 0;
};

Mas ainda precisamos revisar e definir a lógica por trás do problema para sermos mais precisos na hora de dar o próximo passo.

julia-e2002 commented 1 year ago

31 de Março de 2023

Conseguimos desenvolver uma forma de empilhar os dados e fazer com que esse loop que funcione:

//pilha para armazenar "o dia anterior mais próximo cujo preço de ação seja maior que o dia presente."
    stack<int>dias_preco_crescente;
    dias_preco_crescente.push(0);

    //vetor para armazenar o dia calculado e a data referente ao calculo para que possamos armazenar os dados dessa pilha 
    vector<Resultado>dia;

    for (int i = 0; i < info_acoes.size(); ++i) {

        dia.push_back(Resultado());

        while (!dias_preco_crescente.empty() && info_acoes[dias_preco_crescente.top()].preco <= info_acoes[i].preco) {
            dias_preco_crescente.pop();
        }

        if (dias_preco_crescente.empty()) {
            dias_preco_crescente.push(i + 1);
            dia[i].dias_preco_aumentou = i + 1;
        } else {
            dia[i].dias_preco_aumentou = i - dias_preco_crescente.top();
            dias_preco_crescente.push(1 - dias_preco_crescente.top());
        }

        dias_preco_crescente.push(i);
        dia[i].data = info_acoes[i].data;

    }

Para o final precisamos revisar se não existe outra forma mais eficiente.

Fora isso, falta começar a parte de probabilidade.

julia-e2002 commented 1 year ago

1 de Abril de 2023

Iniciamos a parte de probabilidade com a ideia que precisamos ler todos os dias já contados (que estão guardados na struct Resultado), somar quantas vezes cada número apareceu e dividir pelo total. Assim imprimindo, respectivamente, o dia contado e a probabilidade.

Testamos várias vezes esse laço de contagem e não deu certo:

 //vector<Contagem>probabilidade_aumento_preco;
    vector<Contagem>probabilidade_aumento_preco;

    // loop para calcular as probabilidades de duração de preço ascendente

        int contador = 0;
        for (int i = 0; i < info_acoes.size(); i++) {
            int numero = dia[i].dias_preco_aumentou;
            while (i < dia.size()) {
                numero = dia[i].dias_preco_aumentou;
                int digitoAtual = numero % 10;
                if (digitoAtual == dia[i].dias_preco_aumentou) {
                    contador++;
                }
                int num = numero /= 10;
                i++;
            }
        }

Portanto, tentei de outro modo mas falta testar, se der certo, basta apenas descobrir a quantidade de números e adicionar a divisão de probabilidade.

 //vector<Contagem>probabilidade_aumento_preco;
    vector<Contagem>probabilidade_aumento_preco;

    //adicionando os dias contados do vetor dia no vetor de prob
    for(int i = 0; i < dia.size(); i++) {
        probabilidade_aumento_preco[i].dia = dia[i].dias_preco_aumentou;
    }

    sort(probabilidade_aumento_preco.begin(), probabilidade_aumento_preco.end());

    int cont = 1;
    for (int j = 1; j < probabilidade_aumento_preco.size(); j++) {

        if (probabilidade_aumento_preco[j].dia == probabilidade_aumento_preco[j - 1].dia) {
            cont++;
        } else {
            probabilidade_aumento_preco[j-cont].rep = cont;
            cont = 1;
        }

    }

Essa ideia consiste em organizar o vetor da probabilidade com os dias contados por meio do sort e ver quantas vezes ele se repete através do contador, conseguindo já organizar quais são os números e suas ocorrências para facilitar a conta final da probabilidade.

julia-e2002 commented 1 year ago

2 de Abril de 2023

Ainda pensando no código anterior de probabilidade, tentei complementar, jogando os dados ordenados sem repetição em uma fila:

//cria uma fila para os dias sem repetições
    queue<int> ordem_dias;

    for (int i = 0; i < probabilidade_aumento_preco.size(); i++) {
        // se o primeiro num for diferente do segundo, armazena na lista o segundo
        if (probabilidade_aumento_preco[i].dia != probabilidade_aumento_preco[i+1].dia) {
            ordem_dias.push(probabilidade_aumento_preco[i].dia); 
        }
    } //finaliza a lista com todos os numeros sem as repetiçoes

    //conta a probabilidade e armazena na struct 
    for (int i = 0; i < ordem_dias.size(); i++) {
        probabilidade_aumento_preco[i].probabilidade_dias = probabilidade_aumento_preco[i].rep / ordem_dias.size();
    }

Porém, hoje, com várias tentativas, conseguimos finalizar a parte de probabilidade, armazenando os dados importantes para o cálculo também através de um contador. Ficou assim:

//vetor que calcula a probabilidade
vector<Contagem>probabilidade_aumento_preco;

    for (int i = 0; i < dia.size(); ++i) {
        double contador = 0;
        int qtd_dia = dia[i].dias_preco_aumentou;
        for (int j = 0; j < dia.size(); ++j) {
            if (dia[j].dias_preco_aumentou == qtd_dia){
                contador++;
            }
        }
        double probabilidade = contador / dia.size();
        probabilidade_aumento_preco.push_back(Contagem());
        probabilidade_aumento_preco[i].dia = qtd_dia;
        probabilidade_aumento_preco[i].probabilidade_dias = probabilidade;
    }

Como a função sort não funcionou do jeito inicial, pesquisamos outras formas de ordenar esse vetor:

// usando a função SORT para ordenar o vetor de probabilidade
    sort(probabilidade_aumento_preco.begin(), probabilidade_aumento_preco.end(), [](const Contagem& a, const Contagem& b) {
        return a.dia < b.dia;
    });
    // remover elementos duplicados do vetor usando a função UNIQUE
    auto it = unique(probabilidade_aumento_preco.begin(), probabilidade_aumento_preco.end(), [](const Contagem& a, const Contagem& b) {
        return a.dia == b.dia;
    });
    probabilidade_aumento_preco.erase(it, probabilidade_aumento_preco.end());

Por algum motivo não era aceito o sort daquele jeito, mas esse funcionou corretamente.

Então, com os valores dos dias ordenados e a conta da probabilidade, obtivemos todos os resultados possíveis. Assim, fizemos com que os resultados saíssem em dois arquivos:

1 - com a data e a quantidade de dias 2 - com os dias e a probabilidade de cada um.

Como a probabilidade teve o resultado em double, criamos outro laço que percorre o vetor de resultados, transforma os valores de várias casas decimais em valores de 4 casas e escreve no arquivo de resultado.


// ARQUIVOS DE SAÍDA

    //criando o arquivo de saida "resultado" que contém o calculo da quantidade de dias que teve o aumento do preço
    ofstream arq_dias("resultado.txt");
    //valida se deu para abrir o arquivo criado
    if (not arq_dias.is_open()) {
        cerr << "Algum erro ao abrir o arquivo ..." << endl;
        return 0;
    }
    // Percorre o vetor "dia" e escreve cada elemento no arquivo resultado
    for (auto elemento : dia) {
        arq_dias << elemento.data << " "<< elemento.dias_preco_aumentou << endl;
    }

    //criando o arquivo de saida "contagem" que contém o calculo da probabilidade de dias que teve o aumento do preço
    ofstream arq_probabilidade("contagem.txt");
    //valida se deu para abrir o arquivo criado
    if (not arq_probabilidade.is_open()) {
        cerr << "Algum erro ao abrir o arquivo ..." << endl;
        return 0;
    }
    // Percorre o vetor "probabilidade_aumento_preco" e escreve cada elemento no arquivo resultado
    for (auto elemento : probabilidade_aumento_preco) {

        // Arredonda o valor do elemento para 4 casas decimais
        elemento.probabilidade_dias = round(elemento.probabilidade_dias * 10000) / 10000;
        arq_probabilidade << elemento.dia << " " << fixed << setprecision(4) << elemento.probabilidade_dias << endl;
    }

Com o código finalizado e funcionando, acrescentamos possíveis funções para que a main não ficasse tão poluída:

//função que le os dados de entrada e armazena em um vetor do tipo "CotacaoAcoes"
vector<CotacaoAcoes>dados_entrada(ifstream * arq)

// função para calcular os dias com preço ascendente e armazenar em um vetor
vector<Resultado>dias_preco_ascendente(vector<CotacaoAcoes>&info_acoes)

// função para calcular a probabilidade de repetição de preço ascendente e armazenar o resultado em um vetor
vector<Contagem>calculo_probabilidade(vector<Resultado>&dia)

// função para ordenar o vetor de probabilidade e remover os valores repetidos
vector<Contagem>ordena_e_remove_rep(vector<Contagem>&probabilidade_aumento_preco)

Com isso, todos os testes resultaram em arquivos idênticos aos do professor.

julia-e2002 commented 1 year ago

3 de Abril de 2023

De forma inexplicável, o programa que funcionou ontem no windows, não funcionou no linux. Após testes que batiam com o resultado do professor, no linux mostrava um erro correspondente a memória. Conferimos e percebemos que havia um problema na pilha que armazenava os dias, devolvendo alguns valores negativos. Após o erro ser consertado, voltou a rodar e gerar os arquivos, porém com resultados totalmente diferentes.

A solução da função da pilha consertada:

// Função para calcular os dias com preço ascendente e armazenar em um vetor
vector<Resultado>dias_preco_ascendente(vector<CotacaoAcoes>&info_acoes){
    vector<Resultado>dia;
    //pilha para armazenar "o dia anterior mais próximo cujo preço de ação seja maior que o dia presente."
    stack<int>dias_preco_crescente;
    dias_preco_crescente.push(0);

    for (int i = 0; i < info_acoes.size(); ++i) {

        dia.push_back(Resultado());

        while (!dias_preco_crescente.empty() && info_acoes[dias_preco_crescente.top()].preco <= info_acoes[i].preco) {
            dias_preco_crescente.pop();
        }

        if (dias_preco_crescente.empty()) {
            dias_preco_crescente.push(i + 1);
            dia[i].dias_preco_aumentou = i + 1;
        } else {
            dia[i].dias_preco_aumentou = i - dias_preco_crescente.top();
            dias_preco_crescente.push(1 + i - dias_preco_crescente.top());

        }

        dias_preco_crescente.push(i);
        dia[i].data = info_acoes[i].data;
    }

    return dia;
}