Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Randomize values without exceeding a value?

I have some time thinking the following, I want to make a button to randomize whole values of some skills. The question is that I have 10 points to distribute between 4 skills, the idea is to have selected randoms numbers without exceeding 10 points.

I had thought in this

public int startPts = 10, usedPts = 0;
public int skill1 = 0, skill2 = 0, skill3 = 0, skill4 = 0;

public void ButtonRandom(){
   startPts = 10;
   usedPts = 0;

   skill1 = Random.Range( 1, 10 );
   usedPts += skill1;

   skill2 = Random.Range( 1, usedPts );
   usedPts += skill2;

   skill3 = Random.Range( 1, usedPts );
   usedPts += skill3;

   skill4 = startPts - usedPts;
   usedPts += skill4;

   startPts = startPts - usedPts;

 }

I also try with several conditionals and repetitive methods, but I do not get the desired result. Since sometimes it surpasses the 10 points, leaves points without using or only changes the first 2 values when I put the conditions.

Thank you, guys.

like image 456
Nelbi Alvarado Avatar asked Jun 10 '26 08:06

Nelbi Alvarado


1 Answers

If what you want is for every possible distribution to be equally likely, then none of the solutions presented so far work. The solutions presented so far pick 3, 3, 2, 2 much more often than 7, 1, 1, 1. Do you see why?

If your desired distribution is uniform over possibilities, this algorithm gives you that:

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    // Partition n into m summands
    static IEnumerable<IEnumerable<int>> Partitions(int n, int m)
    {
      // There is no partition of n into zero summands for any value of n other than zero.
      // Otherwise, give the partitions that begin with 0, 1, 2, ... n.
      if (m == 0) 
      {
        if (n == 0)
          yield return Enumerable.Empty<int>();
      }
      else 
      {
        for (int nn = 0; nn <= n; ++nn)
            foreach(var p in Partitions(n - nn, m - 1))
                yield return (new[] { nn }).Concat(p);
      }
    }

    public static void Main()
    {
        // Divide up six points into four buckets:
        var partitions = Partitions(6, 4).ToArray();
        // Now choose a random member of partitions, and 
        // add one to each element of that sequence. Now
        // you have ten points total, and every possibility is 
        // equally likely.

        // Let's visualize the partitions:
        foreach(var p in partitions)
            Console.WriteLine(string.Join(",", p));

    }
}
like image 121
Eric Lippert Avatar answered Jun 13 '26 09:06

Eric Lippert