argcv

codes and stuff

Fórmula resolutiva da equação do 2º grau

leave a comment »

Escrevi o seguinte algoritmo para a resolução de equações do segundo grau no domínio dos números reais (como exemplo, o programa resolve 4x²+13x+12 = 0).

/* Escrito por Renato. R. Leme, em 03/06/2012 */
/* e-mail: rntreisleme@gmail.com              */
/* site: https://argcv.wordpress.com           */

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

double *bhaskara (double a, double b, double c);

void main () {
    double *a;
    if (!(a = bhaskara (4, 13, 2)))
        printf ("A equação não pode ser resolvida no domínio dos Reais.\n");
    else
        printf ("x'  = %.2f \nx'' = %.2f\n", a[0], a[1]);
    free (a);
}

/* Esta função recebe a, b e c, de ax² + bx + c e retorna     */
/* um ponteiro para o primeiro número do conjunto de soluções */
/* da equação caso obtenha sucesso em resolvê-la no conjunto  */
/* dos números reais. Retorna NULL caso contrário. */

double *bhaskara (double a, double b, double c) {
    double delta;
    double *solucao = malloc (2 * sizeof (double));
    delta = (b * b) - (4 * a * c);
    if (delta < 0) return NULL;
    solucao[0] = (- b - sqrt (delta)) / (2 * a);
    solucao[1] = (- b + sqrt (delta)) / (2 * a);
    return solucao;
}

Até mais!

Anúncios

Written by rntreis

junho 3, 2012 at 1:49 pm

Publicado em C, dicas, programação

Fibonacci com apenas uma chamada recursiva

leave a comment »

Uma solução clássica para o problema de encontrar um número da sequência de Fibonacci com um algoritmo recursivo é a seguinte:

int calculaFibonacci (int n) {
    if (n < 2) return n;
    else return calculaFibonacci (n - 1) + calculaFibonacci (n - 2);
}

Entretanto, é sabido que duas chamadas recursivas podem pesar bastante.

Pensando nisso, eu escrevi uma solução que usa uma só chamada recursiva aliada a um vetor. Para isso, ao invés de começar os cálculos por n, a função começa por i, que vale 2. A lógica disso é que, sabendo v[i-2] = 0 e v[i-1] = 1, eu posso determinar v[i] (que é v[i-2] + v[i-1]), e, assim, determinar v[i+1…n], usando uma chamada recursiva para cada v[i], até que i seja igual a n e a função tenha achado o que se pede, que é sempre v[n].

Para conseguir o efeito de começar a calcular por i = 2 e usar um vetor v[n] sem que, quando quiser encontrar o número de Fibonacci preterido o usuário da função tenha que especificar esses dois dados à função sem qualquer motivo aparente, eu criei uma função chamada fibonacci(), que funciona como um pacote, simplesmente criando v[n], especificando os dois valores iniciais para v[] e chamando calculaFibonacci() com n, i = 2 e v.

Eis, então, o algoritmo.

#include <stdio.h>

int fibonacci (int n);
int calculaFibonacci (int n, int i, int v[]);

void main () {
    int a = fibonacci (40);
    printf ("%d\n", a);
}

/*  Esta função recebe n >= 0 e devolve o número  */
/*  de fibonacci presente na (n+1)-ésima posição. */

int fibonacci (int n) {
    int v[n];
    v[0] = 0; v[1] = 1;
    return calculaFibonacci (n, 2, v);
}

/*  A função abaixo recebe n >= 0, i = 2 e v[].  */
/*  Preenche o subvetor v[2...n] e retorna v[n]  */
/*  para a função chamadora.                     */

int calculaFibonacci (int n, int i, int v[]) {
    if (i >= n) return ((n == 0) ? 0 : v[i-1] + v[i-2]);
    else v[i++] = v[i-1] + v[i-2];
    calculaFibonacci (n, i, v);
}

Até mais.

Written by rntreis

junho 2, 2012 at 1:29 pm

Publicado em C, dicas, programação

A função system()

leave a comment »

Uma função bastante interessante que temos em C é system(), cujo protótipo encontra-se no arquivo-cabeçalho stdlib.h e é o que se segue:

int system (const char *string)

Com ela, você pode chamar comandos do sistema em seu programa. Por exemplo, a seguinte chamada

system ("dir");

devolve o conteúdo da pasta na qual o seu programa está.

Para exemplo simples, fiz um programinha que faz uso do pacman do Arch Linux através de system(). Confira.

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

void main() {
    char nome[100];
    char comando[200] = "sudo pacman -S ";

    printf("Digite o nome do programa: ");
    gets(nome);

    strcat(comando, nome);

    printf("\n");

    system(comando);
}

É fácil perceber que com uma simples alteração no array comando podemos adaptar o programa para funcionar em outras distribuições (em Debian e derivados, poderíamos usar “sudo apt-get install “, por exemplo).

Até mais.

Written by rntreis

maio 31, 2012 at 11:33 am

Publicado em C, dicas, programação

Cena de “A Dog’s Life”

leave a comment »

Um pouco da sétima arte, com Charles Chaplin.

 

😀

Written by rntreis

maio 31, 2012 at 11:09 am

Publicado em cinema

Multiplicação de matrizes

leave a comment »

Para quebrar o silêncio, compartilho uma função em C que criei que multiplica matrizes. Já está dentro do programinha de teste que se segue, com duas matrizes a serem multiplicadas e o for que imprime a matriz resultante.

Repare que eu utilizo calloc ao invés de malloc. Isso porque, ao contrário de malloc, que devolve um ponteiro para uma sequência de “lixos” na memória, calloc já devolve um ponteiro para uma sequência de zeros. Isso é uma vantagem para mim, pela lógica que utilizei e que pode ser verificada na função.
 

 /*
 * Algoritmo de multiplicação de matrizes.
 * Escrito por Renato R. Leme em 22/05/2012.
 * e-mail: rntreisleme@gmail.com
 * site: https://argcv.wordpress.com */

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

int **mmatriz (int l1, int c1, int l2, int c2, int A[l1][c1], int B[l2][c2]);

void main() {
    int i, j;
    int A[2][3] = {{2, 5, 9}, {3, 6, 8}};
    int B[3][2] = {{2, 7}, {4, 3}, {5, 2}};
    int **AB;

    if (!(AB = mmatriz (2, 3, 3, 2, A, B)))
        printf("Matrizes inválidas!\n");

    for (i = 0; i < 2; i++) {
        for (j = 0; j < 2; j++) printf("%d ", AB[i][j]);
            printf("\n");
    }
}

/* Esta função recebe os inteiros l1, c1, l2, c2, e as matrizes A[l1][c1] e B[l2][c2].
 * Se c1 = l2, é devolvida uma matriz AB[l1][c2], tal que AB = A*B. Caso c1 != l2,
 * a função devolve 0. */

int **mmatriz (int l1, int c1, int l2, int c2, int A[l1][c1], int B[l2][c2]) {
    if (c1 != l2) return 0;
    else {
        int linha = 0, coluna = 0, i, j;
        int **AB;
        AB = calloc (l1, sizeof(int));
        for (i = 0; i < c2; i++) *(AB+i) = calloc (c2, sizeof(int));

        for (linha = 0; linha < l1; linha++) {
            for (i = 0; i < c2; i++) {
                for (j = 0; j < c1; j++) AB[linha][coluna] += (A[linha][j] * B[j][coluna]);
                coluna++;
            }
            coluna = 0;
        }

        return AB;
    }
}

Até mais!

Written by rntreis

maio 22, 2012 at 7:28 pm

Publicado em C

Strcat() “caseira”

leave a comment »

A função strcat(), cujo protótipo se encontra no arquivo de cabeçalho string.h, recebe str1 e str2 e devolve str1, com o conteúdo de str2 copiado para o seu final. str2 não é alterada. Observe seu protótipo:

char *strcat(char *str1, const char *str2);

Naturalmente, em um programa em que essa função se faz necessária, é melhor que você a use direto. Não há nenhum motivo para reinventar a roda.

Mas como exercício pode ser interessante fazer uma versão própria da função, pra ter uma ideia legal de como ela pode funcionar.

Pensando nisso é que a sua construção é proposta em um exercício da apostila do Curso de Linguagem C, da UFMG (ótima apostila, aliás). E eu resolvi fazer. E se interessar a alguém, cá está, já inserida em um programinha para que ela possa ser testada.

 
#include <stdio.h>
#include <string.h>

char *strcat_caseira(char *str1, const char *str2);

void main() {
    char str1[80] = "isto é";
    char str2[80] = " um teste!";

    strcat_caseira(str1, str2);

    printf("%s\n\n", str1);
}

char *strcat_caseira(char *str1, const char *str2) {
    int i = strlen(str1), j;

    for (j = 0, i; str2[j]; j++, i++) str1[i] = str2[j];
    str1[i] = '\0'; // coloca o terminador nulo em str1

    return str1;
}

Até mais.

Written by rntreis

abril 18, 2012 at 8:26 pm

Publicado em C, dicas, programação

Jogo da velha 2.0 – No Country For Old Men

with one comment

Quando terminei de escrever aquele joguinho da velha, um fato ficou me perturbando: a CPU perdia com muita facilidade.

Daí eu resolvi ensinar a ela uns truques, e criei quatro níveis para o jogo: Noob, Médio, Gladiador e Zeus. Sendo que o último, dizem as más línguas, é impossível de se vencer.

Também adaptei a função mostra_tabuleiro() para apresentar tabuleiros que condizem mais com um de verdade. O “1” do player foi substituído pelo “X” e o “2” da CPU foi substituído pelo “O”.

Percebam também que eu adicionei a função __fpurge() em algumas ocasiões. Isso porque sem ela alguns bugs estavam sendo provocados em situações em que havia interação com o usuário.

Se você usa Windows (tsc tsc) deverá trocar o __fpurge() por fflush().

O código-fonte segue abaixo. E também está no pastebin.

/* ***********************************
   * Autor: Renato R. Leme
   * Data: 14/04/2012 (atualizado em 17/04/2012)
   * e-mail: rntreisleme@gmail.com
   * site: https://argcv.wordpress.com
   ***********************************
   Qualquer dúvida ou sugestão, pode entrar em contato comigo pelo meu e-mail
   ou pelo meu blog.
*/

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

#define LINHAS  3
#define COLUNAS 3
#define CASAS   9

void init_tabuleiro(void);
void mostra_tabuleiro(void);
void jogada_player(void);
void jogada_cpu(int rodada);
int update_tabuleiro(int x, int y); // retorna 0 se a operação for bem sucedida
int testa_vencedor(void); // 2 - vitória cpu, 1 - vitória player, 0 - nada aconteceu
int velha(void); // conta o número de casas vazias no tabuleiro

enum vez { PLAYER, CPU } jogador;
enum niveis { NOOB, MEDIO, GLADIADOR, ZEUS } nivel;

int tabuleiro[LINHAS][COLUNAS];

void main() {
    int dificuldade, escolha, status;
    static int rodada;
    rodada = 0;
    jogador = PLAYER; // seta o primeiro jogador para player
    init_tabuleiro(); // inicia o tabuleiro com 0s

    while(1) {
        __fpurge(stdin); // limpa o buffer do teclado
        printf("\nEscolha o nível em que deseja jogar \n(1 - Noob, 2 - Médio, 3 - Gladiador, 4 - Zeus): ");
        scanf("%d", &dificuldade);
        if (dificuldade == 1) { nivel = NOOB; break; }
        else if (dificuldade == 2) { nivel = MEDIO; break; }
        else if (dificuldade == 3) { nivel = GLADIADOR; break; }
        else if (dificuldade == 4) { nivel = ZEUS; break; }
        else printf("\nEscolha invalida!");
    }

    while(1) {
        ++rodada;
        if (jogador == PLAYER) {
            if (!velha()) break;
            mostra_tabuleiro();
            jogada_player();
            status = testa_vencedor();
            if (status) break;
        }
        if (jogador == CPU) {
            if (!velha()) break;
            jogada_cpu(rodada);
            status = testa_vencedor();
            if (status) break;
        }
    }

    mostra_tabuleiro();

    if (status == 1) printf("\nParabéns, você venceu!\n");
    else if (status == 2) printf("\nVocê perdeu! :(\n");
    else printf("\nDeu velha!\n");

    while(1) {
        __fpurge(stdin);
        printf("\nJogar novamente? (1 = sim / 2 = não) : ");
        scanf("%d", &escolha);
        if (escolha == 1) main();
        else if (escolha == 2) exit(0);
        else printf("\nEscolha invalida!");
    }
}

void init_tabuleiro() {
    register int i;
    int *p;
    p = (int *) tabuleiro;

    for (i = 0; i < CASAS; i++ ) *(p+i) = 0;
}

int velha() {
    register int i;
    int *p, zeros = 0;
    p = (int *) tabuleiro;

    for (i = 0; i < CASAS; i++ ) if (*(p+i) == 0) zeros++;

    if (!zeros) return 0;
    else return 1;
}

void mostra_tabuleiro() {
    register int i, j;
    char m_tabuleiro[LINHAS][COLUNAS];

    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            if (tabuleiro[i][j] == 0) m_tabuleiro[i][j] = ' ';
            if (tabuleiro[i][j] == 1) m_tabuleiro[i][j] = 'X';
            if (tabuleiro[i][j] == 2) m_tabuleiro[i][j] = 'O';
        }
    }

    printf("\n");

    for (i = 0; i < 3; i++) {
        for (j = 0; j < 3; j++) {
            if (i < 2) printf("|_%c_|", m_tabuleiro[i][j]);
            else printf("| %c |", m_tabuleiro[i][j]);
        }
        printf("\n");
    }
}

int update_tabuleiro(int x, int y) {
    if (jogador == PLAYER) {
            tabuleiro[x][y] = 1;
            jogador = CPU;
            return 0;
        }
    if (jogador == CPU) {
        if (tabuleiro[x][y] != 0) return 1;
        else {
            tabuleiro[x][y] = 2;
            jogador = PLAYER;
            return 0;
        }
    }
}

void jogada_player() {
    int x, y;
    __fpurge(stdin);
    printf("\nDigite a linha e a coluna em que deseja jogar: ");
    scanf("%d %d", &x, &y);

    x--, y--;

    if (tabuleiro[x][y] != 0 || x < 0 || x > 2 || y < 0 || y > 2) {
        printf("\nJogada inválida.\n");
        jogada_player();
    }
    else update_tabuleiro(x, y);
}

void jogada_cpu(int rodada) {
    register int i;
    int x, y;
    static int diagonais; // será alterada caso o player comece a jogar pelas diagonais
    int ad; // ataque e defesa. Quando 'ad' vale 2, a cpu testa a possibilidade de ataque.
            // se valer 1, ela testa por defesa.

    diagonais = (rodada == 1) ? 0 : diagonais; // será zerada toda vez que o jogo reinicia

    // série de testes que verificará se há possibilidade de o jogador ou
    // a CPU vencer o jogo em alguma linha, alguma coluna ou alguma diagonal.
    // serão executados de acordo com o nivel do jogo.

    if (nivel == MEDIO || nivel == GLADIADOR || nivel == ZEUS) {
        for (ad = 2; ad >= 1; ad--) {
            for (i = 0; i < 3; i++) { // para todas as linhas e colunas
                if (tabuleiro[i][1] == ad && tabuleiro[i][2] == ad) if (!update_tabuleiro(i, 0)) return;
                if (tabuleiro[i][0] == ad && tabuleiro[i][2] == ad) if (!update_tabuleiro(i, 1)) return;
                if (tabuleiro[i][0] == ad && tabuleiro[i][1] == ad) if (!update_tabuleiro(i, 2)) return;
                if (tabuleiro[1][i] == ad && tabuleiro[2][i] == ad) if (!update_tabuleiro(0, i)) return;
                if (tabuleiro[0][i] == ad && tabuleiro[2][i] == ad) if (!update_tabuleiro(1, i)) return;
                if (tabuleiro[0][i] == ad && tabuleiro[1][i] == ad) if (!update_tabuleiro(2, i)) return;
            }

            // para as diagonais
            if (tabuleiro[0][0] == ad && tabuleiro[2][2] == ad) if (!update_tabuleiro(1, 1)) return;
            if (tabuleiro[0][2] == ad && tabuleiro[2][0] == ad) if (!update_tabuleiro(1, 1)) return;
            if (tabuleiro[0][2] == ad && tabuleiro[1][1] == ad) if (!update_tabuleiro(2, 0)) return;
            if (tabuleiro[2][2] == ad && tabuleiro[1][1] == ad) if (!update_tabuleiro(0, 0)) return;
            if (tabuleiro[2][0] == ad && tabuleiro[1][1] == ad) if (!update_tabuleiro(0, 2)) return;
            if (tabuleiro[0][0] == ad && tabuleiro[1][1] == ad) if (!update_tabuleiro(2, 2)) return;
        }

        if (nivel == GLADIADOR || nivel == ZEUS) { // testes que evitam jogadas do player
            if (rodada == 1 && tabuleiro[1][1] == 1) if (!update_tabuleiro(2, 0)) return;
            if ((!diagonais && rodada == 2) && tabuleiro[0][2] == 1) if (!update_tabuleiro(0, 0)) return;

            if (tabuleiro[0][1] == 1  || tabuleiro[1][0] == 1 || tabuleiro[1][2] == 1 || tabuleiro[2][1] == 1) {
                if (rodada == 1 && !update_tabuleiro(1, 1)) return;
                if (rodada == 2) {
                    if (tabuleiro[1][2] == 1 || tabuleiro[1][0] == 1) {
                        if (tabuleiro[2][0] == 1 && !update_tabuleiro(2, 2)) return;
                        if (tabuleiro[0][0] == 1 && !update_tabuleiro(0, 2)) return;
                        if (tabuleiro[0][1] == 1 && !update_tabuleiro(0, 0)) return;
                        if (tabuleiro[2][1] == 1 && !update_tabuleiro(2, 0)) return;
                    }
                    if (tabuleiro[0][1] == 1 || tabuleiro[2][1] == 1) {
                        if ((tabuleiro[2][0] == 1 || tabuleiro[0][0] == 1) && !update_tabuleiro(1, 2)) return;
                        if ((tabuleiro[2][2] == 1 || tabuleiro[0][2] == 1) && !update_tabuleiro(1, 0)) return;
                    }
                }
            }
        }

        if (nivel == ZEUS) { // ultimo nivel de testes para evitar jogadas
            if (tabuleiro[0][0] == 1 || tabuleiro[0][2] == 1 || tabuleiro[2][0] == 1 || tabuleiro[2][2] == 1) {
                diagonais++;
                if (!update_tabuleiro(1, 1)) return;
                if (rodada == 2) if (!update_tabuleiro(1, 0)) return;
            }
        }
    }

    // caso nenhum dos testes acima sejam satisfeitos, a cpu joga aleatoriamente

    srand(time(NULL));

    while(1) {
        x = rand() % 3;
        y = rand() % 3;
        if (!update_tabuleiro(x,y)) return;
    }

}

int testa_vencedor() {
    register int i;
    int a = (jogador == CPU) ? 1 : 2; // 'a' varia de acordo com quem o chama (player ou cpu)

    for (i = 0; i < 3; i++) if (tabuleiro[i][0] == a && tabuleiro[i][1] == a && tabuleiro[i][2] == a) return a;
    for (i = 0; i < 3; i++) if (tabuleiro[0][i] == a && tabuleiro[1][i] == a && tabuleiro[2][i] == a) return a;
    if (tabuleiro[2][0] == a && tabuleiro[1][1] == a && tabuleiro[0][2] == a) return a; 
    if (tabuleiro[0][0] == a && tabuleiro[1][1] == a && tabuleiro[2][2] == a) return a;

    return 0; // se não houver retorno até aqui, é sinal de que ninguém venceu. Portanto, a função retorna 0
}

Written by rntreis

abril 18, 2012 at 8:00 am

Publicado em C, jogos, programação