diff --git a/docs/code/Boletin_3/Ejercicio_29.c b/docs/code/Boletin_3/Ejercicio_29.c
new file mode 100644
index 0000000..0575e0a
--- /dev/null
+++ b/docs/code/Boletin_3/Ejercicio_29.c
@@ -0,0 +1,64 @@
+// SPDX-FileCopyrightText: 2024 Pablo R.
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+// Enunciado: Plantee e implemente una función recursiva en Lenguaje C para determinar si un número natural es capicúa. Además, implemente otra función apropiada para probar su funcionamiento, activando esta última desde el programa principal.
+
+//Para usar bool
+#include
+//Para usar pow
+#include
+//Para usar scanf y printf
+#include
+
+//Precondición: num es positivo
+bool determinarSiCapicua(int num) {
+ int a, b;
+ //Variables auxiliares
+ int reducido, posFinal;
+
+ if(num < 10) {
+ //Caso base de la recursión: Solo queda un dígito
+ return true;
+ } else {
+ //Extraer el primer y último dígito
+ // posFinal ayudará a saber en que posición está «a»
+ for(a = num, posFinal = 0;
+ a >= 10 || a <= -10;
+ posFinal++, a /= 10);
+ b = num % 10;
+
+ //Comprobar si son iguales. Si sí, recursión; si no, se devuelve falso y esto sube por la pila de llamadas
+ if(a == b) {
+ //Quitamos a y b de num
+ reducido = num / 10;
+ reducido -= a * (int)pow(10, posFinal);
+
+ return determinarSiCapicua(reducido);
+ } else {
+ return false;
+ }
+ }
+}
+
+void probarSiCapicua() {
+ int num;
+
+ printf("Introduzca el número natural: ");
+ scanf("%d", &num);
+ if(num < 0) {
+ num = -num;
+ }
+
+ if(determinarSiCapicua(num)) {
+ printf("%d es capicua\n", num);
+ } else {
+ printf("%d no es capicua\n", num);
+ }
+}
+
+int main() {
+ probarSiCapicua();
+
+ return 0;
+}
diff --git a/docs/code/Boletin_3/Ejercicio_30.c b/docs/code/Boletin_3/Ejercicio_30.c
new file mode 100644
index 0000000..490f6c2
--- /dev/null
+++ b/docs/code/Boletin_3/Ejercicio_30.c
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: 2024 Pablo R.
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+// Enunciado: Plantee e implemente una función recursiva que devuelva la suma de las cifras de un número entero > 0. Por ejemplo si el número es 721 devuelve 10. Además de la función, implemente la función apropiada para probar su funcionamiento, activándola desde el programa principal.
+
+#include
+
+int sumaCifras(int num) {
+ //Caso base de la recursión: num es menor que 10
+ if(num < 10) {
+ return num;
+ } else {
+ //Recursión: Se elimina la última cifra
+ return sumaCifras(num / 10) + (num % 10);
+ }
+}
+
+void probarSuma() {
+ int num;
+
+ while(1) {
+ printf("Introduzca el número: ");
+ scanf("%d", &num);
+ if(num <= 0) {
+ printf("%d tiene que ser mayor que 0\n", num);
+ } else {
+ break;
+ }
+ }
+
+ printf("Suma: %d\n", sumaCifras(num));
+}
+
+int main() {
+ probarSuma();
+ return 0;
+}
diff --git a/docs/code/Boletin_3/Ejercicio_31.c b/docs/code/Boletin_3/Ejercicio_31.c
new file mode 100644
index 0000000..e48b11a
--- /dev/null
+++ b/docs/code/Boletin_3/Ejercicio_31.c
@@ -0,0 +1,47 @@
+// SPDX-FileCopyrightText: 2024 Pablo R.
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+// Enunciado: Plantee e implemente una función recursiva en Lenguaje C para resolver el problema de las torres de Hanoi. Además de la función, implemente la función apropiada para probar su funcionamiento, activando este último desde el programa principal.
+
+#include
+#include
+
+
+//Función auxiliar para mover un disco de una torre a otra
+void mover(int n, char *origen, char *destino) {
+ printf("Mover %d de %s a %s\n", n, origen, destino);
+}
+
+void torresHanoi(int disco, char *origen, char *auxiliar, char *destino){
+ if(disco == 1){
+ mover(disco, origen, destino);
+ } else{
+ torresHanoi(disco - 1,origen,destino,auxiliar);
+ mover(disco, origen, destino);
+ torresHanoi(disco - 1,auxiliar,origen,destino);
+ }
+}
+
+void ejecutar(int numDiscos) {
+ //Ejecutar el algorimo
+ torresHanoi(numDiscos, "Origen", "Auxiliar", "Destino");
+}
+
+int main() {
+ int numDiscos;
+
+ while(1) {
+ printf("Introduzca el numero de discos: ");
+ scanf("%d", &numDiscos);
+ if(numDiscos <= 0) {
+ printf("Debe haber 1 o más discos\n");
+ } else {
+ break;
+ }
+ }
+
+ ejecutar(numDiscos);
+
+ return 0;
+}
diff --git a/docs/code/Boletin_3/Ejercicio_33.c b/docs/code/Boletin_3/Ejercicio_33.c
new file mode 100644
index 0000000..257d92d
--- /dev/null
+++ b/docs/code/Boletin_3/Ejercicio_33.c
@@ -0,0 +1,41 @@
+// SPDX-FileCopyrightText: 2024 Pablo R.
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+// Enunciado: Plantee e implemente una función recursiva en Lenguaje C que calcule la suma de los términos de la sucesión de Fibonacci hasta el término indicado por el usuario a través del teclado. Además de la función, implemente la función apropiada para probar su funcionamiento, activando está último desde el programa principal.
+
+#include
+
+int sumaFib(int limite, int a, int b) {
+ int siguiente;
+
+ siguiente = a + b;
+ printf("%d %d = %d %d\n", a, b, siguiente, limite);
+ //Caso base de la recursión: se llegó al límite
+ if(siguiente == limite) {
+ return siguiente;
+ } else {
+ return sumaFib(limite, b, siguiente) + siguiente;
+ }
+}
+
+void probarSuma() {
+ int num;
+
+ while(1) {
+ printf("Introduzca el número: ");
+ scanf("%d", &num);
+ if(num <= 0) {
+ printf("%d tiene que ser mayor que 0\n", num);
+ } else {
+ break;
+ }
+ }
+
+ printf("Suma: %d\n", sumaFib(num, 1, 1) + 2); //El 2 representa la suma de los 1 iniciales
+}
+
+int main() {
+ probarSuma();
+ return 0;
+}
diff --git a/docs/code/Boletin_3/Ejercicio_34.c b/docs/code/Boletin_3/Ejercicio_34.c
new file mode 100644
index 0000000..8792e1a
--- /dev/null
+++ b/docs/code/Boletin_3/Ejercicio_34.c
@@ -0,0 +1,178 @@
+// SPDX-FileCopyrightText: 2024 Pablo R.
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+/* Enunciado: Plantee e implemente, mediante funciones y procedimientos, un programa en Lenguaje C gestionado por menú en el que se presenten opciones para realizar las siguientes operaciones sobre números enteros:
+
+- Calcular el número de cifras de un entero
+- Sumar las cifras de un entero
+- Indicar la cifra i-ésima menos significativa de un entero
+- Calcular la imagen especular de un entero
+- Comprobar si un entero es primo
+- Calcula el MCD (mínimo común divisor) de dos números enteros
+- Presentar la tabla de sumar, restar, multiplicar y dividir (hasta 10) de un número entero*/
+
+#include
+#include
+#include
+
+enum Operaciones {
+ SALIR,
+ CONTAR_CIFRAS,
+ SUMAR_CIFRAS,
+ CIFRA_SIGNIFICATIVA,
+ IMAGEN,
+ PRIMO,
+ MCD,
+ TABLA
+};
+
+int numCifras(int num) {
+ int n;
+ //Bucle for, en cada paso dividimos num entre 10 y sumamos 1
+ for(n = 1; num /= 10; n++);
+ return n;
+ //Otra opción sería hacer
+ // #include
+ // return (int)log10(num) + 1;
+}
+
+int sumaCifras(int num) {
+ //Caso base de la recursión: num es menor que 10
+ if(num < 10) {
+ return num;
+ } else {
+ //Recursión: Se elimina la última cifra
+ return sumaCifras(num / 10) + (num % 10);
+ }
+}
+
+int cifraSignificativa(int num, int i) {
+ //Se coje la i-ésima cifra, empezando por el final.
+ for(; i > 1; i--) {
+ num /= 10;
+ }
+
+ return num % 10;
+}
+
+int imagen(int num) {
+ int x;
+ for(x = 0; num > 0; num /= 10) {
+ x = x*10 + (num % 10);
+ }
+ return x;
+}
+
+bool primo(int n) {
+ //Este algoritmo usa el método de Eratóstenes,
+ // eliminando números hasta la raíz cuadrada de n
+ //Indica si el i-ésimo número no es primo
+ bool *no_primos;
+
+ no_primos = calloc(n, sizeof(bool));
+
+ //Recorremos los números enteros hasta la raiz de n
+ for(int i = 2; i*i <= n; i++) {
+ if(no_primos[i]) {
+ //Si ya se comprobó, saltar
+ continue;
+ } else {
+ if(n % i == 0) {
+ //No es primo
+ return false;
+ } else {
+ //Si es primo. Marcamos todos sus múltiplos
+ for(int j = i + 1; j*j <= n; j++) {
+ no_primos[i] = n % j == 0;
+ }
+ }
+ }
+ }
+
+ free(no_primos);
+
+ return true;
+}
+
+int mcd(int a, int b) {
+ //Algoritmo de Euclides recursivo
+ int tmp;
+
+ if(b == 0) {
+ //Caso base
+ return a;
+ } else {
+ if(a > b) {
+ tmp = a % b;
+ } else {
+ tmp = b % a;
+ }
+ return mcd(b, tmp);
+ }
+}
+
+void tabla(int num) {
+ printf(" SUMA RESTA MULT DIV\n");
+ for(int i = 1; i <= 10; i++) {
+ printf("%2d %4d %5d %4d %4d\n", i, num + i, num - i, num * i, num / i);
+ }
+}
+
+void menu() {
+ int op, num, i;
+
+ do {
+ printf("0 - Salir\n");
+ printf("1 - Calcular el número de cifras de un entero\n");
+ printf("2 - Sumar las cifras de un entero\n");
+ printf("3 - Indicar la cifra i-ésima menos significativa de un entero\n");
+ printf("4 - Calcular la imagen especular de un entero\n");
+ printf("5 - Comprobar si un entero es primo\n");
+ printf("6 - Calcula el MCD (mínimo común divisor) de dos números enteros\n");
+ printf("7 - Presentar la tabla de sumar, restar, multiplicar y dividir (hasta 10) de un número entero\n");
+ printf("Introduzca el nº de operación: ");
+ scanf("%d", &op);
+ if(op == SALIR) {
+ continue;
+ }
+ printf("Introduza el número: ");
+ scanf("%d", &num);
+ if(op == CIFRA_SIGNIFICATIVA || op == MCD) {
+ printf("Introduzca el segundo número: ");
+ scanf("%d", &i);
+ }
+ printf("\n");
+ switch(op) {
+ case CONTAR_CIFRAS:
+ printf("%d cifras\n", numCifras(num));
+ break;
+ case SUMAR_CIFRAS:
+ printf("Total: %d\n", sumaCifras(num));
+ break;
+ case CIFRA_SIGNIFICATIVA:
+ printf("Cifra: %d\n", cifraSignificativa(num, i));
+ break;
+ case IMAGEN:
+ printf("%d -> %d\n", num, imagen(num));
+ break;
+ case PRIMO:
+ printf("%d %s primo\n", num, primo(num) ? "es" : "no es");
+ break;
+ case MCD:
+ printf("mcd(%d, %d) = %d\n", num, i, mcd(num, i));
+ break;
+ case TABLA:
+ tabla(num);
+ break;
+ default:
+ printf("Opción incorrecta");
+ };
+ printf("\n");
+ } while(op);
+}
+
+int main() {
+ menu();
+ return 0;
+}
diff --git a/docs/code/Boletin_3/Ejercicio_35.c b/docs/code/Boletin_3/Ejercicio_35.c
new file mode 100644
index 0000000..b7ce67e
--- /dev/null
+++ b/docs/code/Boletin_3/Ejercicio_35.c
@@ -0,0 +1,383 @@
+// SPDX-FileCopyrightText: 2024 Pablo R.
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+/* Enunciado: Plantee e implemente, mediante funciones y procedimientos, un programa en Lenguaje C gestionado por menú en el que se presenten opciones para realizar las siguientes operaciones sobre números enteros:
+ *
+ * - Salir del programa
+ * - Tres opciones de entre las siguientes:
+ * - Conocer el número de vocales sin acentuar existentes en un texto que el usuario escribe mientras no aparezca el carácter *.
+ * - Calcular la potencia de un número b elevado a e, sin utilizar los operadores de exponenciación.
+ * - Mostrar por pantalla el factorial del menor de dos números enteros positivos que introduzca por teclado el usuario.
+ * - Visualizar una tabla con los cuadrados y los cubos de los números contenidos en un intervalo de enteros indicado por el usuario.
+ * - Dibujar un cuadrado, aproximadamente centrado, en pantalla con el carácter y longitud del lado que indique el usuario.
+ * - Mostrar el área y el perímetro del rectángulo de menor área. El usuario debe indicar las longitudes de los lados de los dos rectángulos.
+ * - Visualizar una tabla de los números, los cuadrados y las raíces cuadradas de aquellos números contenidos en un intervalo de enteros indicado por el usuario.
+ * - Calcular el máximo, el mínimo y la media de una serie de números enteros que el usuario introduce por teclado. Finaliza la serie cuando el número introducido es múltiplo de 10.
+ * - Mostrar por pantalla los divisores de un número entero que indique el usuario.
+ * - Dibujar un triángulo equilátero, aproximadamente centrado, en pantalla con el carácter y longitud del lado que indique el usuario.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+enum Operaciones {
+ SALIR,
+ VOCALES,
+ POTENCIA,
+ FACTORIAL,
+ CUBOS,
+ CUADRADO,
+ RECTANGULO,
+ TABLA,
+ MAXIMO,
+ DIVISORES,
+ EQUILATERO
+};
+
+void vocales() {
+ char c;
+ int n = 0;
+
+ printf("Introduzca el texto. Introduzca «*» y pulse intro para terminar: ");
+ do {
+ c = getc(stdin);
+ switch(c) {
+ case 'a':
+ case 'e':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'A':
+ case 'E':
+ case 'I':
+ case 'O':
+ case 'U':
+ n++;
+ break;
+ }
+ } while(c != EOF && c != '*');
+
+ printf("%d vocales\n", n);
+}
+
+int potencia(int base, int exponente) {
+ int n;
+
+ //Para no usar las funciones de exponenciación, se hace un simple bucle
+ for(n = 1; exponente > 0; exponente--) {
+ n *= base;
+ }
+
+ return n;
+}
+
+int factorial(int n) {
+ if(n <= 1) {
+ return 1;
+ } else {
+ return n * factorial(n - 1);
+ }
+}
+
+void cuadradosYCubos(int de, int hasta) {
+ printf("%5s Cuadrado Cubo\n", "");
+ for(int i = de; i <= hasta; i++) {
+ printf("%5d %8d %8d\n", i, i*i, i*i*i);
+ }
+}
+
+void dibujarCuadrado(int lado, char caracter) {
+ int i;
+ //Primera línea
+ for(i = 0; i < lado; i++) {
+ putchar(caracter);
+ }
+ putchar('\n');
+ //Siguientes líneas
+ for(i = 1; i < lado - 1; i++) {
+ putchar(caracter);
+ for(int j = 1; j < lado - 1; j++) {
+ putchar(' ');
+ }
+ putchar(caracter);
+ putchar('\n');
+ }
+ //Línea final
+ for(i = 0; i < lado; i++) {
+ putchar(caracter);
+ }
+}
+
+void areaRectangulo(int largoA, int cortoA, int largoB, int cortoB) {
+ int areaA, areaB, perimetroA, perimetroB;
+
+ areaA = largoA * cortoA;
+ perimetroA = (largoA + cortoA)*2;
+
+ areaB = largoB * cortoB;
+ perimetroB = (largoB + cortoB)*2;
+
+ if(areaA < areaB) {
+ printf("Rectángulo %d %d: Área %d Perímetro %d\n", largoA, cortoA, areaA, perimetroA);
+ } else {
+ printf("Rectángulo %d %d: Área %d Perímetro %d\n", largoB, cortoB, areaB, perimetroB);
+ }
+}
+
+void raices(int de, int hasta) {
+ printf("%5s Cuadrado Raiz cuadrada\n", "");
+ for(int i = de; i <= hasta; i++) {
+ printf("%5d %8d %e\n", i, i*i, sqrt(i));
+ }
+}
+
+void maximo() {
+ long *numeros, tmp, max, i;
+ char *entrada, *continuar, *entradaTmp;
+ size_t tamEntrada = sizeof(char);
+
+ long maximo, minimo;
+ float media;
+
+
+ //Inicializar la cadena que contendrá la entrada
+ entrada = malloc(sizeof(char));
+ printf("Introduzca los números separados por espacios. Termine con un salto de línea: ");
+ getline(&entrada, &tamEntrada, stdin);
+ entradaTmp = entrada;
+ continuar = entrada;
+
+ //Inicializar el vector de números
+ numeros = calloc(tamEntrada / 2 + 1, sizeof(int));
+ //Si el número es múltiplo de 10, se para
+ for (i = 0; (tmp = strtol(continuar, &entradaTmp, 10)) % 10 != 0; i++ ) {
+ //Si continuar es igual a entradaTmp no se han introducido
+ // números. Si entradaTmp es igual a '\0' es que se ha
+ // leido toda la entrada.
+ if(continuar == entradaTmp || *entradaTmp == '\0') {
+ break;
+ } else {
+ //En cada vuelta, strtol coje un número de continuar, y
+ // apunta al siguiente en la variable entradaTmp
+ continuar = entradaTmp;
+ }
+ numeros[i] = tmp;
+ }
+
+ //Calcular la media, máximo y mínimo
+ max = i;
+ maximo = LONG_MIN;
+ minimo = LONG_MAX;
+ for(i = 0, tmp = 0; i < max; i++) {
+ tmp += numeros[i];
+ if(numeros[i] > maximo) {
+ maximo = numeros[i];
+ }
+ if(numeros[i] < minimo) {
+ minimo = numeros[i];
+ }
+ }
+ media = (float)tmp / max;
+
+ printf("Máximo: %ld\nMínimo: %ld\nMedia: %f\n", maximo, minimo, media);
+
+ free(numeros);
+ free(entrada);
+}
+
+void divisores(int num) {
+ printf("Divisores de %d: ", num);
+ for(int i = 2; i < num; i++) {
+ if(num % i == 0) {
+ printf("%d ", i);
+ }
+ }
+ printf("\n");
+}
+
+void triangulo(int lado, char caracter) {
+ int i;
+
+ int espacioAntes, espacioEntre;
+
+ if(lado % 2 == 0) {
+ espacioAntes = (lado - 2) / 2;
+ espacioEntre = 2;
+ } else {
+ espacioAntes = lado / 2;
+ espacioEntre = 1;
+ }
+
+ //Punta del triángulo
+ //Si lado es par, 2 asteriscos
+ //Si impar, 1 asterisco
+ for(i = 0; i < espacioAntes; i++) {
+ putchar(' ');
+ }
+ putchar(caracter);
+ if(lado % 2 == 0) {
+ putchar(caracter);
+ }
+ putchar('\n');
+
+ //Dibujar los lados
+ // El espacio anterior se reduce un caracter de cada vez
+ // El espacio interior se reduce de 2 en 2
+ for(espacioAntes-- ; espacioAntes > 0; espacioAntes--, espacioEntre += 2) {
+ //Dibujar espacios antes
+ for(i = 0; i < espacioAntes; i++) {
+ putchar(' ');
+ }
+ putchar(caracter);
+ //Dibujar espacios entre
+ for(i = 0; i < espacioEntre; i++) {
+ putchar(' ');
+ }
+ putchar(caracter);
+ putchar('\n');
+ }
+
+ //Dibujar el lado inferior
+ for(i = 0; i < lado; i++) {
+ putchar(caracter);
+ }
+ putchar('\n');
+}
+
+
+//Función auxiliar con gets que lee un número por pantalla
+//Equivalente a scanf("%d")
+int leerNumero() {
+ size_t len = 10*sizeof(char);
+ char *str;
+ int n;
+
+ str = calloc(10, sizeof(char));
+ getline(&str, &len, stdin);
+
+ n = strtol(str, NULL, 10);
+ free(str);
+ return n;
+}
+
+void menu() {
+ int op, tmpA, tmpB, tmpC, tmpD;
+ size_t len;
+ char *c;
+
+ c = calloc(10, sizeof(char));
+
+ do {
+printf(" 0 - Salir del programa\n");
+printf(" 1 - Conocer el número de vocales sin acentuar existentes en un texto que el usuario escribe mientras no aparezca el carácter *\n");
+printf(" 2 - Calcular la potencia de un número b elevado a e, sin utilizar los operadores de exponenciación\n");
+printf(" 3 - Mostrar por pantalla el factorial del menor de dos números enteros positivos que introduzca por teclado el usuario\n");
+printf(" 4 - Visualizar una tabla con los cuadrados y los cubos de los números contenidos en un intervalo de enteros indicado por el usuario\n");
+printf(" 5 - Dibujar un cuadrado, aproximadamente centrado, en pantalla con el carácter y longitud del lado que indique el usuario\n");
+printf(" 6 - Mostrar el área y el perímetro del rectángulo de menor área. El usuario debe indicar las longitudes de los lados de los dos rectángulos\n");
+printf(" 7 - Visualizar una tabla de los números, los cuadrados y las raíces cuadradas de aquellos números contenidos en un intervalo de enteros indicado por el usuario\n");
+printf(" 8 - Calcular el máximo, el mínimo y la media de una serie de números enteros que el usuario introduce por teclado. Finaliza la serie cuando el número introducido es múltiplo de 10\n");
+printf(" 9 - Mostrar por pantalla los divisores de un número entero que indique el usuario\n");
+printf("10 - Dibujar un triángulo equilátero, aproximadamente centrado, en pantalla con el carácter y longitud del lado que indique el usuario\n");
+ printf("Introduzca el nº de operación: ");
+ op = leerNumero();
+ if(op == SALIR) {
+ continue;
+ }
+ printf("\n");
+ switch(op) {
+ case VOCALES:
+ vocales();
+ break;
+
+ case POTENCIA:
+ printf("Base: ");
+ tmpA = leerNumero();
+ printf("Exponente: ");
+ tmpB = leerNumero();
+ printf("Resultado %d ** %d: %d", tmpA, tmpB, potencia(tmpA, tmpB));
+ break;
+
+ case FACTORIAL:
+ printf("Primer número: ");
+ tmpA = leerNumero();
+ printf("Segundo número: ");
+ tmpB = leerNumero();
+ if(tmpA > tmpB) {
+ printf("Factorial de %d: %d\n", tmpB, factorial(tmpB));
+ } else {
+ printf("Factorial de %d: %d\n", tmpA, factorial(tmpA));
+ }
+ break;
+
+ case CUBOS:
+ printf("De: ");
+ tmpA = leerNumero();
+ printf("Hasta: ");
+ tmpB = leerNumero();
+ cuadradosYCubos(tmpA, tmpB);
+ break;
+
+ case CUADRADO:
+ printf("Caracter: ");
+ getline(&c, &len, stdin);
+ printf("Tamaño: ");
+ tmpA = leerNumero();
+ dibujarCuadrado(tmpA, c[0]);
+ break;
+
+ case RECTANGULO:
+ printf("Longitudes de los lados largo y ancho del primer rectángulo, separados por espacios: ");
+ getline(&c, &len, stdin);
+ sscanf("%d %d", c, &tmpA, &tmpB);
+ printf("Longitudes de los lados largo y ancho del segundo rectángulo, separados por espacios: ");
+ getline(&c, &len, stdin);
+ sscanf("%d %d", c, &tmpC, &tmpD);
+ areaRectangulo(tmpA, tmpB, tmpC, tmpD);
+ break;
+
+ case TABLA:
+ printf("De: ");
+ tmpA = leerNumero();
+ printf("Hasta: ");
+ tmpB = leerNumero();
+ raices(tmpA, tmpB);
+ break;
+
+ case MAXIMO:
+ maximo();
+ break;
+
+ case DIVISORES:
+ printf("Introduca el número: ");
+ tmpA = leerNumero();
+ divisores(tmpA);
+ break;
+
+ case EQUILATERO:
+ printf("Caracter: ");
+ getline(&c, &len, stdin);
+ printf("Tamaño: ");
+ tmpA = leerNumero();
+ triangulo(tmpA, c[0]);
+ break;
+
+ default:
+ printf("Opción incorrecta");
+ };
+ printf("\n");
+ } while(op);
+
+ free(c);
+}
+
+int main() {
+ menu();
+ return 0;
+}
diff --git a/docs/code/Boletin_3/Ejercicio_36.c b/docs/code/Boletin_3/Ejercicio_36.c
new file mode 100644
index 0000000..dcb05d5
--- /dev/null
+++ b/docs/code/Boletin_3/Ejercicio_36.c
@@ -0,0 +1,197 @@
+// SPDX-FileCopyrightText: 2024 Pablo R.
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+/* Enunciado: Implemente un programa en Lenguaje C para trabajar con números complejos. Las opciones que debe tener son:
+1. Introducir dos números complejos en forma binómica por teclado
+2. Introducir dos números complejos en forma módulo-argumental por teclado
+3. Sumar dos números complejos
+4. Restar dos números complejos
+5. Multiplicar dos números complejos
+0. Salir
+*/
+
+#include
+#include
+#include
+#include
+
+enum Operaciones {
+ SALIR,
+ BINOMICA,
+ MODULO,
+ SUMAR,
+ RESTAR,
+ MULTIPLICAR
+};
+
+typedef struct {
+ double real;
+ double imaginario;
+} Binomica;
+
+typedef struct {
+ double modulo;
+ double argumento;
+} ModuloArg;
+
+
+typedef struct {
+ bool binomico;
+ union {
+ Binomica b;
+ ModuloArg m;
+ };
+} Numero;
+
+void binomicaAModulo(Binomica *origen, ModuloArg *destino) {
+ destino->modulo = sqrt(origen->real*origen->real + origen->imaginario*origen->imaginario);
+ destino->argumento = atan(origen->imaginario);
+}
+
+void moduloABinomica(ModuloArg *origen, Binomica *destino) {
+ destino->imaginario = tan(origen->argumento);
+ destino->real = sqrt(origen->modulo*origen->modulo - destino->imaginario*destino->imaginario);
+}
+
+void escribirNumero(Numero *n, const char *nombre) {
+ printf("%s ", nombre);
+
+ if(n->binomico) {
+ printf("(binomico): z = %e + i*%e", n->b.real, n->b.imaginario);
+ } else {
+ printf("(módulo-argumental): |%e|_%e ", n->m.modulo, n->m.argumento);
+ }
+
+ printf("\n");
+}
+
+void sumaBinomico(Binomica *x, Binomica *y, Binomica *z) {
+ z->real = x->real + y->real;
+ z->imaginario = x->imaginario + y->imaginario;
+}
+
+void restaBinomico(Binomica *x, Binomica *y, Binomica *z) {
+ z->real = x->real - y->real;
+ z->imaginario = x->imaginario - y->imaginario;
+}
+
+void multBinomico(Binomica *x, Binomica *y, Binomica *z) {
+ z->real = x->real*y->real - x->imaginario*y->imaginario;
+ z->imaginario = x->imaginario*y->real + x->real*y->imaginario;
+}
+
+void menu() {
+ int op;
+ double tmpA, tmpB;
+ Numero x, y, z;
+ Binomica tempA, tempB;
+ ModuloArg tempC;
+
+ do {
+ printf(" 1. Introducir dos números complejos en forma binómica por teclado\n");
+ printf(" 2. Introducir dos números complejos en forma módulo-argumental por teclado\n");
+ printf(" 3. Sumar dos números complejos\n");
+ printf(" 4. Restar dos números complejos\n");
+ printf(" 5. Multiplicar dos números complejos\n");
+ printf(" 0. Salir\n");
+ printf("Escoja una opción: ");
+ scanf("%d", &op);
+ if(op == SALIR) {
+ continue;
+ }
+ printf("\n");
+ switch(op) {
+ case BINOMICA:
+ printf("Introduzca los números, con la parte real e imaginaria separados por espacios.\n");
+ printf("X: ");
+ scanf("%lf %lf", &tmpA, &tmpB);
+ x.binomico = true;
+ x.b.real = tmpA;
+ x.b.imaginario = tmpB;
+ printf("Y: ");
+ scanf("%lf %lf", &tmpA, &tmpB);
+ y.binomico = true;
+ y.b.real = tmpA;
+ y.b.imaginario = tmpB;
+ break;
+
+ case MODULO:
+ printf("Introduzca los números, con el módulo y argumento separados por espacios.\n");
+ printf("X: ");
+ scanf("%lf %lf", &tmpA, &tmpB);
+ x.binomico = false;
+ x.m.modulo = tmpA;
+ x.m.argumento = tmpB;
+ printf("Y: ");
+ scanf("%lf %lf", &tmpA, &tmpB);
+ y.binomico = false;
+ y.m.modulo = tmpA;
+ y.m.argumento = tmpB;
+ break;
+
+ case SUMAR:
+ if(x.binomico && y.binomico) {
+ sumaBinomico(&x.b, &y.b, &(z.b));
+ } else {
+ moduloABinomica(&x.m, &tempA);
+ moduloABinomica(&y.m, &tempB);
+ sumaBinomico(&tempA, &tempB, &(z.b));
+ }
+ z.binomico = true;
+ escribirNumero(&z, "Z");
+
+ z.binomico = false;
+ binomicaAModulo(&z.b, &tempC);
+ z.m = tempC;
+ escribirNumero(&z, "Z");
+ break;
+
+ case RESTAR:
+ if(x.binomico && y.binomico) {
+ restaBinomico(&x.b, &y.b, &(z.b));
+ } else {
+ moduloABinomica(&x.m, &tempA);
+ moduloABinomica(&y.m, &tempB);
+ restaBinomico(&tempA, &tempB, &(z.b));
+ }
+ z.binomico = true;
+ escribirNumero(&z, "Z");
+
+ z.binomico = false;
+ binomicaAModulo(&z.b, &tempC);
+ z.m = tempC;
+ escribirNumero(&z, "Z");
+ break;
+
+ case MULTIPLICAR:
+ if(x.binomico && y.binomico) {
+ multBinomico(&x.b, &y.b, &(z.b));
+ } else {
+ moduloABinomica(&x.m, &tempA);
+ moduloABinomica(&y.m, &tempB);
+ multBinomico(&tempA, &tempB, &(z.b));
+ }
+ z.binomico = true;
+ escribirNumero(&z, "Z");
+
+ z.binomico = false;
+ binomicaAModulo(&z.b, &tempC);
+ z.m = tempC;
+ escribirNumero(&z, "Z");
+ break;
+
+ default:
+ printf("Opción incorrecta");
+ };
+ printf("\n");
+ printf("Números cargados:\n");
+ escribirNumero(&x, "X");
+ escribirNumero(&y, "Y");
+ } while(op);
+}
+
+int main() {
+ menu();
+ return 0;
+}
diff --git a/docs/topics/02-Boletines/Pro-1/Boletin-3.md b/docs/topics/02-Boletines/Pro-1/Boletin-3.md
index 720e81a..bbd2151 100644
--- a/docs/topics/02-Boletines/Pro-1/Boletin-3.md
+++ b/docs/topics/02-Boletines/Pro-1/Boletin-3.md
@@ -10,12 +10,6 @@ SPDX-License-Identifier: CC-BY-NC-4.0
Funciones, recursividad y retorno de datos.
-
-
-¡Se necesita tu ayuda!
-
-Faltan soluciones para los ejercicios del 29 al 31 y del 33 al 36. [Colabora](https://github.com/TeenBiscuits/Pro2324)
-
### Ejercicio 1
@@ -282,14 +276,6 @@ probar su funcionamiento.
-
-
-¡Se necesita tu ayuda!
-
-Faltan soluciones para los ejercicios del 29 al 31. [Colabora](https://github.com/TeenBiscuits/Pro2324)
-
-
-
--->
### Ejercicio 32
@@ -323,14 +310,6 @@ Además de la función, implemente otra función apropiada para probar su funcio
-
-
-¡Se necesita tu ayuda!
-
-Faltan soluciones para los ejercicios del 33 al 36. [Colabora](https://github.com/TeenBiscuits/Pro2324)
-
-
-
\ No newline at end of file
diff --git a/src/Boletin_3/CMakeLists.txt b/src/Boletin_3/CMakeLists.txt
index 19b789f..15abe53 100644
--- a/src/Boletin_3/CMakeLists.txt
+++ b/src/Boletin_3/CMakeLists.txt
@@ -2,10 +2,11 @@
#
# SPDX-License-Identifier: GPL-3.0-only
-cmake_minimum_required(VERSION 3.26)
+cmake_minimum_required(VERSION 3.25)
project(Boletin_3 C)
set(CMAKE_C_STANDARD 99)
+set(CMAKE_BUILD_TYPE Debug)
add_executable(Bol3-Ej01 Ejercicio_01.c)
add_executable(Bol3-Ej02 Ejercicio_02.c)
@@ -35,11 +36,19 @@ add_executable(Bol3-Ej25 Ejercicio_25.c)
add_executable(Bol3-Ej26 Ejercicio_26.c)
add_executable(Bol3-Ej27 Ejercicio_27.c)
add_executable(Bol3-Ej28 Ejercicio_28.c)
-#add_executable(Bol3-Ej29 Ejercicio_29.c)
-#add_executable(Bol3-Ej30 Ejercicio_30.c)
-#add_executable(Bol3-Ej31 Ejercicio_31.c)
+add_executable(Bol3-Ej29 Ejercicio_29.c)
+add_executable(Bol3-Ej30 Ejercicio_30.c)
+add_executable(Bol3-Ej31 Ejercicio_31.c)
add_executable(Bol3-Ej32 Ejercicio_32.c)
-#add_executable(Bol3-Ej33 Ejercicio_33.c)
-#add_executable(Bol3-Ej34 Ejercicio_34.c)
-#add_executable(Bol3-Ej35 Ejercicio_35.c)
-#add_executable(Bol3-Ej36 Ejercicio_36.c)
+add_executable(Bol3-Ej33 Ejercicio_33.c)
+add_executable(Bol3-Ej34 Ejercicio_34.c)
+add_executable(Bol3-Ej35 Ejercicio_35.c)
+add_executable(Bol3-Ej36 Ejercicio_36.c)
+
+#Necesario para math.h
+target_link_libraries(Bol3-Ej04 m)
+target_link_libraries(Bol3-Ej13 m)
+target_link_libraries(Bol3-Ej25 m)
+target_link_libraries(Bol3-Ej29 m)
+target_link_libraries(Bol3-Ej35 m)
+target_link_libraries(Bol3-Ej36 m)
diff --git a/src/Boletin_3/Ejercicio_29.c b/src/Boletin_3/Ejercicio_29.c
new file mode 100644
index 0000000..0575e0a
--- /dev/null
+++ b/src/Boletin_3/Ejercicio_29.c
@@ -0,0 +1,64 @@
+// SPDX-FileCopyrightText: 2024 Pablo R.
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+// Enunciado: Plantee e implemente una función recursiva en Lenguaje C para determinar si un número natural es capicúa. Además, implemente otra función apropiada para probar su funcionamiento, activando esta última desde el programa principal.
+
+//Para usar bool
+#include
+//Para usar pow
+#include
+//Para usar scanf y printf
+#include
+
+//Precondición: num es positivo
+bool determinarSiCapicua(int num) {
+ int a, b;
+ //Variables auxiliares
+ int reducido, posFinal;
+
+ if(num < 10) {
+ //Caso base de la recursión: Solo queda un dígito
+ return true;
+ } else {
+ //Extraer el primer y último dígito
+ // posFinal ayudará a saber en que posición está «a»
+ for(a = num, posFinal = 0;
+ a >= 10 || a <= -10;
+ posFinal++, a /= 10);
+ b = num % 10;
+
+ //Comprobar si son iguales. Si sí, recursión; si no, se devuelve falso y esto sube por la pila de llamadas
+ if(a == b) {
+ //Quitamos a y b de num
+ reducido = num / 10;
+ reducido -= a * (int)pow(10, posFinal);
+
+ return determinarSiCapicua(reducido);
+ } else {
+ return false;
+ }
+ }
+}
+
+void probarSiCapicua() {
+ int num;
+
+ printf("Introduzca el número natural: ");
+ scanf("%d", &num);
+ if(num < 0) {
+ num = -num;
+ }
+
+ if(determinarSiCapicua(num)) {
+ printf("%d es capicua\n", num);
+ } else {
+ printf("%d no es capicua\n", num);
+ }
+}
+
+int main() {
+ probarSiCapicua();
+
+ return 0;
+}
diff --git a/src/Boletin_3/Ejercicio_30.c b/src/Boletin_3/Ejercicio_30.c
new file mode 100644
index 0000000..490f6c2
--- /dev/null
+++ b/src/Boletin_3/Ejercicio_30.c
@@ -0,0 +1,38 @@
+// SPDX-FileCopyrightText: 2024 Pablo R.
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+// Enunciado: Plantee e implemente una función recursiva que devuelva la suma de las cifras de un número entero > 0. Por ejemplo si el número es 721 devuelve 10. Además de la función, implemente la función apropiada para probar su funcionamiento, activándola desde el programa principal.
+
+#include
+
+int sumaCifras(int num) {
+ //Caso base de la recursión: num es menor que 10
+ if(num < 10) {
+ return num;
+ } else {
+ //Recursión: Se elimina la última cifra
+ return sumaCifras(num / 10) + (num % 10);
+ }
+}
+
+void probarSuma() {
+ int num;
+
+ while(1) {
+ printf("Introduzca el número: ");
+ scanf("%d", &num);
+ if(num <= 0) {
+ printf("%d tiene que ser mayor que 0\n", num);
+ } else {
+ break;
+ }
+ }
+
+ printf("Suma: %d\n", sumaCifras(num));
+}
+
+int main() {
+ probarSuma();
+ return 0;
+}
diff --git a/src/Boletin_3/Ejercicio_31.c b/src/Boletin_3/Ejercicio_31.c
new file mode 100644
index 0000000..e48b11a
--- /dev/null
+++ b/src/Boletin_3/Ejercicio_31.c
@@ -0,0 +1,47 @@
+// SPDX-FileCopyrightText: 2024 Pablo R.
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+// Enunciado: Plantee e implemente una función recursiva en Lenguaje C para resolver el problema de las torres de Hanoi. Además de la función, implemente la función apropiada para probar su funcionamiento, activando este último desde el programa principal.
+
+#include
+#include
+
+
+//Función auxiliar para mover un disco de una torre a otra
+void mover(int n, char *origen, char *destino) {
+ printf("Mover %d de %s a %s\n", n, origen, destino);
+}
+
+void torresHanoi(int disco, char *origen, char *auxiliar, char *destino){
+ if(disco == 1){
+ mover(disco, origen, destino);
+ } else{
+ torresHanoi(disco - 1,origen,destino,auxiliar);
+ mover(disco, origen, destino);
+ torresHanoi(disco - 1,auxiliar,origen,destino);
+ }
+}
+
+void ejecutar(int numDiscos) {
+ //Ejecutar el algorimo
+ torresHanoi(numDiscos, "Origen", "Auxiliar", "Destino");
+}
+
+int main() {
+ int numDiscos;
+
+ while(1) {
+ printf("Introduzca el numero de discos: ");
+ scanf("%d", &numDiscos);
+ if(numDiscos <= 0) {
+ printf("Debe haber 1 o más discos\n");
+ } else {
+ break;
+ }
+ }
+
+ ejecutar(numDiscos);
+
+ return 0;
+}
diff --git a/src/Boletin_3/Ejercicio_33.c b/src/Boletin_3/Ejercicio_33.c
new file mode 100644
index 0000000..257d92d
--- /dev/null
+++ b/src/Boletin_3/Ejercicio_33.c
@@ -0,0 +1,41 @@
+// SPDX-FileCopyrightText: 2024 Pablo R.
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+// Enunciado: Plantee e implemente una función recursiva en Lenguaje C que calcule la suma de los términos de la sucesión de Fibonacci hasta el término indicado por el usuario a través del teclado. Además de la función, implemente la función apropiada para probar su funcionamiento, activando está último desde el programa principal.
+
+#include
+
+int sumaFib(int limite, int a, int b) {
+ int siguiente;
+
+ siguiente = a + b;
+ printf("%d %d = %d %d\n", a, b, siguiente, limite);
+ //Caso base de la recursión: se llegó al límite
+ if(siguiente == limite) {
+ return siguiente;
+ } else {
+ return sumaFib(limite, b, siguiente) + siguiente;
+ }
+}
+
+void probarSuma() {
+ int num;
+
+ while(1) {
+ printf("Introduzca el número: ");
+ scanf("%d", &num);
+ if(num <= 0) {
+ printf("%d tiene que ser mayor que 0\n", num);
+ } else {
+ break;
+ }
+ }
+
+ printf("Suma: %d\n", sumaFib(num, 1, 1) + 2); //El 2 representa la suma de los 1 iniciales
+}
+
+int main() {
+ probarSuma();
+ return 0;
+}
diff --git a/src/Boletin_3/Ejercicio_34.c b/src/Boletin_3/Ejercicio_34.c
new file mode 100644
index 0000000..8792e1a
--- /dev/null
+++ b/src/Boletin_3/Ejercicio_34.c
@@ -0,0 +1,178 @@
+// SPDX-FileCopyrightText: 2024 Pablo R.
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+/* Enunciado: Plantee e implemente, mediante funciones y procedimientos, un programa en Lenguaje C gestionado por menú en el que se presenten opciones para realizar las siguientes operaciones sobre números enteros:
+
+- Calcular el número de cifras de un entero
+- Sumar las cifras de un entero
+- Indicar la cifra i-ésima menos significativa de un entero
+- Calcular la imagen especular de un entero
+- Comprobar si un entero es primo
+- Calcula el MCD (mínimo común divisor) de dos números enteros
+- Presentar la tabla de sumar, restar, multiplicar y dividir (hasta 10) de un número entero*/
+
+#include
+#include
+#include
+
+enum Operaciones {
+ SALIR,
+ CONTAR_CIFRAS,
+ SUMAR_CIFRAS,
+ CIFRA_SIGNIFICATIVA,
+ IMAGEN,
+ PRIMO,
+ MCD,
+ TABLA
+};
+
+int numCifras(int num) {
+ int n;
+ //Bucle for, en cada paso dividimos num entre 10 y sumamos 1
+ for(n = 1; num /= 10; n++);
+ return n;
+ //Otra opción sería hacer
+ // #include
+ // return (int)log10(num) + 1;
+}
+
+int sumaCifras(int num) {
+ //Caso base de la recursión: num es menor que 10
+ if(num < 10) {
+ return num;
+ } else {
+ //Recursión: Se elimina la última cifra
+ return sumaCifras(num / 10) + (num % 10);
+ }
+}
+
+int cifraSignificativa(int num, int i) {
+ //Se coje la i-ésima cifra, empezando por el final.
+ for(; i > 1; i--) {
+ num /= 10;
+ }
+
+ return num % 10;
+}
+
+int imagen(int num) {
+ int x;
+ for(x = 0; num > 0; num /= 10) {
+ x = x*10 + (num % 10);
+ }
+ return x;
+}
+
+bool primo(int n) {
+ //Este algoritmo usa el método de Eratóstenes,
+ // eliminando números hasta la raíz cuadrada de n
+ //Indica si el i-ésimo número no es primo
+ bool *no_primos;
+
+ no_primos = calloc(n, sizeof(bool));
+
+ //Recorremos los números enteros hasta la raiz de n
+ for(int i = 2; i*i <= n; i++) {
+ if(no_primos[i]) {
+ //Si ya se comprobó, saltar
+ continue;
+ } else {
+ if(n % i == 0) {
+ //No es primo
+ return false;
+ } else {
+ //Si es primo. Marcamos todos sus múltiplos
+ for(int j = i + 1; j*j <= n; j++) {
+ no_primos[i] = n % j == 0;
+ }
+ }
+ }
+ }
+
+ free(no_primos);
+
+ return true;
+}
+
+int mcd(int a, int b) {
+ //Algoritmo de Euclides recursivo
+ int tmp;
+
+ if(b == 0) {
+ //Caso base
+ return a;
+ } else {
+ if(a > b) {
+ tmp = a % b;
+ } else {
+ tmp = b % a;
+ }
+ return mcd(b, tmp);
+ }
+}
+
+void tabla(int num) {
+ printf(" SUMA RESTA MULT DIV\n");
+ for(int i = 1; i <= 10; i++) {
+ printf("%2d %4d %5d %4d %4d\n", i, num + i, num - i, num * i, num / i);
+ }
+}
+
+void menu() {
+ int op, num, i;
+
+ do {
+ printf("0 - Salir\n");
+ printf("1 - Calcular el número de cifras de un entero\n");
+ printf("2 - Sumar las cifras de un entero\n");
+ printf("3 - Indicar la cifra i-ésima menos significativa de un entero\n");
+ printf("4 - Calcular la imagen especular de un entero\n");
+ printf("5 - Comprobar si un entero es primo\n");
+ printf("6 - Calcula el MCD (mínimo común divisor) de dos números enteros\n");
+ printf("7 - Presentar la tabla de sumar, restar, multiplicar y dividir (hasta 10) de un número entero\n");
+ printf("Introduzca el nº de operación: ");
+ scanf("%d", &op);
+ if(op == SALIR) {
+ continue;
+ }
+ printf("Introduza el número: ");
+ scanf("%d", &num);
+ if(op == CIFRA_SIGNIFICATIVA || op == MCD) {
+ printf("Introduzca el segundo número: ");
+ scanf("%d", &i);
+ }
+ printf("\n");
+ switch(op) {
+ case CONTAR_CIFRAS:
+ printf("%d cifras\n", numCifras(num));
+ break;
+ case SUMAR_CIFRAS:
+ printf("Total: %d\n", sumaCifras(num));
+ break;
+ case CIFRA_SIGNIFICATIVA:
+ printf("Cifra: %d\n", cifraSignificativa(num, i));
+ break;
+ case IMAGEN:
+ printf("%d -> %d\n", num, imagen(num));
+ break;
+ case PRIMO:
+ printf("%d %s primo\n", num, primo(num) ? "es" : "no es");
+ break;
+ case MCD:
+ printf("mcd(%d, %d) = %d\n", num, i, mcd(num, i));
+ break;
+ case TABLA:
+ tabla(num);
+ break;
+ default:
+ printf("Opción incorrecta");
+ };
+ printf("\n");
+ } while(op);
+}
+
+int main() {
+ menu();
+ return 0;
+}
diff --git a/src/Boletin_3/Ejercicio_35.c b/src/Boletin_3/Ejercicio_35.c
new file mode 100644
index 0000000..b7ce67e
--- /dev/null
+++ b/src/Boletin_3/Ejercicio_35.c
@@ -0,0 +1,383 @@
+// SPDX-FileCopyrightText: 2024 Pablo R.
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+/* Enunciado: Plantee e implemente, mediante funciones y procedimientos, un programa en Lenguaje C gestionado por menú en el que se presenten opciones para realizar las siguientes operaciones sobre números enteros:
+ *
+ * - Salir del programa
+ * - Tres opciones de entre las siguientes:
+ * - Conocer el número de vocales sin acentuar existentes en un texto que el usuario escribe mientras no aparezca el carácter *.
+ * - Calcular la potencia de un número b elevado a e, sin utilizar los operadores de exponenciación.
+ * - Mostrar por pantalla el factorial del menor de dos números enteros positivos que introduzca por teclado el usuario.
+ * - Visualizar una tabla con los cuadrados y los cubos de los números contenidos en un intervalo de enteros indicado por el usuario.
+ * - Dibujar un cuadrado, aproximadamente centrado, en pantalla con el carácter y longitud del lado que indique el usuario.
+ * - Mostrar el área y el perímetro del rectángulo de menor área. El usuario debe indicar las longitudes de los lados de los dos rectángulos.
+ * - Visualizar una tabla de los números, los cuadrados y las raíces cuadradas de aquellos números contenidos en un intervalo de enteros indicado por el usuario.
+ * - Calcular el máximo, el mínimo y la media de una serie de números enteros que el usuario introduce por teclado. Finaliza la serie cuando el número introducido es múltiplo de 10.
+ * - Mostrar por pantalla los divisores de un número entero que indique el usuario.
+ * - Dibujar un triángulo equilátero, aproximadamente centrado, en pantalla con el carácter y longitud del lado que indique el usuario.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+enum Operaciones {
+ SALIR,
+ VOCALES,
+ POTENCIA,
+ FACTORIAL,
+ CUBOS,
+ CUADRADO,
+ RECTANGULO,
+ TABLA,
+ MAXIMO,
+ DIVISORES,
+ EQUILATERO
+};
+
+void vocales() {
+ char c;
+ int n = 0;
+
+ printf("Introduzca el texto. Introduzca «*» y pulse intro para terminar: ");
+ do {
+ c = getc(stdin);
+ switch(c) {
+ case 'a':
+ case 'e':
+ case 'i':
+ case 'o':
+ case 'u':
+ case 'A':
+ case 'E':
+ case 'I':
+ case 'O':
+ case 'U':
+ n++;
+ break;
+ }
+ } while(c != EOF && c != '*');
+
+ printf("%d vocales\n", n);
+}
+
+int potencia(int base, int exponente) {
+ int n;
+
+ //Para no usar las funciones de exponenciación, se hace un simple bucle
+ for(n = 1; exponente > 0; exponente--) {
+ n *= base;
+ }
+
+ return n;
+}
+
+int factorial(int n) {
+ if(n <= 1) {
+ return 1;
+ } else {
+ return n * factorial(n - 1);
+ }
+}
+
+void cuadradosYCubos(int de, int hasta) {
+ printf("%5s Cuadrado Cubo\n", "");
+ for(int i = de; i <= hasta; i++) {
+ printf("%5d %8d %8d\n", i, i*i, i*i*i);
+ }
+}
+
+void dibujarCuadrado(int lado, char caracter) {
+ int i;
+ //Primera línea
+ for(i = 0; i < lado; i++) {
+ putchar(caracter);
+ }
+ putchar('\n');
+ //Siguientes líneas
+ for(i = 1; i < lado - 1; i++) {
+ putchar(caracter);
+ for(int j = 1; j < lado - 1; j++) {
+ putchar(' ');
+ }
+ putchar(caracter);
+ putchar('\n');
+ }
+ //Línea final
+ for(i = 0; i < lado; i++) {
+ putchar(caracter);
+ }
+}
+
+void areaRectangulo(int largoA, int cortoA, int largoB, int cortoB) {
+ int areaA, areaB, perimetroA, perimetroB;
+
+ areaA = largoA * cortoA;
+ perimetroA = (largoA + cortoA)*2;
+
+ areaB = largoB * cortoB;
+ perimetroB = (largoB + cortoB)*2;
+
+ if(areaA < areaB) {
+ printf("Rectángulo %d %d: Área %d Perímetro %d\n", largoA, cortoA, areaA, perimetroA);
+ } else {
+ printf("Rectángulo %d %d: Área %d Perímetro %d\n", largoB, cortoB, areaB, perimetroB);
+ }
+}
+
+void raices(int de, int hasta) {
+ printf("%5s Cuadrado Raiz cuadrada\n", "");
+ for(int i = de; i <= hasta; i++) {
+ printf("%5d %8d %e\n", i, i*i, sqrt(i));
+ }
+}
+
+void maximo() {
+ long *numeros, tmp, max, i;
+ char *entrada, *continuar, *entradaTmp;
+ size_t tamEntrada = sizeof(char);
+
+ long maximo, minimo;
+ float media;
+
+
+ //Inicializar la cadena que contendrá la entrada
+ entrada = malloc(sizeof(char));
+ printf("Introduzca los números separados por espacios. Termine con un salto de línea: ");
+ getline(&entrada, &tamEntrada, stdin);
+ entradaTmp = entrada;
+ continuar = entrada;
+
+ //Inicializar el vector de números
+ numeros = calloc(tamEntrada / 2 + 1, sizeof(int));
+ //Si el número es múltiplo de 10, se para
+ for (i = 0; (tmp = strtol(continuar, &entradaTmp, 10)) % 10 != 0; i++ ) {
+ //Si continuar es igual a entradaTmp no se han introducido
+ // números. Si entradaTmp es igual a '\0' es que se ha
+ // leido toda la entrada.
+ if(continuar == entradaTmp || *entradaTmp == '\0') {
+ break;
+ } else {
+ //En cada vuelta, strtol coje un número de continuar, y
+ // apunta al siguiente en la variable entradaTmp
+ continuar = entradaTmp;
+ }
+ numeros[i] = tmp;
+ }
+
+ //Calcular la media, máximo y mínimo
+ max = i;
+ maximo = LONG_MIN;
+ minimo = LONG_MAX;
+ for(i = 0, tmp = 0; i < max; i++) {
+ tmp += numeros[i];
+ if(numeros[i] > maximo) {
+ maximo = numeros[i];
+ }
+ if(numeros[i] < minimo) {
+ minimo = numeros[i];
+ }
+ }
+ media = (float)tmp / max;
+
+ printf("Máximo: %ld\nMínimo: %ld\nMedia: %f\n", maximo, minimo, media);
+
+ free(numeros);
+ free(entrada);
+}
+
+void divisores(int num) {
+ printf("Divisores de %d: ", num);
+ for(int i = 2; i < num; i++) {
+ if(num % i == 0) {
+ printf("%d ", i);
+ }
+ }
+ printf("\n");
+}
+
+void triangulo(int lado, char caracter) {
+ int i;
+
+ int espacioAntes, espacioEntre;
+
+ if(lado % 2 == 0) {
+ espacioAntes = (lado - 2) / 2;
+ espacioEntre = 2;
+ } else {
+ espacioAntes = lado / 2;
+ espacioEntre = 1;
+ }
+
+ //Punta del triángulo
+ //Si lado es par, 2 asteriscos
+ //Si impar, 1 asterisco
+ for(i = 0; i < espacioAntes; i++) {
+ putchar(' ');
+ }
+ putchar(caracter);
+ if(lado % 2 == 0) {
+ putchar(caracter);
+ }
+ putchar('\n');
+
+ //Dibujar los lados
+ // El espacio anterior se reduce un caracter de cada vez
+ // El espacio interior se reduce de 2 en 2
+ for(espacioAntes-- ; espacioAntes > 0; espacioAntes--, espacioEntre += 2) {
+ //Dibujar espacios antes
+ for(i = 0; i < espacioAntes; i++) {
+ putchar(' ');
+ }
+ putchar(caracter);
+ //Dibujar espacios entre
+ for(i = 0; i < espacioEntre; i++) {
+ putchar(' ');
+ }
+ putchar(caracter);
+ putchar('\n');
+ }
+
+ //Dibujar el lado inferior
+ for(i = 0; i < lado; i++) {
+ putchar(caracter);
+ }
+ putchar('\n');
+}
+
+
+//Función auxiliar con gets que lee un número por pantalla
+//Equivalente a scanf("%d")
+int leerNumero() {
+ size_t len = 10*sizeof(char);
+ char *str;
+ int n;
+
+ str = calloc(10, sizeof(char));
+ getline(&str, &len, stdin);
+
+ n = strtol(str, NULL, 10);
+ free(str);
+ return n;
+}
+
+void menu() {
+ int op, tmpA, tmpB, tmpC, tmpD;
+ size_t len;
+ char *c;
+
+ c = calloc(10, sizeof(char));
+
+ do {
+printf(" 0 - Salir del programa\n");
+printf(" 1 - Conocer el número de vocales sin acentuar existentes en un texto que el usuario escribe mientras no aparezca el carácter *\n");
+printf(" 2 - Calcular la potencia de un número b elevado a e, sin utilizar los operadores de exponenciación\n");
+printf(" 3 - Mostrar por pantalla el factorial del menor de dos números enteros positivos que introduzca por teclado el usuario\n");
+printf(" 4 - Visualizar una tabla con los cuadrados y los cubos de los números contenidos en un intervalo de enteros indicado por el usuario\n");
+printf(" 5 - Dibujar un cuadrado, aproximadamente centrado, en pantalla con el carácter y longitud del lado que indique el usuario\n");
+printf(" 6 - Mostrar el área y el perímetro del rectángulo de menor área. El usuario debe indicar las longitudes de los lados de los dos rectángulos\n");
+printf(" 7 - Visualizar una tabla de los números, los cuadrados y las raíces cuadradas de aquellos números contenidos en un intervalo de enteros indicado por el usuario\n");
+printf(" 8 - Calcular el máximo, el mínimo y la media de una serie de números enteros que el usuario introduce por teclado. Finaliza la serie cuando el número introducido es múltiplo de 10\n");
+printf(" 9 - Mostrar por pantalla los divisores de un número entero que indique el usuario\n");
+printf("10 - Dibujar un triángulo equilátero, aproximadamente centrado, en pantalla con el carácter y longitud del lado que indique el usuario\n");
+ printf("Introduzca el nº de operación: ");
+ op = leerNumero();
+ if(op == SALIR) {
+ continue;
+ }
+ printf("\n");
+ switch(op) {
+ case VOCALES:
+ vocales();
+ break;
+
+ case POTENCIA:
+ printf("Base: ");
+ tmpA = leerNumero();
+ printf("Exponente: ");
+ tmpB = leerNumero();
+ printf("Resultado %d ** %d: %d", tmpA, tmpB, potencia(tmpA, tmpB));
+ break;
+
+ case FACTORIAL:
+ printf("Primer número: ");
+ tmpA = leerNumero();
+ printf("Segundo número: ");
+ tmpB = leerNumero();
+ if(tmpA > tmpB) {
+ printf("Factorial de %d: %d\n", tmpB, factorial(tmpB));
+ } else {
+ printf("Factorial de %d: %d\n", tmpA, factorial(tmpA));
+ }
+ break;
+
+ case CUBOS:
+ printf("De: ");
+ tmpA = leerNumero();
+ printf("Hasta: ");
+ tmpB = leerNumero();
+ cuadradosYCubos(tmpA, tmpB);
+ break;
+
+ case CUADRADO:
+ printf("Caracter: ");
+ getline(&c, &len, stdin);
+ printf("Tamaño: ");
+ tmpA = leerNumero();
+ dibujarCuadrado(tmpA, c[0]);
+ break;
+
+ case RECTANGULO:
+ printf("Longitudes de los lados largo y ancho del primer rectángulo, separados por espacios: ");
+ getline(&c, &len, stdin);
+ sscanf("%d %d", c, &tmpA, &tmpB);
+ printf("Longitudes de los lados largo y ancho del segundo rectángulo, separados por espacios: ");
+ getline(&c, &len, stdin);
+ sscanf("%d %d", c, &tmpC, &tmpD);
+ areaRectangulo(tmpA, tmpB, tmpC, tmpD);
+ break;
+
+ case TABLA:
+ printf("De: ");
+ tmpA = leerNumero();
+ printf("Hasta: ");
+ tmpB = leerNumero();
+ raices(tmpA, tmpB);
+ break;
+
+ case MAXIMO:
+ maximo();
+ break;
+
+ case DIVISORES:
+ printf("Introduca el número: ");
+ tmpA = leerNumero();
+ divisores(tmpA);
+ break;
+
+ case EQUILATERO:
+ printf("Caracter: ");
+ getline(&c, &len, stdin);
+ printf("Tamaño: ");
+ tmpA = leerNumero();
+ triangulo(tmpA, c[0]);
+ break;
+
+ default:
+ printf("Opción incorrecta");
+ };
+ printf("\n");
+ } while(op);
+
+ free(c);
+}
+
+int main() {
+ menu();
+ return 0;
+}
diff --git a/src/Boletin_3/Ejercicio_36.c b/src/Boletin_3/Ejercicio_36.c
new file mode 100644
index 0000000..dcb05d5
--- /dev/null
+++ b/src/Boletin_3/Ejercicio_36.c
@@ -0,0 +1,197 @@
+// SPDX-FileCopyrightText: 2024 Pablo R.
+//
+// SPDX-License-Identifier: GPL-3.0-only
+
+/* Enunciado: Implemente un programa en Lenguaje C para trabajar con números complejos. Las opciones que debe tener son:
+1. Introducir dos números complejos en forma binómica por teclado
+2. Introducir dos números complejos en forma módulo-argumental por teclado
+3. Sumar dos números complejos
+4. Restar dos números complejos
+5. Multiplicar dos números complejos
+0. Salir
+*/
+
+#include
+#include
+#include
+#include
+
+enum Operaciones {
+ SALIR,
+ BINOMICA,
+ MODULO,
+ SUMAR,
+ RESTAR,
+ MULTIPLICAR
+};
+
+typedef struct {
+ double real;
+ double imaginario;
+} Binomica;
+
+typedef struct {
+ double modulo;
+ double argumento;
+} ModuloArg;
+
+
+typedef struct {
+ bool binomico;
+ union {
+ Binomica b;
+ ModuloArg m;
+ };
+} Numero;
+
+void binomicaAModulo(Binomica *origen, ModuloArg *destino) {
+ destino->modulo = sqrt(origen->real*origen->real + origen->imaginario*origen->imaginario);
+ destino->argumento = atan(origen->imaginario);
+}
+
+void moduloABinomica(ModuloArg *origen, Binomica *destino) {
+ destino->imaginario = tan(origen->argumento);
+ destino->real = sqrt(origen->modulo*origen->modulo - destino->imaginario*destino->imaginario);
+}
+
+void escribirNumero(Numero *n, const char *nombre) {
+ printf("%s ", nombre);
+
+ if(n->binomico) {
+ printf("(binomico): z = %e + i*%e", n->b.real, n->b.imaginario);
+ } else {
+ printf("(módulo-argumental): |%e|_%e ", n->m.modulo, n->m.argumento);
+ }
+
+ printf("\n");
+}
+
+void sumaBinomico(Binomica *x, Binomica *y, Binomica *z) {
+ z->real = x->real + y->real;
+ z->imaginario = x->imaginario + y->imaginario;
+}
+
+void restaBinomico(Binomica *x, Binomica *y, Binomica *z) {
+ z->real = x->real - y->real;
+ z->imaginario = x->imaginario - y->imaginario;
+}
+
+void multBinomico(Binomica *x, Binomica *y, Binomica *z) {
+ z->real = x->real*y->real - x->imaginario*y->imaginario;
+ z->imaginario = x->imaginario*y->real + x->real*y->imaginario;
+}
+
+void menu() {
+ int op;
+ double tmpA, tmpB;
+ Numero x, y, z;
+ Binomica tempA, tempB;
+ ModuloArg tempC;
+
+ do {
+ printf(" 1. Introducir dos números complejos en forma binómica por teclado\n");
+ printf(" 2. Introducir dos números complejos en forma módulo-argumental por teclado\n");
+ printf(" 3. Sumar dos números complejos\n");
+ printf(" 4. Restar dos números complejos\n");
+ printf(" 5. Multiplicar dos números complejos\n");
+ printf(" 0. Salir\n");
+ printf("Escoja una opción: ");
+ scanf("%d", &op);
+ if(op == SALIR) {
+ continue;
+ }
+ printf("\n");
+ switch(op) {
+ case BINOMICA:
+ printf("Introduzca los números, con la parte real e imaginaria separados por espacios.\n");
+ printf("X: ");
+ scanf("%lf %lf", &tmpA, &tmpB);
+ x.binomico = true;
+ x.b.real = tmpA;
+ x.b.imaginario = tmpB;
+ printf("Y: ");
+ scanf("%lf %lf", &tmpA, &tmpB);
+ y.binomico = true;
+ y.b.real = tmpA;
+ y.b.imaginario = tmpB;
+ break;
+
+ case MODULO:
+ printf("Introduzca los números, con el módulo y argumento separados por espacios.\n");
+ printf("X: ");
+ scanf("%lf %lf", &tmpA, &tmpB);
+ x.binomico = false;
+ x.m.modulo = tmpA;
+ x.m.argumento = tmpB;
+ printf("Y: ");
+ scanf("%lf %lf", &tmpA, &tmpB);
+ y.binomico = false;
+ y.m.modulo = tmpA;
+ y.m.argumento = tmpB;
+ break;
+
+ case SUMAR:
+ if(x.binomico && y.binomico) {
+ sumaBinomico(&x.b, &y.b, &(z.b));
+ } else {
+ moduloABinomica(&x.m, &tempA);
+ moduloABinomica(&y.m, &tempB);
+ sumaBinomico(&tempA, &tempB, &(z.b));
+ }
+ z.binomico = true;
+ escribirNumero(&z, "Z");
+
+ z.binomico = false;
+ binomicaAModulo(&z.b, &tempC);
+ z.m = tempC;
+ escribirNumero(&z, "Z");
+ break;
+
+ case RESTAR:
+ if(x.binomico && y.binomico) {
+ restaBinomico(&x.b, &y.b, &(z.b));
+ } else {
+ moduloABinomica(&x.m, &tempA);
+ moduloABinomica(&y.m, &tempB);
+ restaBinomico(&tempA, &tempB, &(z.b));
+ }
+ z.binomico = true;
+ escribirNumero(&z, "Z");
+
+ z.binomico = false;
+ binomicaAModulo(&z.b, &tempC);
+ z.m = tempC;
+ escribirNumero(&z, "Z");
+ break;
+
+ case MULTIPLICAR:
+ if(x.binomico && y.binomico) {
+ multBinomico(&x.b, &y.b, &(z.b));
+ } else {
+ moduloABinomica(&x.m, &tempA);
+ moduloABinomica(&y.m, &tempB);
+ multBinomico(&tempA, &tempB, &(z.b));
+ }
+ z.binomico = true;
+ escribirNumero(&z, "Z");
+
+ z.binomico = false;
+ binomicaAModulo(&z.b, &tempC);
+ z.m = tempC;
+ escribirNumero(&z, "Z");
+ break;
+
+ default:
+ printf("Opción incorrecta");
+ };
+ printf("\n");
+ printf("Números cargados:\n");
+ escribirNumero(&x, "X");
+ escribirNumero(&y, "Y");
+ } while(op);
+}
+
+int main() {
+ menu();
+ return 0;
+}