Quiz: Números aleatorios en .NET

La siguiente porción de código será usado para determinar el ganador del sorteo del voucher para un exámen de certificación Microsoft

csharp:
using System;
using System.Collections.Generic;
using System.IO;

class Participante
{
    private string Nombre, Email;
    public Participante(string nombre, string email)
    {
        Nombre = nombre;
        Email = email;
    }
    public override string ToString()
    {
        return string.Format("Nombre: {0}\t\tEmail: {1}", Nombre, Email);
    }
}
class Program
{
    static void Main(string[] args)
    {
        StreamReader reader = null;
        try
        {
            reader = new StreamReader("sorteo.txt");
            List<Participante> participantes = new List<Participante>();
            string line;

            while ((line = reader.ReadLine()) != null)
            {
                participantes.Add(new Participante(line.Split(',')[0], line.Split(',')[1]));
                Console.WriteLine(participantes[participantes.Count - 1]);
            }
           
            int ganador = ObtenerGanador(participantes.Count);

            Console.WriteLine("\n\nEl ganador es: {0}", participantes[ganador]);
        }
        finally
        {
            if (reader != null)
                reader.Close();
        }
    }
    public static int ValorAleatorio()
    {
        int semilla = DateTime.Now.Millisecond;
        Random rnd = new Random(semilla);
       
        int maximo = rnd.Next(0, semilla) * semilla;
       
        return rnd.Next(0, maximo % int.MaxValue);
    }
    public static int ObtenerGanador(int numeroParticipantes)
    {
        int ganador = 0;
        for (int i = 0; i < numeroParticipantes; i++)
            ganador += ValorAleatorio();

        return ganador % numeroParticipantes;
    }
}

El archivo sorteo.txt, tiene la siguiente estructura:

code:
Nombre Apellidos,Email
Nombre Apellidos,Email
Nombre Apellidos,Email

Determinen si el código mostrado sirve o no para los propósitos antes mencionados, si observan algún comportamiento raro, comenten abajo indicando las correcciones del caso.

Pueden descargar el código en C# o VB, para compilarlo -como se habrán dado cuenta- necesitan el .NET Framework 2.0

Nota: El código se ejecutará en una máquina con procesador AMD Athlon 64 3200+ y 1GB RAM.

12 thoughts on “Quiz: Números aleatorios en .NET”

  1. Hola alex,

    Las pruebas las he llebado acabo en VB.NET y las modificaciónes realizadas han sido:

    1.- Importar el Nombre de Espacios Microsoft.VisualBasic para el uso de la constante vbCrLf:

    Imports Microsoft.VisualBasic

    2.- En caso de tener activada la opcion de restringir las conversiones de tipos de datos implícitas únicamente a conversiones de ampliación :

    Option Strict On

    a)Convertir el valor de retorno de la lectura de linea al tipo de dato String:

    line = Convert.ToString(reader.ReadLine)

    b)Declarar la cadena de separación "," al como tipo de dato Char para la funcion Split. Ademas espero que no te importe que haya declarado dicho parametro como una constante para prevenir posibles cambios en el criterio de separación:

    Const separador As Char = ","c
    participantes.Add(New Participante(line.Split(separador)(0), line.Split(separador)(1)))

    El resto del codigo me ha funcionado sin problemas.

    Saludos.

  2. Bien!, ya hice las correcciones (en cuanto al punto a, no es necesario hacer la conversión, ya que reader.ReadLine() devuelve un string).

    Todavía quedan pendientes algunas cositas :) (hint: observa el historial de resultados al ejecutar múltiples veces ese código)

    Saludos

  3. Hola Alex,

    A ver si tenemos mas suerte esta vez! jejejeje

    1.- Importar el espacio de nombres System.Threading

    Imports System.Threading

    2.- Añadir un Sleep a la función ValorAleatorio()

    Public Shared Function ValorAleatorio() As Integer
    Dim semilla As Integer = DateTime.Now.Millisecond
    Dim rnd As New Random(semilla)

    Thread.Sleep(1)
    Dim maximo As Integer = rnd.Next(0, semilla) * semilla

    Return rnd.Next(0, maximo Mod Integer.MaxValue)
    End Function

    PD: La clase Random genera números seudoaleatorios a partir de una semilla (a mi me gustaria llamarle serie, supongo que a sido una traducción literial de seed) generada en funcion del valor del tiempo. El bucle que sucesibamente llamaba a la función que contiene el Random se recorre de una manera tan rápida que no da tiempo a que la semilla (serie) cambie de valor). Supongo que por eso se nos da el dato de la pontencia del procesador del ordenador donde correra el código. El resultado era que el programa siempre te debolvia el mismo valor.

    Envio un vinculo a la página que me ha ayudado a resolver el problema:

    http://msdn2.microsoft.com/es-es/library/system.random.aspx

    Saludos.

  4. Hola,

    1.- jeje, las cosas a las que te "acostumbra" vb.net (en realidad el IDE para vb.net).

    2.- Muy bien, esa es la razón por la que el código iba a favorecer a alguien :-P, en realidad la función ValorAleatorio era más para distraer la atención que para otra cosa :).

    Saludos

  5. Braulio,

    No creas que yo tp lo tengo todo claro porque esta mu confusa la cosa esta de los seudoaleatorios. El mayor problema supongo que no sabemos el algoritmo que calcula el Random.Next(). Porque necesitara el tiempo como varialbe? Con lo facil que es usar en VB el Randomize y el Rnd() que ni clase ni miembros compartidos ni complicaciones...

  6. Melkorcete, tienes razón, pero también con c# podría hacerlo en ese tiempo :D, sólo que lo "compliqué" intencionalmente.

    Saludos

  7. voy un poco tarde, pero para si alguien lo lee a partir de ahora, cuando se utiliza la funcion random hay que tener mucho cuidado con el seed que se utiliza, utilizando la parte de milisegundos de la fecha, estas restringiendo el numero de secuencias a 1000, de forma que si tuvieses mas que esos participantes habria algunos a los que nunca podria tocarle. Lo ideal en este caso es inicializar si seed, o con el metodo getTicks, que cada vez te da un numero diferente y no repetido.

Comments are closed.