1. Strings (3 valores)

Defina uma função int capitaliza (char txt[]) que, dada uma string onde está armazenada um texto, substitui a primeira letra de cada palavra pela correspondente letra maiúscula. Considere que uma palavra começa numa letra que está no inicio da string ou imediatamente após um espaço. Por exemplo, se a string for “Muito bom dia” a função deve transformá-la em “Muito Bom Dia”. A função deve retornar o número de caracteres alterados.

int capitaliza (char txt[]){
	int i = 1, s = strlen(txt) - 1, conta = 0;
	for (; i < s; i++){
		if(txt[i] == ' '){
			txt[i++] += 32;
			conta ++;
		}
	}
	return conta;
}
int capitaliza(char txt[]){
	int i = 0; s = strlen(txt) - 1, conta = 0;
	for(; i < s; i++){
		if(txt[i] == ' ' && txt[i +  1] > 'a' && txt[i + 1] <= 'z')
		txt[i + 1]-= 32;
		conta ++;
	}
	return conta;
}

2. Arrays (3 valores)

Defina uma função int maxSomaK (int a[], int N, int k) que, dado um array a com N elementos e um número k , calcula a máxima soma que é possível obter com k elementos consecutivos do array. Por exemplo, para o array {1, 3, -1, 7, 5, -2, 8, 3, 4} com 10 elementos, a invocação da função para 4 = 4 como resultado 14 correspondendo à soma dos elementos {5, -2, 8, 3}

int maxSomaK(int a[], int N, int k){
	int r = 0, soma = 0;
	for(int i = 0; i < N; i++){
		soma = 0;
		for(int j = 0; j < k; j ++){
			soma += v[(i + j) % N]; 
		}
		if(soma > r) r = soma;
	}
	return soma;
}
int maxSomaK(int a[], int N, int k){
	int r = -999999;
	int soma;
	for(int i = 0; i <= N - k; i++){
		soma = 0;
		for(int j = 0; j < k; j++) soma += a[i + j];
	}
	if (soma > r) r = soma;
	return r;
}

3. Ordenação de arrays (2 + 2 = 4 valores)

1.

Defina a função int mergeSemRep(int a[], int na, int b[], int nb, int r[]) que, dados dois arrays ordenados sem repetições (a com na elementos e b com nb elementos) preenche o array r com os elementos dos arrays a e b, ordenado por ordem crescente e sem repetições. A função retorna o número de elementos que foram escritos em r.

int mergeSemRep(int a[], int na, int b[], int nb, int r[]){
	int ia = 0, ib = 0;
	for(int i = 0; ia < na && ib < nb; i++){
		if(a[ia] <= b[ib]){
			r[i] = a[ia];
			ia++;
			i++;
		} else {r = b[ib]; ib++; i++;}
	} i++;
	if(ia < na){
		while(i < na){r[i++] = a[na++];}
	}
	else {while(ib < nb){r[i++] = b[nb++];}}
	return i;
}
int mergeSemRep(int a[], int na, int b[], int nb, int r[]){
	int ia = 0, ib = 0, ir = 0;
	while(ia < na && ib < nb){
		int menor;
		if (a[ia] < b[ib]) menor = a[ia++];
		else if (b[ib] < a[ia]) menor = b[ib++];
		else { 
			menor = a[ia++]; 
			ib++; 
        }
		if(ir == 0 || r[ir - 1] != menor) r[ir++] = menor;
	}
	while(ia < na){
		if(ir == 0 || r[ir - 1] != a[ia]) r[ir++] = a[ia];
		ia++;
	}
	while(ib < nb){
		if(ir == 0 || r[ir - 1] != b[ib]) r[ir++] = b[ib];
		ib++;
	}
	return ir;
}

2.

Defina uma função int mSort(int v[], int N), uma variante da função mergeSort estudada, que ordena um array de N inteiros retirando as repetições. A função deve retornar o número de elementos.

 
int mSort(int v[], int N){
	if(N < 2) return N;
	int meio = N / 2;
	int tamEsq = mSort(v, meio);
	int tamDir = mSort(v + meio, N - meio);
	int *temp = malloc((tamEsq + tamDir) * sizeof(int));
	int novoTamanho = mergeSemRep(v, tamEsq, v + meio, tamDir, temp);
	for(int i = 0; i < novoTamanho; i++) v[i] = temp[i];
	free(temp);
	return novoTamanho;
}

4. Lista ligadas (3 valores)

Defina uma função int contido(int v[], int N, LInt l) que dado um array v com N elementos (ordenado e sem repetições) e uma lista ordenada l, testa se todos os elementos do array existem na lista. A função deve retornar 1 se todos os elementos de v existem na lista l, e 0 caso contrario.

typedef struct no{
	int valor;
	struct no *prox;
} *LInt;
int contido(int v[], int N, LInt l){
	for(int i = 0; i < N; i++){
		int flag = 1;
		while(!flag){
			if(v[i] == l->valor) flag = 0;
			else if(v[i] < a->valor) return 0;
			else l = l->prox;
		}
	}
	return 1;
} 
int contido(int v[], int N, LInt l){
	int i = 0;
	while(i < N && l != NULL){
		if(v[i] == l->valor) i++;
		else if(v[i] > l->valor) l = l->prox;
		else return 0;
	}
	return (i == N) ? 1 : 0;
}
 

5. Lista ligadas (4 valores)

Defina uma função int removeMuitos(LInt *l, int v[], int N) que retira da lista *l os elementos que estão no array v. Assuma que tanto a lista como o array estão ordenados e que o array não tem elementos repetidos. A função deve devolver o número de elementos removidos.

int removeMuitos(LInt *l, int v[], int N){
	int conta = 0;
	for(int i = o; i < N; i++){
		while(*l != NULL){
			*l = (*l)->prox;
			conta++;
		}
		l = &((*l)->prox);
	}
	return conta;
}
int removeMuitos(LInt *l, int v[], int N){
	int conta = 0, i = 0;
	while(*l != NULL && i < N){
		if((*l)->valor < v[i]) l = &((*l)->prox);
		else if((*l)->valor == v[i]){
			LInt temp = *l;
			*l = (*l)->prox;
			free(temp);
			conta++;
		}
		else i++;
	}
	return conta;
}

6. Árvores binárias (3 valores)

Relembre a definição (recursiva) da função ABin insere(ABin a, int x) de inserção de um elementos numa árvore binária de procura. Considere agora que em cada nodo das árvores é ainda armazenada a altura da árvore que se inicia (i.e., que tem raiz) nesse nodo. A árvore em baixo exemplifica uma destas árvores (em cada nodo aparece valor; altura) Adapte a função de inserção de um novo elementos para esta nova definição de árvores binárias de procura. Note que esta inserção pode ter que alterar a informação (campo altura) de alguns nodos da árvore. Por exemplo, a inserção de 10 não altera os outros nodos da árvore. Por outro lado, a inserção de 7 irá alterar a informação de 4 dos nodos da árvore (12, 6, 9 e 8).

typedef struct abin{
	int valor;
	int altura;
	struct abin *esq, *dir;
} *ABin;
void restaAltura(ABin a){
	if(a != NULL) a->altura --;
	restaALtura(a->esq);
	restaAltura(a->dir);
}
ABin insere(ABin a, int x){
	ABin aux = a;
	while(a->esq != NULL && a->dir != NULL){
		if(x < a->valor){
			a = a->esq;
		}
		else a = a->dir;
	}
	ABin nova = malloc(sizeof(struct abin));
	nova->valor = x;
	nova->esq = NULL; 
	nova->dir = NULL;
	nova->altura = (a->altura) - 1;
	(a->esq == NULL) ? (a->esq = nova) : (a->dir = nova);
	if(nova->altura == 1){
		nova->altura++;
		restaAltura(aux);
	}
	return aux;
}
ABin insere(ABin a, int x){
	if(a == NULL){
		ABin nova = malloc(sizeof(struct abin));
		nova->valor = x;
		nova->altura = 1;
		nova->esq = NULL;
		nova->dir = NULL;
		return nova;
	}
	if(x < a->valor) a->esq = insere(a->esq, x);
	else if(x > a->valor) a->dir = insere(a->dir, x);
	else return a;
	int altEsq = (a->esq != NULL) ? a->esq->altura : 0;
	int altDir = (a->dir != NULL) ? a->dir->altura : 0;
	a->altura = 1 + ((altEsq > altDir) ? altEsq : altDir);
	return a;
}