Universidade Estadual de Campinas INSTITUTO DE COMPUTAÇÃO MC 102 – Algoritmos e Programação de Computadores TURMAS I, J, K e L Lista de Exercícios III (Data de entrega: 10/12/2009) 01 - Desconsidere o conhecimento da função sqrt na linguagem C. Uma forma de se obter a raiz quadrada de um número qualquer x seria através de busca binária. Assuma que a raiz quadrada de x está entre 0 e x (Se o número for negativo, retorne 0). Para sabermos se um palpite y é a raiz quadrada de x, basta testar se y*y é próximo o suficiente de x ou, em outras palavras, se o módulo da diferença entre eles está dentro de uma tolerância definida. Caso contrário, podemos restringir a busca entre 0 e y ou entre y e x. Escreva a função abaixo que implemente este algoritmo, considerando 10-6 como tolerância para o cálculo do resultado. double raiz(double x) 02 - Faça um programa que leia n nomes inserindo-os em uma lista de forma ordenada utilizando a idéia do algoritmo da inserção. No final, o programa deve mostrar todos os nomes ordenados alfabeticamente. 03 - Crie um programa que dado uma string, coloque as letras dela em ordem crescente pelo algoritmo da bolha. 04 - Faça um programa que leia n nomes e ordene-os pelo tamanho utilizando o algoritmo da seleção. No final, o algoritmo deve mostrar todos os nomes ordenados. 05 - Faça um programa que contêm uma função recursiva que calcula o valor de m a partir de um vetor de números reais V com tamanho N e um valor λ . Assuma 0 < λ < 1. N −1 m = N −t V t ∑ t =0 06 - Faça um programa que contêm uma função recursiva que calcula a média aritmética dos elementos de um vetor de números reais V com tamanho N. 07 - Faça um programa que contêm uma função recursiva que determina o maior e o menor elemento de um vetor de inteiros V de tamanho N. 08 - Faça um programa que contêm uma função recursiva que imprime uma string com as letras em ordem invertida. Entrada: Bom dia Saída: aid moB 09 - Calcular a representação binária de um número consiste em realizar sucessívas divisões deste número por 2 e, quando seu resto for menor que 2, imprimir do último para o primeiro, todos os restos das divisões. Por exemplo: 6 / 2 = 3 (resto 0) => 3 / 2 = 1 (resto 1) => 1 / 2 = 0 (resto 1) 6 em binário = 110 Desenvolva a função recursiva para o cálculo da representação binária de um inteiro positivo n qualquer. 10 - Considere a seguinte estrutura: typedef struct pessoa { unsigned int RA; float Nota;} Aluno; Faça uma função que, dado um valor inteiro N positivo, aloque dinâmicamente um vetor de Aluno, leia do teclado os N pares de valores (RA, Nota) e retorne o vetor alocado. Imprima, ao final do programa, a lista dos alunos ordenada por nota final (use algum algoritmo recursivo de ordenação dado em aula). 11 - Faça um programa que leia n nomes e ordene-os pelo tamanho utilizando o algoritmo mergesort. No final, o algoritmo deve mostrar todos os nomes ordenados. 12 - Crie um programa que dado uma string, coloque as letras dela em ordem crescente pelo algoritmo quick-sort. 13 - Um programador escreveu o programa abaixo, utilizando apontadores. Entretanto, ele esqueceu de marcar quais variáveis devem ser apontadores e quais devem ser inteiros normais. Separe as variáveis rotuladas de a1 a a10 em dois grupos: variáveis que devem ser apontadores para inteiros e variáveis que devem ser inteiros. #include <stdio.h> #include <stdlib.h> int main (void) { int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10; int vetor[2]; vetor[0] = 0; vetor[1] = 1; a1 = malloc (sizeof(int) * 2); a2 = a1; a3 = *a2; a4 = &a5; *a4 = 5; a6 = a1++; a7 = a3; a8 = a5++; a9 = a1[1]; a1[0] = vetor[1]; a10 = vetor; return 0; } 14 - Faça um programa que receba como entrada as coordenadas de 2 pontos em um espaço de N dimensões, dados por 2 vetores de float com tamanho N. Em seguida, o programa deverá calcular a distância euclidiana entre eles. Faça um programa, de modo que o usuário possa repetir o cálculo para diversos pares de pontos, inclusive com variação do valor N. Utilize alocação dinâmica de memória e ponteiros e não se esqueça de desalocar a memória quando necessário. ∑ N d x , y = x i − y i 2 i =1 15 - Faça um programa que receba 2 strings, que podem ser de tamanhos distintos de tamanho máximo N. Faça um programa para determinar o número de caracteres em comum (sem contar ‘\0’). O programa deverá permitir que o usuário repita o cálculo para diversos pares de strings, inclusive com variação do valor N. Utilize alocação dinâmica de memória e ponteiros e não se esqueça de desalocar a memória quando necessário. 16 - Uma marcenaria encomendou a você um programa para gerenciar a sua produção. A marcenaria produz n tipos de móveis. Cada modelo é designado por uma sigla de 5 caracteres e demanda uma quantidade específica de madeira (em metros quadrados) e parafusos (em unidades) para ser feito. Além disso, cada modelo dá uma certa quantia de lucro à empresa. O programa deverá inicialmente ler o número de produtos produzidos e fazer o cadastro dos mesmos com o uso de um vetor alocado dinamicamente. Para isso, utilize a seguinte estrutura: typedef struct cadastro{ char nome[6]; float madeira; int parafusos; float lucro; }s_cadastro; O programa também deverá armazenar o planejamento de produção para até T dias, ou seja, deverá armazenar a quantidade de cada produto a ser produzido em cada dia do plano do período de tempo desejado. Faça isso com o uso de uma matriz alocada dinamicamente em que cada linha é associada a um tipo de móvel e cada coluna a um dia do planejamento. O número de dias considerados no plano deve ser informado imediatamente antes da inserção do plano de produção. Após a entrada dos dados acima, o programa deverá ser capaz de informar a quantidade de madeira utilizada em cada dia, a quantidade de parafusos utilizada durante o período e o lucro gerado por cada modelo durante o período. O programa deverá conter funções específicas para: - Realizar o cadastro dos produtos - Realizar a leitura do planejamento de produção - Exibir as informações solicitadas. Exemplo: Entrada: 3 MX001 3.0 10 10.00 (quantidade de produtos) (nome do produto 1) (quantidade de madeira do produto 1) (quantidade de parafusos do produto 1) (lucro do produto 1) MX002 (nome do produto 2) 4.0 (quantidade de madeira do produto 2) 30 (quantidade de parafusos do produto 2) 20.00 (lucro do produto 2) NX054 (nome do produto 3) 3.2 (quantidade de madeira do produto 3) 15 (quantidade de parafusos do produto 3) 15.50 (lucro do produto 3) 7 (quantidade de dias) 1 0 0 1 0 1 3 (plano de produção do produto 1) 3 3 1 0 2 5 2 (plano de produção do produto 2) 1 1 0 0 1 1 1 (plano de produção do produto 3) Saída: Quantidade de madeira utilizada em cada dia Dia 1: 18.2 Dia 2: 15.2 Dia 3: 4.0 Dia 4: 3.0 Dia 5: 11.2 Dia 6: 26.2 Dia 7: 20.2 Quantidade de parafusos utilizados durante a semana: 615 Lucro gerado por cada modelo durante a semana: MX001: 60.00 MX002: 320.00 NX054: 77.50 17 - Considere uma estrutura chamada Ponto (composta por valores x e y) e uma estrutura chamada POLIGONO (composta por uma lista ligada de pontos). Faça uma função que leia um polígono do teclado e outra que dado um polígono, classifique-o de acordo com o número de pontos que ele contém: triângulo, quadrilátero, pentágono, hexágono, heptágono, octógono, eneágono, decágono ou outro para mais de 10 lados. 18 - Com o uso das funções descritas a seguir, faça o cadastro dos produtos de um supermercado por código, preço e nome. Utilize se necessário: struct produto { int codigo; float preco; char nome[100]; }; Será implementado um cadastro (por meio de 2 programas diferentes) e os programas devem ser capazes de armazenar ou recuperar os dados cadastrados com o uso de arquivos. O primeiro deverá conter as seguintes funções: le_dados_do_teclado(): recebe do teclado os dados requeridos pelo cadastro e os armazena em um arquivo em formato de texto. O número de elementos cadastrados não deve ser armazenado no arquivo. escreve_dados_na_tela() : lê o conjunto de dados armazenados em um arquivo de texto e lista as informações do cadastro na tela do computador. Dica: Utilize as funções fscanf, fprintf e feof. O segundo programa deverá conter as seguintes funções: le_dados_do_teclado_bin(): recebe do teclado os dados requeridos pelo cadastro e os armazena em um arquivo em formato binário (utilize registros). O número de elementos cadastrados não deve ser armazenado no arquivo. escreve_dados_na_tela_bin(): lê o conjunto de dados armazenados em um arquivo binário e lista as informações do cadastro na tela do computador. escreve_dados_n_esimo_bin(int n): mostra na tela do computador os dados do n-ésimo elemento do cadastro armazenado no arquivo binário. Caso a posição não exista o programa deverá escrever uma mensagem de erro na tela. Dica: Utilize as funções fread, fwrite, feof e fseek. 19 - Escreva uma função, que dado um vetor, passado como parâmetro, armazena em um arquivo um gráfico de barras com o seu conteúdo. O cabeçalho da função deve ser: void imprime_grafico(char nome arquivo[], int vetor[], int tamanho); Cada linha do arquivo contém o número n a ser impresso e uma barra que contém n vezes a letra “X” . Por exemplo, para o vetor {5, 6, 2, 4} teríamos o seguinte gráfico armazenado no arquivo: 5 | XXXXX 6 | XXXXXX 2 | XX 4 | XXXX 20 - Considere a estrutura abaixo utilizada para armazenar vetores no espaço R2 struct v {double x; double y; }; typedef struct v Vetor; (a) Escreva o corpo da função int li (Vetor a, Vetor b); que retorna 1 se os vetores forem linearmente independentes ou 0 caso eles sejam linearmente dependentes. Dois vetores são linearmente dependentes se existe uma constante α tal que A = αB. Se tal constante não existe, então os vetores são linearmente independentes. (b) Escreva o corpo de um programa que lê um conjunto de variáveis do tipo Vetor do arquivo texto “vetores.txt” e utiliza a função li para determinar e escrever no arquivo “li.txt” todos os pares de vetores linearmente independentes existentes arquivo de entrada. Considere que todos os valores informados são corretos e que nunca existe mais de 100 vetores no arquivo “vetores.txt”. Um exemplo de execução seria: Arquivo de Entrada: 1 2 2 4 3 5 Arquivo de Saída 1 2 e 3 5 sao LI 2 4 e 3 5 sao LI 21 - Implemente um programa que, dado um texto, armazene as palavras desse texto em uma lista ligada (ou seja, uma FRASE é uma lista ligada de palavras). Crie: - Uma função que converta uma cadeia de caracteres em uma lista de palavras; - Uma função que, dada uma FRASE, retorne o número de palavras que ela contem. - Uma função que, dada uma FRASE, imprima todo o seu conteúdo na tela. OBS: Considere apenas letras e números como entrada. 22 - Pilhas são listas de elementos onde o elemento removido é sempre aquele que foi inserido mais recentemente. Escreva duas funcões que manipulam pilhas (utilizando listas ligadas): void insere_pilha(int n) : insere o elemento n no topo da pilha. int remove_pilha() : remove um elemento do topo da pilha e retorna -1 se a lista estiver vazia. 23 - Escreva um programa que ordene os elementos de uma lista ligada simples de inteiros. Utilize o método de ordenação que você considerar mais conveniente. 24 - Um polinômio pode ser representado por uma lista ligada, onde cada nó representa um termo do polinômio com seu coeficiente e seu expoente, além do apontador para o próximo elemento do polinômio. A estrutura de cada nó segue abaixo: struct polinomio {float coef; float expo; struct polinomio* prox; }; typedef struct polinomio Polinomio; Escreva o corpo da função imprime polinômio, que imprime o conteúdo do polinômio na tela. Considere que não há termos nulos (ou seja, que o coeficiente é sempre diferente de zero) e que os expoentes não se repetem ao longo da lista ligada. O cabeçalho da função é: void imprime polinomio(Polinomio *p)