La tarea básica es simple: dados N números reales, se debe calcular su promedio. Sin embargo, lo que lo complica es que algunos números de entrada pueden no ser válidos. Una entrada válida es un número real en el rango [−1000, 1000] y con una precisión de no más de 2 decimales. Al calccular el promedio, esos números ilegales no deben ser contados.
Especificación de entrada:
Cada archivo de entrada contiene un caso de prueba. En la primera línea se da un entero positivo N (≤ 100). Luego, en la siguiente línea se dan N números, separados por un espacio.
Especificación de salida:
Para cada número de entrada ilegal, imprima en una línea ERROR: X is not a legal number donde X es la entrada. Luego, imprima en una línea el resultado: The average of K numbers is Y, donde K es la cantidad de entradas válidas e Y es su promedio, con precisión de 2 decimales. En caso de que no se pueda calcular el promedio, imprima Undefined en lugar de Y. En caso de que K sea solo 1, imprima The average of 1 number is Y en su lugar.
Ejemplo de entrada 1:
7
5 -3.2 aaa 9999 2.3.4 7.123 2.35
Ejemplo de salida 1:
ERROR: aaa is not a legal number
ERROR: 9999 is not a legal number
ERROR: 2.3.4 is not a legal number
ERROR: 7.123 is not a legal number
The average of 3 numbers is 1.38
Ejemplo de entrada 2:
2
aaa -9999
Ejemplo de salida 2:
ERROR: aaa is not a legal number
ERROR: -9999 is not a legal number
The average of 0 numbers is Undefined
Código de solución:
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <cmath>
using namespace std;
// Función que valida y convierte una cadena a número real.
// Retorna true si la cadena es válida y asigna el valor a 'resultado'.
bool parsearNumero(const string &cadena, double &resultado) {
// Permitir un signo negativo al inicio
if (cadena.empty()) return false;
string limpia = cadena;
bool negativo = false;
size_t inicio = 0;
if (cadena[0] == '-') {
negativo = true;
inicio = 1;
if (cadena.size() == 1) return false; // Solo el signo
}
// Verificar caracteres permitidos: dígitos y un punto decimal
int puntoPos = -1;
for (size_t i = inicio; i < cadena.size(); ++i) {
char c = cadena[i];
if (c == '.') {
if (puntoPos != -1) return false; // Más de un punto
puntoPos = static_cast<int>(i);
} else if (c < '0' || c > '9') {
return false; // Carácter no válido
}
}
// Si hay punto, verificar que no esté al final y que tenga máximo 2 decimales
if (puntoPos != -1) {
if (puntoPos == static_cast<int>(cadena.size()) - 1) return false; // punto final
int decimales = static_cast<int>(cadena.size()) - puntoPos - 1;
if (decimales > 2) return false;
}
// Convertir usando stringstream
stringstream ss(cadena);
double valor;
ss >> valor;
if (ss.fail()) return false;
// Verificar rango
if (valor < -1000.0 || valor > 1000.0) return false;
resultado = valor;
return true;
}
int main() {
int n;
cin >> n;
int cuentaValidos = 0;
double suma = 0.0;
for (int i = 0; i < n; ++i) {
string token;
cin >> token;
double numero;
if (parsearNumero(token, numero)) {
suma += numero;
++cuentaValidos;
} else {
cout << "ERROR: " << token << " is not a legal number" << endl;
}
}
cout << fixed << setprecision(2);
if (cuentaValidos == 0) {
cout << "The average of 0 numbers is Undefined" << endl;
} else if (cuentaValidos == 1) {
cout << "The average of 1 number is " << suma << endl;
} else {
double promedio = suma / cuentaValidos;
cout << "The average of " << cuentaValidos << " numbers is " << promedio << endl;
}
return 0;
}