Spanish Generar números aleatorios que sumen una cifra concreta

Discussion in 'Spanish Forum' started by ivavilagu, Jun 29, 2015.

  1. ivavilagu

    ivavilagu Member Licensed User

    Hola,

    necesito crear una función a la que se le pasa dos valores:
    • Número de cifras aleatorias
    • Cantidad total que han de sumar dichas cifras
    Es decir, si por ejemplo paso (5,75) me ha de devolver 5 números aleatorios comprendidos entre 1 y 75 que sumen 75.

    Ninguno de los números aleatorios ha de ser cero ni negativo.

    Saludos
     
  2. JordiCP

    JordiCP Well-Known Member Licensed User

    De hecho, este problema es más de matemáticas que de programación.

    Al fijar la suma, los resutados entre sí ya no son independientes, sino que están ligados de alguna manera (probabilidad condicionada)
    Cada uno debe ser como mínimo =1, por lo tanto, ninguno de ellos debe superar 71
    (A tener en cuenta: la funcion rnd(a,b) devuelve un numero entre a y b-1)

    Una aproximación NO uniforme, que serviría por ejemplo en un caso como el siguiente: tenemos 75 bolas en una caja, viene una primera persona y saca un numero definido entre 1 y 71, luego una segunda, saca un numero aleatorio entre uno y las que queden menos 3, etc....

    num_1=rnd(1,76-4)
    num_2=rnd(1,76-3-num_1)
    num_3=rnd(1,76-2-(num_1+num_2))
    num_4=rnd(1,76-1-(num_1+num_2+num_3))
    num_5=rnd(1,76-(num_1+num_2+num_3+num_4))

    En general
    Code:
    Sub Lista_Aleatorios(cuantos As Int, maximo As Int) As Int()

      
    If cuantos>maximo Then Return Null
      
    Dim numeros(cuantos) As Int
      
    Dim k As Int
      
    Dim parcial_acumulado As Int=0
      
    For k=1 To cuantos
        numeros(k-
    1)=Rnd(1,maximo+1-(cuantos-k)-parcial_acumulado)
        parcial_acumulado = parcial_acumulado + numeros(k-
    1)
      
    Next
      
    Return numeros
    End Sub

    Sin embargo, si quieres distribuciones realmente independientes (que cada conjunto de 5 numeros cuya suma sea 75 tenga la misma probabilidad que otro conjunto), la aproximación dada aquí es muy buena:
    Por ejemplo, si tenemos: suma=75 y num_valores=5
    Crea una lista
    Genera 4 ( = num_valores-1) numeros aleatorios entre 1 y 74 ( = suma-1) --> lo generaremos mediante rnd(1,75) , ya que rnd(a,b) genera numeros entre a y b-1
    Si no está en la lista, lo añadimos
    Si ya lo está, generamos otro hasta que no esté en la lista.
    Ordena la lista de menor a mayor.
    Nuestros numeros serán:
    numero(0) = lista(0)
    numero(1) = lista(1)-lista(0)
    numero(2) = lista(2)-lista(1)
    numero(3) = lista(3)-lista(2)
    numero(4) = 75 - lista(3)

    Ya que estamos, añado el código
    Code:
    Sub Lista_Aleatorios2(cuantos As Int, maximo As Int) As Int()

      
    If cuantos>maximo Then Return Null
      
    Dim l_dist As List
      l_dist.Initialize
      
    Dim k As Int =1
      
    Dim Num As Int
      
    Do While k<cuantos
          Num = 
    Rnd(1,maximo)
        
    If l_dist.IndexOf(Num)=-1 Then  'Si no existe, lo añadimos a la lista
            l_dist.Add(Num)
            k=k+
    1
        
    End If
      
    Loop
      l_dist.Add(maximo)    
    'per al bucle que ve
      l_dist.Sort(True)
      
    Dim myNumbers(cuantos) As Int
      myNumbers(
    0)=l_dist.Get(0)
      
    For k=1 To cuantos-1
        myNumbers(k)=l_dist.Get(k)-l_dist.Get(k-
    1)
      
    Next

      
    Return myNumbers

    End Sub
     
    cimperia likes this.
  3. ivavilagu

    ivavilagu Member Licensed User

    Joder, menuda respuesta. Es un placer leer réplicas tan extensas y detalladas ;)

    Estoy realizando pruebas y funciona a la perfección excepto que si aleatoriamente se genera un número elevado y próximo a la suma, el resto de números pendientes quedan MUY condicionados a la baja.

    Saludos y muchas gracias!!!
     
    JordiCP likes this.
  4. JordiCP

    JordiCP Well-Known Member Licensed User

    Jajaj, reconozco que me animé un poquito con el tema :D

    Con la primera opción es mucho más probable que te salgan grupos tipo {28,31,7,4,5},{45,23,2,4,1},....,está más sesgado.

    Con la segunda también puede suceder pero la distribución es más uniforme. Yo trabajaría con ésta.
     
Loading...