using System.Collections.Generic;
static void Main(string[] args)
var app = new EstadisticaApp();
string archivoNombre = "";
List<double> datosNoAgrupados = new List<double>();
List<(double Xi, int fi)> datosAgrupados = new List<(double, int)>();
Console.WriteLine("Bienvenido al programa estadístico.");
Console.Write("Ingrese su nombre: ");
string nombreUsuario = Console.ReadLine();
archivoNombre = $"{nombreUsuario}.txt";
archivo = new StreamWriter(archivoNombre, false);
archivo.WriteLine($"Usuario: {nombreUsuario}");
archivo.WriteLine($"Fecha inicio: {DateTime.Now}");
string opcion = Console.ReadLine();
MenuVariablesAleatorias();
Console.WriteLine("Opcion Invalida.");
archivo.WriteLine($"Fecha fin: {DateTime.Now}");
void MostrarMenuPrincipal()
Console.WriteLine("\nMenú principal:");
Console.WriteLine("1) Ingresar datos");
Console.WriteLine("2) Técnicas de conteo");
Console.WriteLine("3) Variables aleatorias discretas");
Console.WriteLine("4) Consultar historial");
Console.WriteLine("5) Salir");
Console.Write("Seleccione opción: ");
datosNoAgrupados.Clear();
Console.WriteLine("\nIngrese los datos numéricos a evaluar. Para terminar, ingrese 'f':");
string entrada = Console.ReadLine();
if (entrada.ToLower() == "f") break;
if (double.TryParse(entrada, out double valor))
datosNoAgrupados.Add(valor);
Console.WriteLine("Dato invalido, intente de nuevo.");
archivo.WriteLine("\nDatos ingresados:");
archivo.WriteLine(string.Join(", ", datosNoAgrupados));
if (datosNoAgrupados.Count == 0)
Console.WriteLine("No se ingresaron datos.");
if (datosNoAgrupados.Count <= 30)
void MenuDatosNoAgrupados()
Console.WriteLine("\nDatos no agrupados - opciones:\n1) Medidas de tendencia central\n2) Tabla de frecuencias\n3) Medidas de dispersión\n4) Regresar al menú principal");
Console.Write("Seleccione opción: ");
string op = Console.ReadLine();
MedidasTendenciaCentralNoAgrupados();
TablaFrecuenciasNoAgrupados();
MedidasDispersionNoAgrupados();
Console.WriteLine("Opcion invalida.");
void MedidasTendenciaCentralNoAgrupados()
Console.WriteLine("\nMedidas de tendencia central:");
double media = datosNoAgrupados.Average();
archivo.WriteLine($"Media: {media:F4}");
Console.WriteLine($"Media: {media:F4}");
var ordenados = datosNoAgrupados.OrderBy(x => x).ToList();
mediana = (ordenados[n / 2 - 1] + ordenados[n / 2]) / 2.0;
mediana = ordenados[n / 2];
archivo.WriteLine($"Mediana: {mediana:F4}");
Console.WriteLine($"Mediana: {mediana:F4}");
var grupos = datosNoAgrupados.GroupBy(x => x);
int maxFreq = grupos.Max(g => g.Count());
var modas = grupos.Where(g => g.Count() == maxFreq).Select(g => g.Key).ToList();
archivo.WriteLine($"Moda(s): {string.Join(", ", modas)}");
Console.WriteLine($"Moda(s): {string.Join(", ", modas)}");
void TablaFrecuenciasNoAgrupados()
Console.WriteLine("\nTabla de frecuencias (no agrupados):");
int n = datosNoAgrupados.Count;
var grupos = datosNoAgrupados.GroupBy(x => x).OrderBy(g => g.Key);
archivo.WriteLine("Xi\tfi\tfr\tFa\tFra");
Console.WriteLine("Xi\tfi\tfr\tFa\tFra");
foreach (var grupo in grupos)
double fr = (double)fi / n;
double Fra = (double)Fa / n;
archivo.WriteLine($"{grupo.Key}\t{fi}\t{fr:F4}\t{Fa}\t{Fra:F4}");
Console.WriteLine($"{grupo.Key}\t{fi}\t{fr:F4}\t{Fa}\t{Fra:F4}");
void MedidasDispersionNoAgrupados()
Console.WriteLine("\nMedidas de dispersion:");
double media = datosNoAgrupados.Average();
int n = datosNoAgrupados.Count;
double varianza = datosNoAgrupados.Sum(x => Math.Pow(x - media, 2)) / (n - 1);
double desviacion = Math.Sqrt(varianza);
archivo.WriteLine($"Varianza: {varianza:F4}");
archivo.WriteLine($"Desviación estándar: {desviacion:F4}");
Console.WriteLine($"Varianza: {varianza:F4}");
Console.WriteLine($"Desviación estándar: {desviacion:F4}");
void MenuDatosAgrupados()
Console.WriteLine("\nTabla de frecuencias agrupadas (intervalos de 10 en 10)");
if (datosNoAgrupados.Count == 0)
Console.WriteLine("No hay datos para agrupar");
double min = datosNoAgrupados.Min();
double max = datosNoAgrupados.Max();
double rango = max - min;
int n = datosNoAgrupados.Count;
int numClases = (int)Math.Ceiling(1 + 3.32 * Math.Log10(n));
if (numClases < 1) numClases = 1;
double intervalo = Math.Ceiling(rango / numClases);
if (intervalo < 1) intervalo = 1;
double li = Math.Floor(min);
for (int i = 0; i < numClases; i++)
double limiteInferior = li + i * intervalo;
double limiteSuperior = limiteInferior + intervalo;
int fi = datosNoAgrupados.Count(x => x >= limiteInferior && x < limiteSuperior);
double marcaClase = (limiteInferior + limiteSuperior) / 2;
datosAgrupados.Add((marcaClase, fi));
archivo.WriteLine($"\nDatos agrupados en {numClases} clases, intervalo {intervalo}:");
foreach (var d in datosAgrupados)
archivo.WriteLine($"Mc: {d.Xi}, fi: {d.fi}");
Console.WriteLine("\nDatos agrupados - opciones:");
Console.WriteLine("1) Medidas de tendencia central");
Console.WriteLine("2) Tabla de frecuencias");
Console.WriteLine("3) Medidas de dispersión");
Console.WriteLine("4) Regresar al menú principal");
Console.Write("Seleccione opción: ");
string op = Console.ReadLine();
MedidasTendenciaCentralAgrupados();
TablaFrecuenciasAgrupados();
MedidasDispersionAgrupados();
Console.WriteLine("Opción inválida.");
void TablaFrecuenciasAgrupados()
Console.WriteLine("\nTabla de frecuencias agurupados");
if (datosAgrupados.Count == 0)
Console.WriteLine("No hay datos agrupados para mostrar.");
double intervalo = datosAgrupados.Count > 1 ? datosAgrupados[1].Xi - datosAgrupados[0].Xi : 1;
double minMc = datosAgrupados.First().Xi - intervalo / 2;
int numClases = datosAgrupados.Count;
int N = datosAgrupados.Sum(d => d.fi);
string encabezado = "Li\tLs\tMc\tfi\tfr\tFa\tFra";
Console.WriteLine(encabezado);
archivo.WriteLine(encabezado);
for (int i = 0; i < numClases; i++)
double li = minMc + i * intervalo;
double ls = li + intervalo;
double mc = (li + ls) / 2;
int fi = datosAgrupados[i].fi;
double fr = N > 0 ? (double)fi / N : 0;
double Fra = N > 0 ? (double)Fa / N : 0;
string linea = $"{li}\t{ls}\t{mc}\t{fi}\t{fr:F4}\t{Fa}\t{Fra:F4}";
Console.WriteLine(linea);
archivo.WriteLine(linea);
void MedidasTendenciaCentralAgrupados()
Console.WriteLine("\nMedidas de tendencia central (agrupados):");
int n = datosAgrupados.Sum(d => d.fi);
double media = datosAgrupados.Sum(d => d.Xi * d.fi) / n;
archivo.WriteLine($"Media: {media:F4}");
Console.WriteLine($"Media: {media:F4}");
foreach (var d in datosAgrupados.OrderBy(d => d.Xi))
archivo.WriteLine($"Mediana (aproximada): {mediana:F4}");
Console.WriteLine($"Mediana (aproximada): {mediana:F4}");
int maxFi = datosAgrupados.Max(d => d.fi);
var modas = datosAgrupados.Where(d => d.fi == maxFi).Select(d => d.Xi).ToList();
archivo.WriteLine($"Moda(s): {string.Join(", ", modas)}");
Console.WriteLine($"Moda(s): {string.Join(", ", modas)}");
void MedidasDispersionAgrupados()
Console.WriteLine("\nMedidas de dispersión (agrupados):");
int n = datosAgrupados.Sum(d => d.fi);
double media = datosAgrupados.Sum(d => d.Xi * d.fi) / n;
double varianza = datosAgrupados.Sum(d => d.fi * Math.Pow(d.Xi - media, 2)) / (n - 1);
double desviacion = Math.Sqrt(varianza);
archivo.WriteLine($"Varianza: {varianza:F4}\nDesviación estándar: {desviacion:F4}");
Console.WriteLine($"Varianza: {varianza:F4}\nDesviación estándar: {desviacion:F4}");
void MenuTecnicasConteo()
Console.WriteLine("\nTécnicas de conteo:\n1) Principio multiplicativo\n2) Principio aditivo\n3) Permutaciones\n4) Combinaciones\n5) Regresar al menú principal");
Console.Write("Seleccione opción: ");
string op = Console.ReadLine();
PrincipioMultiplicativo();
Console.WriteLine("Opción inválida.");
void PrincipioMultiplicativo()
Console.WriteLine("\nPrincipio multiplicativo:\nIngrese la cantidad de elecciones posibles en cada etapa.\nPara terminar, ingrese 'f'.");
List<int> elecciones = new List<int>();
Console.Write("Numero de opciones: ");
string entrada = Console.ReadLine();
if (entrada.ToLower() == "f") break;
if (int.TryParse(entrada, out int valor) && valor >= 0)
Console.WriteLine("Valor invalido.");
if (elecciones.Count == 0)
Console.WriteLine("No se ingresaron datos.");
foreach (int e in elecciones)
Console.WriteLine($"Resultado del principio multiplicativo: {resultado}");
archivo.WriteLine($"Principio multiplicativo ({string.Join(" x ", elecciones)}) = {resultado}");
Console.WriteLine("\nPrincipio aditivo:\nIngrese la cantidad de formas posibles de realizar diferentes tareas mutuamente excluyentes.\nPara terminar, ingrese 'f'.");
List<int> tareas = new List<int>();
Console.Write("Número de formas para una tarea: ");
string entrada = Console.ReadLine();
if (entrada.ToLower() == "f") break;
if (int.TryParse(entrada, out int valor) && valor >= 0)
Console.WriteLine("Valor inválido.");
Console.WriteLine("No se ingresaron datos.");
long resultado = tareas.Sum();
Console.WriteLine($"Resultado del principio aditivo: {resultado}");
archivo.WriteLine($"Principio aditivo ({string.Join(" + ", tareas)}) = {resultado}");
for (int i = 2; i <= n; i++) f *= i;
long Permutacion(int n, int r)
return Factorial(n) / Factorial(n - r);
long Combinacion(int n, int r)
return Factorial(n) / (Factorial(r) * Factorial(n - r));
Console.Write("Ingrese n (total elementos): ");
bool okN = int.TryParse(Console.ReadLine(), out int n);
Console.Write("Ingrese r (elementos a ordenar): ");
bool okR = int.TryParse(Console.ReadLine(), out int r);
if (okN && okR && n >= r && r >= 0)
long p = Permutacion(n, r);
Console.WriteLine($"Permutaciones P({n},{r}) = {p}");
archivo.WriteLine($"Permutaciones P({n},{r}) = {p}");
Console.WriteLine("Entrada inválida.");
Console.Write("Ingrese n (total elementos): ");
bool okN = int.TryParse(Console.ReadLine(), out int n);
Console.Write("Ingrese r (elementos a seleccionar): ");
bool okR = int.TryParse(Console.ReadLine(), out int r);
if (okN && okR && n >= r && r >= 0)
long c = Combinacion(n, r);
Console.WriteLine($"Combinaciones C({n},{r}) = {c}");
archivo.WriteLine($"Combinaciones C({n},{r}) = {c}");
Console.WriteLine("Entrada inválida.");
void MenuVariablesAleatorias()
Console.WriteLine("\nVariables aleatorias discretas:\nIngrese pares (valor probabilidad). Ingrese 'f' para terminar.");
List<(double valor, double prob)> variable = new List<(double, double)>();
Console.Write("Valor: ");
string v = Console.ReadLine();
if (v.ToLower() == "f") break;
Console.Write("Probabilidad: ");
string p = Console.ReadLine();
if (double.TryParse(v, out double val) && double.TryParse(p, out double prob) && prob >= 0 && prob <= 1)
variable.Add((val, prob));
Console.WriteLine("Entrada inválida.");
Console.WriteLine("No ingresó valores.");
double sumaProbs = variable.Sum(x => x.prob);
if (Math.Abs(sumaProbs - 1) > 0.01)
Console.WriteLine($"Suma de probabilidades = {sumaProbs:F4} (debe ser 1). Ajuste las probabilidades.");
archivo.WriteLine("\nVariable aleatoria discreta:\nValor\tProbabilidad");
foreach (var vp in variable)
archivo.WriteLine($"{vp.valor}\t{vp.prob}");
double esperanza = variable.Sum(x => x.valor * x.prob);
double varianza = variable.Sum(x => Math.Pow(x.valor - esperanza, 2) * x.prob);
archivo.WriteLine($"Esperanza: {esperanza:F4}\nVarianza: {varianza:F4}\nDesviación estándar: {Math.Sqrt(varianza):F4}\nEsperanza: {esperanza:F4}\nVarianza: {varianza:F4}\nDesviación estándar: {Math.Sqrt(varianza):F4}");
Console.WriteLine($"\nResultados de las operaciones en {archivoNombre}:");
if (!File.Exists(archivoNombre))
Console.WriteLine("Archivo no encontrado.");
string[] lineas = File.ReadAllLines(archivoNombre);
string[] claves = new string[]
"Media", "Mediana", "Moda", "Varianza", "Desviación estándar",
"Permutaciones", "Combinaciones", "Regla multiplicativa",
"Regla aditiva", "Esperanza", "P(", "C(", "Total combinaciones",
"Variable aleatoria discreta"
bool hayResultados = false;
foreach (string linea in lineas)
if (string.IsNullOrWhiteSpace(linea)) continue;
foreach (string clave in claves)
if (linea.IndexOf(clave, StringComparison.OrdinalIgnoreCase) >= 0)
Console.WriteLine(linea.Trim());
Console.WriteLine("No hay resultados de operaciones en el historial.");
Console.WriteLine("\nContenido completo del archivo:");
foreach (string l in lineas)