diff --git a/2ano/1semestre/aed/setup.sh b/2ano/1semestre/aed/setup.sh index a35e61b..7c3702e 100755 --- a/2ano/1semestre/aed/setup.sh +++ b/2ano/1semestre/aed/setup.sh @@ -3,8 +3,8 @@ parent_path=$( cd "$(dirname "${BASH_SOURCE[0]}")" || exit ; pwd -P ) cd "$parent_path" || exit -if [ $# -ne 1 ]; then - echo "Usage: $0 " +if [ $# -lt 1 ] || [ $# -gt 2 ]; then + echo "Usage: $0 [debug|memcheck]" exit 1 fi @@ -13,6 +13,16 @@ if [ ! -f "$1" ]; then exit 1 fi +if [ "${1: -2}" != ".c" ]; then + echo "File $1 is not a C source file" + exit 1 +fi + +if [ ! -x "$(command -v gcc)" ]; then + echo "gcc is not installed" + exit 1 +fi + out_dirname=$(dirname "$1") out_basename=$(basename "$1") @@ -30,4 +40,30 @@ if [ $? -ne 0 ]; then exit 1 fi +if [ ! -f "out/$out_dirname/${out_basename%.*}" ]; then + echo "Compilation failed" + exit 1 +fi + +if [ $# -eq 2 ]; then + if [ "$2" == "debug" ]; then + if [ ! -x "$(command -v gdb)" ]; then + echo "gdb is not installed" + exit 1 + fi + gdb "out/$out_dirname/${out_basename%.*}" "out/$out_dirname/${out_basename%.*}.core" -tui + exit 0 + elif [ "$2" == "memcheck" ]; then + if [ ! -x "$(command -v valgrind)" ]; then + echo "valgrind is not installed" + exit 1 + fi + valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes "out/$out_dirname/${out_basename%.*}" + exit 0 + else + echo "Usage: $0 [debug|memcheck]" + exit 1 + fi +fi + out/"$out_dirname"/"${out_basename%.*}" diff --git a/2ano/1semestre/aed/teoricas/README.md b/2ano/1semestre/aed/teoricas/README.md index 273c986..c304d26 100644 --- a/2ano/1semestre/aed/teoricas/README.md +++ b/2ano/1semestre/aed/teoricas/README.md @@ -17,6 +17,8 @@ | [09](https://github.com/TiagoRG/uaveiro-leci/tree/master/2ano/1semestre/aed/teoricas/tema09) | Dicionários | | [10](https://github.com/TiagoRG/uaveiro-leci/tree/master/2ano/1semestre/aed/teoricas/tema10) | Grafos | | [11](https://github.com/TiagoRG/uaveiro-leci/tree/master/2ano/1semestre/aed/teoricas/tema11) | C++ | +| [12](https://github.com/TiagoRG/uaveiro-leci/tree/master/2ano/1semestre/aed/teoricas/tema12) | Procura Exaustiva | +| [13](https://github.com/TiagoRG/uaveiro-leci/tree/master/2ano/1semestre/aed/teoricas/tema13) | Tópicos Avançados | --- *Pode conter erros, caso encontre algum, crie um* [*ticket*](https://github.com/TiagoRG/uaveiro-leci/issues/new) diff --git a/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva.pdf b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva.pdf new file mode 100644 index 0000000..09d0166 Binary files /dev/null and b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva.pdf differ diff --git a/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/binarycounter.c b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/binarycounter.c new file mode 100644 index 0000000..d5f2d16 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/binarycounter.c @@ -0,0 +1,50 @@ +/* TAD que permite obter todos os subconjuntos de um conjunto de n elementos */ +/* Ficheiro de implementacao binarycounter.c J. Madeira --- 2010/06/02 */ + +#include "binarycounter.h" /* ficheiro de interface do TAD */ + +#include +#include + +int* createBinCounter(int size) { return (int*)calloc(size, sizeof(int)); } + +void copyBinCounter(int* original, int* copy, int size) { + int i; + + for (i = 0; i < size; i++) { + copy[i] = original[i]; + } +} + +void destroyBinCounter(int** binCounter) { + free(*binCounter); + *binCounter = NULL; +} + +void printBinCounter(int* binCounter, int size) { + int i; + + for (i = size - 1; i >= 0; i--) { + printf("%d", binCounter[i]); + } + + printf("\n"); +} + +int increaseBinCounter(int* binCounter, int size) { + int i = 0; + + while ((i < size) && (binCounter[i] == 1)) { + binCounter[i] = 0; + i++; + } + + if (i < size) { + binCounter[i] = 1; + return 1; + } + + /* Overflow */ + + return 0; +} diff --git a/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/binarycounter.h b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/binarycounter.h new file mode 100644 index 0000000..bfad35e --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/binarycounter.h @@ -0,0 +1,20 @@ +/* TAD que permite obter todos os subconjuntos de um conjunto de n elementos */ +/* Ficheiro de interface binarycounter.h J. Madeira --- 2010/06/02 */ + +#include +#include + +int* createBinCounter(int size); +/* Cria o contador binário com dimensão size, inicializado a zeros */ + +void copyBinCounter(int* original, int* copy, int size); +/* Copia o contador actual */ + +void destroyBinCounter(int** binCounter); +/* Destroi o contador */ + +void printBinCounter(int* binCounter, int size); +/* Imprime o contador */ + +int increaseBinCounter(int* binCounter, int size); +/* Incrementa o contador */ diff --git a/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/knapsack.c b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/knapsack.c new file mode 100644 index 0000000..cc03caa --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/knapsack.c @@ -0,0 +1,158 @@ +#include +#include +#include + +#include "binarycounter.h" /* ficheiro de interface do TAD */ + +void solutionKnapsack(int, float*, float*, int, float, int*); +int* knapsackSearch(float*, float*, int, float); + +int main(void) { + int n; + float capacidade; + + float w[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; + + float v[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 100, + 12, 32, 44, 14, 15, 16, 17, 128, 29, 20}; + + n = sizeof(w) / sizeof(float); + + do { + printf("Capacidade da mochila? "); + scanf("%f", &capacidade); + } while (capacidade <= 0.0); + + knapsackSearch(w, v, n, capacidade); + + return 0; +} + +void solutionKnapsack(int solNumber, float* weight, float* value, int n, + float capacity, int* validIndices) { + int i; + + int flag = 0; + + float w = 0.0; + + float v = 0.0; + + printf("Knapsack capacity = %f --- Solution number = %d\n", capacity, + solNumber); + + printf("Set of items = "); + + for (i = 0; i < n; i++) { + if (validIndices[i]) { + if (flag) { + printf(" + "); + } else { + flag = 1; + } + + printf("item[%d]", i); + } + } + + printf("\n"); + + flag = 0; + + printf("Total weight = "); + + for (i = 0; i < n; i++) { + if (validIndices[i]) { + w += weight[i]; + + if (flag) { + printf(" + "); + } else { + flag = 1; + } + + printf("%.2f", weight[i]); + } + } + + printf(" = %.2f\n", w); + + flag = 0; + + printf("Total value = "); + + for (i = 0; i < n; i++) { + if (validIndices[i]) { + v += value[i]; + + if (flag) { + printf(" + "); + } else { + flag = 1; + } + + printf("%.2f", value[i]); + } + } + + printf(" = %.2f\n", v); + + printf("\n"); +} + +int* knapsackSearch(float* weight, float* value, int n, float capacity) { + /* Gerar todos os sub-conjuntos dos indices do array de items */ + /* Aproveitar a representacao binaria para os gerar ! */ + /* Verificar, para cada um, o valor da soma dos pesos e dos valores */ + + int subSetIndex; + + float sumWeights; + + float sumValues, maxSumValues = 0.0; + + int i; + + /* O numero de sub-conjuntos e 2^n */ + + int numSubSets = (int)pow(2.0, n); + + /* Nao se testa o (sub-)conjunto vazio */ + + int* binaryCounter = createBinCounter(n); + + int* currentBestSol = createBinCounter(n); + + for (subSetIndex = 1; subSetIndex < numSubSets; subSetIndex++) { + sumWeights = 0; + sumValues = 0; + + increaseBinCounter(binaryCounter, n); + + for (i = 0; i < n; i++) { + if (binaryCounter[i] && ((sumWeights += weight[i]) > capacity)) { + break; /* EficiEncia --- Testar tambem sem este break !! */ + } + if (binaryCounter[i]) { + sumValues += value[i]; + } + } + + if (sumValues > maxSumValues) { + maxSumValues = sumValues; + + copyBinCounter(binaryCounter, currentBestSol, n); + + /* Listar as sucessivas melhores solucoes */ + + solutionKnapsack(subSetIndex, weight, value, n, capacity, binaryCounter); + } + + /* Poderia listar tambem eventuais solucoes alternativas !! */ + } + + destroyBinCounter(&binaryCounter); + + return currentBestSol; +} diff --git a/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/magicsquare.c b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/magicsquare.c new file mode 100644 index 0000000..3b4ebac --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/magicsquare.c @@ -0,0 +1,138 @@ +/* A magic square is a n x n matrix, whose elements are a permutation of the + integers from 1 to n x n, which satisfies the following: + + The sum of the n elements in each row is equal to the sum of the n elements + in each colummn, and is also equal to the sum of the n elements of the two + diagonals. + + J. Madeira --- 2010/06/02 +*/ + +#include +#include +#include + +#include "permutation.h" + +int isMagicSquare(int*, int); +void printMagicSquare(int*, int); +void magicSquaresSearch(int); + +int main(void) { + int n = 9; + + magicSquaresSearch(n); + + return 0; +} + +int isMagicSquare(int* a, int size) { + int i, j; + int sum; + int n = (int)sqrt(size); + + int* sumRow = (int*)calloc(n, sizeof(int)); + int* sumColumn = (int*)calloc(n, sizeof(int)); + int* sumDiag = (int*)calloc(2, sizeof(int)); + + /* Adding the elements */ + + for (i = 0; i < n; i++) { + for (j = 0; j < n; j++) { + sumRow[i] += a[j + i * n]; + sumColumn[j] += a[j + i * n]; + + if (i == j) { + /* Main diagonal */ + sumDiag[0] += a[j + i * n]; + } + + if ((i + j) == (n - 1)) { + /* The other diagonal */ + sumDiag[1] += a[j + i * n]; + } + } + } + + /* Checking the diagonals */ + + if (sumDiag[0] != sumDiag[1]) { + free(sumRow); + free(sumColumn); + free(sumDiag); + return 0; + } + + sum = sumDiag[0]; + + /* Checking the rows */ + + for (i = 0; i < n; i++) { + if (sumRow[i] != sum) { + free(sumRow); + free(sumColumn); + free(sumDiag); + return 0; + } + } + + /* Checking the columns */ + + for (i = 0; i < n; i++) { + if (sumColumn[i] != sum) { + free(sumRow); + free(sumColumn); + free(sumDiag); + return 0; + } + } + + free(sumRow); + free(sumColumn); + free(sumDiag); + + return sum; +} + +void printMagicSquare(int* a, int size) { + int i, j; + + int n = (int)sqrt(size); + + printf("\n"); + + for (i = 0, j = 0; i < size; i++) { + printf("%3d", a[i]); + + j++; + + if (j == n) { + printf("\n"); + + j = 0; + } + } + + printf("\n"); +} + +void magicSquaresSearch(int size) { + /* Gerar todas as permutacoes dos elementos do array */ + /* Verificar, para cada uma, se se trata de um quadrado magico */ + + int sum; + int permutationIndex = 1; + int* p; + p = createFirstPermutation(size); + + do { + if ((sum = isMagicSquare(p, size))) { + printf(" *** Permutation %d is a magic square of sum %d :\n\n", + permutationIndex, sum); + printMagicSquare(p, size); + } + permutationIndex++; + } while (nextPermutation(p, size)); + + destroyPermutation(&p); +} diff --git a/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/permutation.c b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/permutation.c new file mode 100644 index 0000000..f635be9 --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/permutation.c @@ -0,0 +1,90 @@ +/* TAD que permite obter todas as permutacoes de um conjunto de n elementos */ +/* Ficheiro de implementacao permutation.c J. Madeira --- 2010/06/02 */ + +#include "permutation.h" /* ficheiro de interface do TAD */ + +#include +#include + +static void swapElements(int*, int, int); + +int* createFirstPermutation(int n) { + int i; + + int* p = (int*)malloc(n * sizeof(int)); + + for (i = 0; i < n; i++) { + p[i] = i + 1; + } + + return p; +} + +void copyPermutation(int* original, int* copy, int n) { + int i; + + for (i = 0; i < n; i++) { + copy[i] = original[i]; + } +} + +void destroyPermutation(int** p) { + free(*p); + *p = NULL; +} + +void printPermutation(int* p, int n) { + int i; + + for (i = 0; i < n; i++) { + printf("%d ", p[i]); + } + + printf("\n"); +} + +int nextPermutation(int* v, int n) { + /* Adapted from + * http://compprog.wordpress.com/2007/10/08/generating-permutations-2/ */ + + int i, j, k; + + /* Find the largest i */ + + i = n - 2; + while ((i >= 0) && (v[i] > v[i + 1])) { + --i; + } + + /* If i is smaller than 0, then there are no more permutations. */ + if (i < 0) + + { + return 0; + } + + /* Find the largest element after vi but not larger than vi */ + + k = n - 1; + while (v[i] > v[k]) { + --k; + } + + swapElements(v, i, k); + + /* Swap the last n - i elements. */ + + k = 0; + for (j = i + 1; j < (n + i) / 2 + 1; ++j, ++k) { + swapElements(v, j, n - k - 1); + } + + return 1; +} + +/* funcao interna que troca dois elementos do array */ +static void swapElements(int* p, int i, int j) { + int aux = p[i]; + p[i] = p[j]; + p[j] = aux; +} diff --git a/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/permutation.h b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/permutation.h new file mode 100644 index 0000000..4df5d1e --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/permutation.h @@ -0,0 +1,21 @@ +/* TAD que permite obter todas as permutacoes de um conjunto de n elementos */ +/* Ficheiro de interface permutation.h J. Madeira --- 2010/06/02 */ + +#include +#include + +int* createFirstPermutation(int n); +/* Cria o array de permutacoes com dimensao n, sendo a primeira permutacao + * 123456...n */ + +void copyPermutation(int* original, int* copy, int n); +/* Copia a permutacao actual */ + +void destroyPermutation(int** p); +/* Destroi o array de permutacoes */ + +void printPermutation(int* p, int n); +/* Imprime a permutacao actual */ + +int nextPermutation(int* v, int n); +/* Cria a permutacao seguinte */ diff --git a/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/subsetsum.c b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/subsetsum.c new file mode 100644 index 0000000..2b207ee --- /dev/null +++ b/2ano/1semestre/aed/teoricas/tema12/27_AED_Procura_Exaustiva/subsetsum.c @@ -0,0 +1,114 @@ +#include +#include +#include + +#include "binarycounter.h" /* ficheiro de interface do TAD */ + +void solutionFound(int, int*, int, int*); +void subsetSumSearch(int*, int, int); + +int main(void) { + int n, soma; + + int array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20}; + + n = sizeof(array) / sizeof(int); + + printf("Soma? "); + scanf("%d", &soma); + + subsetSumSearch(array, n, soma); + + return 0; +} + +void solutionFound(int sum, int* a, int size, int* validIndices) { + int i; + + int flag = 0; + + int s = 0; + + printf("%d = ", sum); + + for (i = 0; i < size; i++) { + if (validIndices[i]) { + s += a[i]; + + if (flag) { + printf(" + "); + } else { + flag = 1; + } + + printf("%d", a[i]); + } + } + + printf("\n"); + + flag = 0; + + printf("%d = ", sum); + + for (i = 0; i < size; i++) { + if (validIndices[i]) { + if (flag) { + printf(" + "); + } else { + flag = 1; + } + + printf("a[%d]", i); + } + } + + printf("\n"); + + if (s != sum) { + printf("ERRO !!!\n"); + } + + printf("\n"); +} + +void subsetSumSearch(int* a, int size, int sum) { + // Gerar todos os sub-conjuntos dos indices do array + // Verificar, para cada um, o valor da soma dos elementos + // Aproveitar a representacao binaria para os gerar ! + + int subSetIndex; + + int sumElements; + + int i; + + // O numero de sub-conjuntos e 2^n + + int numSubSets = (int)pow(2.0, size); + + // Nao se testa o (sub-)conjunto vazio + + int* binaryCounter = createBinCounter(size); + + for (subSetIndex = 1; subSetIndex < numSubSets; subSetIndex++) { + sumElements = 0; + + increaseBinCounter(binaryCounter, size); + + for (i = 0; i < size; i++) { + if (binaryCounter[i] && ((sumElements += a[i]) > sum)) { + break; /* Eficiencia --- Testar tambem sem este break !!*/ + } + } + + // Listar todas as solucoes encontradas + + if (sumElements == sum) { + solutionFound(sum, a, size, binaryCounter); + } + } + + destroyBinCounter(&binaryCounter); +} diff --git a/2ano/1semestre/aed/teoricas/tema13/28_AED_Topicos_Avancados.pdf b/2ano/1semestre/aed/teoricas/tema13/28_AED_Topicos_Avancados.pdf new file mode 100644 index 0000000..ccf3482 Binary files /dev/null and b/2ano/1semestre/aed/teoricas/tema13/28_AED_Topicos_Avancados.pdf differ