1. Entrada y salida
1.1. Leer horas, minutos, segundos
Escriba un programa que lea una hora en formato h:m:s
y la imprima con ceros a la izquierda.
#include <stdio.h>
// procedure main()
int main() {
unsigned short hour = 0, min = 0, sec = 0;
//scanf("%hu:%hu:%hu", &hour, &min, &sec);
printf("hour %hu:%hu:%hu\n", hour, min, sec);
}
2. Expresiones y condicionales
Escriba una expresión que resuelva cada una de las siguientes situaciones.
2.1. Números aleatorios en rango
Suponga que rand()
genera un número aleatorio entero en el rango {0, …, r - 1}
, donde normalmente r = 2^31
. Escriba una expresión/función que siempre genere un número aleatorio de lotería, es decir, entre {00, …, 99}.
int rand100() {
return rand() % 100;
}
Escriba una expresión/función que genere un número aleatorio entero entre {a, …, b - 1}
.
2.1.1. Diseño por contratos
Versión 1. Diseño por contratos (design by contract). Indicar en la documentación (comentarios) que es responsabilidad de quien usa la función, proveer los valores correctos.
/**
* @brief Return a random number in range [min, max[.
* @param min The minimum number
* @param max The maximum
* @remark min must be less than max, otherwise the function generates
* invalid data or may crash the process
* @return A random number in range [min, max[.
*/
int rand_between(const int min, const int max) {
return min + rand() % (max - min);
}
2.1.2. Assert
Versión 2. Programación defensiva (defensive programming) con diseño por contratos. La subrutina se defiende ante situaciones anómalas o problemáticas pero sólo advierte a desarrolladores, no usuarios. La expresión assert()`
evalúa una condición, si esta es falsa, detiene el programa y reporta un error para el equipo de desarrollo en lo que se conoce como "versión debug" del programa. En la versión para los usuarios finales (release), los assert()
son removidos (como si nunca hubieran estado en el código fuente) porque no tiene sentido que un supuesto se dispare a quien no tiene responsabilidad del código fuente.
/**
* @brief Return a random number in range [min, max[.
* @param min The minimum number
* @param max The maximum
* @remark min must be less than max, otherwise the function generates
* invalid data
* @return A random number in range [min, max[.
*/
int rand_between(int min, int max) {
assert(min < max);
return min + rand() % (max - min);
}
2.1.3. Programación defensiva
Versión 3. Programación defensiva (defensive programming). La subrutina se defiende ante situaciones anómalas o problemáticas con condicionaes if ()
que verifica los supuestos y se defiende de errores de desarrolladores y usuarios con reacciones como retornar códigos de error, avisa de errores en alguna memoria compartida, lanza excepciones, o imprime mensajes de error. Esta es la versión que debe usarse si los datos provienen de usuarios humanos, otros programas, o fuentes no confiables.
/**
* @brief Return a random number in range [min, max[.
* @param min The minimum number
* @param max The maximum
* @remark If min >= max, raises an exception
* @return A random number in range [min, max[.
*/
int rand_between(int min, int max) {
if (min < max) {
return min + rand() % (max - min);
} else {
// Return an error-code
// Set a global variable with error code
// Raise/throw an exception
// Print an error message
}
}
2.1.4. Rango aleatorio en Java
Adapte las expresiones de los dos ejercicios anteriores, si el número aleatorio es un flotante en el rango [0, 1[
.
Math.rand()
cada vez que se invoca, genera un flotante al azar en el rango [0, 1]public int randBetween(int min, int max) {
if (min < max) {
return min + (int) (Math.random() * (max - min));
} else {
// TODO(you): fix
}
}
2.2. Días después
Si hoy es domingo, qué día de la semana es dentro de x
días. Por ejemplo, para x=1
sería lunes, x=2
sería martes, x=7
sería domingo, x=10
sería miércoles. Escriba una función que recibe x
y retorne el número de día. Escriba otra que recibe un número de día y retorne un texto con el nombre del día.
public int daysAfter(int x) {
assert x >= 0;
return x % 7;
}
if/else
public String nameDaysAfter(int x) {
String result = "";
if (daysAfter(x) == 0) {
result = "domingo";
} else if (daysAfter(x) == 1) {
result = "lunes";
} else if (daysAfter(x) == 2) {
result = "martes";
} else if (daysAfter(x) == 3) {
result = "miercoles";
} else if (daysAfter(x) == 4) {
result = "jueves";
} else if (daysAfter(x) == 5) {
result = "viernes";
} else if (daysAfter(x) == 6) {
result = "sabado";
} else {
assert false;
}
return result;
}
switch
public String nameDaysAfter(int x) {
String result = "";
switch (daysAfter(x)) {
case 0: result = "domingo"; break;
case 1: result = "lunes"; break;
case 2: result = "martes"; break;
case 3: result = "miercoles"; break;
case 4: result = "jueves"; break;
case 5: result = "viernes"; break;
case 6: result = "sabado"; break;
default: assert false; break;
}
return result;
}
if
y return
public String nameDaysAfter(int x) {
if (daysAfter(x) == 0) return "domingo";
if (daysAfter(x) == 1) return "lunes";
if (daysAfter(x) == 2) return "martes";
if (daysAfter(x) == 3) return "miercoles";
if (daysAfter(x) == 4) return "jueves";
if (daysAfter(x) == 5) return "viernes";
if (daysAfter(x) == 6) return "sabado";
assert false;
}
switch
y return
public String nameDaysAfter(int x) {
switch (daysAfter(x)) {
case 0: return "domingo";
case 1: return "lunes";
case 2: return "martes";
case 3: return "miercoles";
case 4: return "jueves";
case 5: return "viernes";
case 6: return "sabado";
default: assert false; break;
}
}
2.3. Tablero de bingo
Cuando el organizador de un juego de Bingo saca una bola de la tómbola, debe colocarla en una mesa que tiene 5 filas, una por cada letra de la palabra BINGO. Cada fila tiene 15 agujeros. Cuando sale el número x
de la tómbola, ¿en qué letra (fila) y agujero debe colocarla el organizador? Escriba un procedimiento que recibe el número de la bola e imprime en la salida estándar la letra de la fila y el número del agujero donde debe colocarse.
public int bingoColumn(int ball) {
assert ball >= 1 && ball <= 75;
return (ball - 1) % 15 + 1;
}
public int bingoRow(int ball) {
assert ball >= 1 && ball <= 75;
return (ball - 1) / 15 + 1;
}
public char bingoRowLetter(int ball) {
int index = bingoRow(ball);
assert index >= 1 && index <= 5;
return "BINGO".charAt(index - 1);
}
2.4. El ventanal roto
Un ventanal de un templo de 2m de ancho por 3m de alto, esta construido con varios vidrios cuadrados de 50cm de lado, dispuestos matricialmente. Suponga que el inicio es la esquina superior izquierda. El templo está frente a una plaza de deportes y raras veces una bola rompe uno de los vídrios. Si la bola golpea x
metros a la derecha del inicio y y
metros hacia abajo del inicio, ¿en qué fila y columna se encuentra el vídrio roto? Por ejemplo, si la bola impacta en x=1.04m
y y=2.17m
, el mosaico a reemplazar sería el que está en la fila 5 y columna 3. Escriba un procedimiento que recibe x
y y
e imprime la fila y columna del vidrio que debe reemplazarse.
2.5. Tablero de memoria
Un juego de memoria ocupa la totalidad de una pantalla de 640x480 pixeles. Las cartas están en 10 filas y 10 columnas. Si el usuario hace click en el píxel (x, y)
¿En cuál fila y columna está la carta que debe voltearse? Tome en consideración que las ventanas tienen su inicio en la esquina inferior izquierda.
2.6. Imagen en la última página
Se debe imprimir un documento de R
líneas en páginas tamaño oficio a las que les cabe r
líneas. Se quiere imprimir una imagen de H
líneas de alto en la última página (H
< r
), sólo si queda espacio. Diseñe una función que indique si se puede o no agregar la imagen sin tener que incurrir en una página en blanco más. Por ejemplo, una imagen de H=15
líneas cabe perfectamente en la última página, si se imprimen R=70
líneas en páginas con capacidad para r=30
línas, pero no una imagen de 21 líneas.
3. Ciclos
3.1. Estadísticas v1
Escriba un programa que lea un número C
de la entrada estándar. Luego lee C
números enteros de la entrada estándar. Finalmente el programa imprime: el menor de los números, el promedio, y el mayor de los valores. Por ejemplo, la entrada:
4 80 95 40 80
produciría:
Min: 40 Average: 73.75 Max: 95
for
) dado que se conoce la cantidad de iteraciones de antemanopublic void run() {
final int valueCount = this.input.nextInt();
double min = Double.POSITIVE_INFINITY;
double max = Double.NEGATIVE_INFINITY;
double sum = 0.0;
for (int counter = 0; counter < valueCount; counter = counter + 1) {
final double value = this.input.nextDouble();
if (value < min) {
min = value;
}
if (value > max) {
max = value;
}
sum = sum + value;
}
System.out.printf("Min: %f%n", min);
final double average = sum / valueCount;
System.out.printf("Average: %f%n", average);
System.out.printf("Max: %f%n", max);
}
Valide la entrada del programa anterior, de tal forma que el número C
sea siempre positivo. Si es cero, no imprima ninguna estadística. Si es negativo o un texto, imprima un mensaje de error en el error estándar.
3.2. Estadísticas v2
Escriba un programa que lea todos los números reales de la entrada estándar hasta encontrar el fin-de-archivo, e imprima: la cantidad de ellos, el menor de ellos, el promedio, y el mayor de los valores. Por ejemplo, la entrada:
80 95 40 80
produciría:
Count: 4 Min: 40 Average: 73.75 Max: 95
while
) dado que no se conoce la cantidad de iteraciones de antemanopublic void run() {
int valueCount = 0;
double min = Double.POSITIVE_INFINITY;
double max = Double.NEGATIVE_INFINITY;
double sum = 0.0;
while (this.input.hasNextDouble()) {
final double value = this.input.nextDouble();
if (value < min) {
min = value;
}
if (value > max) {
max = value;
}
sum = sum + value;
valueCount = valueCount + 1;
}
System.out.printf("Count: %d%n", valueCount);
System.out.printf("Min: %f%n", min);
final double average = sum / valueCount;
System.out.printf("Average: %f%n", average);
System.out.printf("Max: %f%n", max);
}
3.3. Secuencia programada
Haga un programa que lea una secuencia de números enteros de la entrada estándar. Si el número es negativo, por ejemplo, -5, el programa "se brinca" los siguientes 5 números en la entrada estándar. Si el número es positivo, el programa lo suma a un resultado. Si el número es 0, el programa termina su ejecución e imprime la suma resultado. Por ejemplo, la siguiente entrada produce 16
:
7 3 -4 1 0 -2 -8 -2 3 4 6 -1 0 0 4
Si los números se acaban antes de encontrar un cero, imprima invalid program
en lugar de la suma resultado.
3.4. El arbolito de navidad
-
Construya un programa que imprima un árbol de navidad. El programa lee de la entrada la cantidad de ramas que tiene el árbol y el carácter con que se debe imprimir el árbol. Por ejemplo,
4 *
produce* *** ***** ******* *
¿Por qué esta implementación no produce el resultado correcto? Corríjala para que imprima el árbol de navidad como se espera.
3.5. Intercambio for/while
Cambie los siguientes ciclos de for
a while
y viceversa.
while (true) {
int x = this.input.nextInt();
if (x <= 0) {
break;
}
}
Solución:
// for (; true;) {
for (;;) {
int x = this.input.nextInt();
if (x <= 0) {
break;
}
}
int i = 1, n = this.input.nextInt(), p = 1;
while (i <= n) {
p *= this.input.nextInt();
++i;
}
Solución:
for (int i = 1, n = this.input.nextInt(), p = 1; i <= n; ++i) {
p *= this.input.nextInt();
}
double total = 0.0;
while (this.input.hasNextDouble()) {
total += this.input.nextInt();
}
System.out.println(total);
Solución:
double total = 0.0;
for (; this.input.hasNextDouble(); total += this.input.nextInt()) {
// empty loop
}
System.out.println(total);
double total = 0.0;
for (; this.input.hasNextDouble(); ) {
total += this.input.nextInt();
}
System.out.println(total);
double diffSum = 0.0;
try {
for (int c = 0; ; c++) {
final double a = this.input.nextDouble();
final double b = this.input.nextDouble();
diffSum += Math.abs(a - b);
}
System.out.println(diffSum);
} catch (final java.util.NoSuchElementException error) {
System.out.println(diffSum);
} catch (final java.util.InputMismatchException error) {
System.err.println("invalid data");
}
Solución:
4. Subrutinas
5. Arreglos y matrices
5.1. Arreglos literales
Escriba otra versión de la función al problema "Días después" (Section 2.2) que use arreglos para retornar un texto con el nombre del día.
public String nameDaysAfter(int x) {
final String[] days = { "domingo", "lunes", "martes", "miercoles", "jueves", "viernes", "sabado" };
if (daysAfter(x) >= 0 && daysAfter(x) < days.length) {
return days[daysAfter(x)];
} else {
throw new Exception("index out of bounds");
}
}
5.2. Asociación con índices
Escriba un programa que cuente cuántas apariciones hay de cada letra del alfabeto inglés en un texto. Considere mayúsculas y minúsculas como si fuesen iguales. Cualquier otro carácter que no sea una letra del alfabeto en inglés, considérela como puntuación. Si una letra no aparece en el texto, no la reporte en la salida. Recuerde que los arreglos asocian números enteros no negativos conocidos como índices a datos de cualquier tipo.
Ejemplo de entrada:
Practice makes perfect.
Ejemplo de salida:
a: 2
c: 3
e: 4
f: 1
i: 1
k: 1
m: 1
p: 2
r: 2
s: 1
t: 2
*: 3
5.3. Matriz traspuesta
Haga un programa que lea una matriz de enteros grandes de la entrada estándar. En la primera línea están sus dimensiones en filas y columnas. Si la matriz es cuadrada y es la matriz identidad, imprima en la salida estándar identity matrix
. De lo contrario, construya en memoria la matrix traspuesta, y luego imprímala.
Ejemplo de entrada 1:
3 4
1 0 1 3
7 1 0 1
0 0 8 5
Ejemplo de salida 1:
1 7 0
0 1 0
1 0 8
3 1 5
Ejemplo de entrada 2:
3 3
1 0 0
0 1 0
0 0 1
Ejemplo de salida 2:
identity matrix