Anuncia aquí

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.

Esta entrada fue publicada en .NET, Quiz

11 Comentarios

  1. 1 Emilio Velardiez (24 de agosto de 2006, 05:21:00 pm) http://evelardiez.blogspot.com/

    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. 2 alex (24 de agosto de 2006, 05:40:43 pm) http://www.buayacorp.com

    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. 3 Emilio Velardiez (25 de agosto de 2006, 04:00:05 pm) http://evelardiez.blogspot.com/

    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. 4 alex (25 de agosto de 2006, 04:29:02 pm) http://www.buayacorp.com

    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. 5 Braulio (25 de agosto de 2006, 05:40:16 pm) http://www.buayacorp.com

    No entiendo nada :$

  6. 6 Emilio Velardiez (25 de agosto de 2006, 05:57:42 pm) http://evelardiez.blogspot.com/

    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...

  7. 7 melkorcete (25 de agosto de 2006, 07:27:33 pm) http://www.melkorcete.com

    Hazlo en PHP que tardas 3 minutos escasos xD

  8. 8 braulio (26 de agosto de 2006, 12:54:53 am) http://www.buayacorp.com

    Emilio, yo decía que no entiendo porque no sé ni un poquito de .NET :P , espero aprender pronto jejeje

  9. 9 alex (26 de agosto de 2006, 08:13:50 am) http://www.buayacorp.com

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

    Saludos

  10. 10 Italo (4 de abril de 2007, 05:37:16 pm) http://tecnologiainformaticageek.blogspot.com

    Parece demasiado complicado!

  11. 11 Jokin (29 de junio de 2007, 02:56:41 am)

    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.

Un Trackback

  1. [...] Actualización: Verifica la validez del código que se utilizará para el sorteo! [...]

Publicar un Comentario

Tu email nunca será publicado o compartido. Los campos requeridos están marcados con un *

*
*

Puedes usar estas etiquetas y atributos HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>