当前位置: 首页 > 知识库问答 >
问题:

Java 偏置三角形数组中的随机数

公羊宗清
2023-03-14

这个问题是Java-Math.random()的扩展:选择13×13三角形数组的元素。我随机选择两个数字(包括 0-12),我希望这些值相等。

但现在,由于这是一个乘法游戏,我希望有一种方法来偏置结果,以便某些组合出现得更频繁(比如,如果玩家在12x8时表现得更差,我希望它出现得更频密)。最终,我想偏向于91种组合中的任何一种,但一旦我把这一点写下来,那就不难了。

我的想法:添加一些int n到三角形数和Random.nextInt(91n)以将结果偏向组合。

private int[] triLessThan(int x, int[] bias) { // I'm thinking a 91 element array, 0 for no bias, positive for bias towards
    int i = 0;
    int last = 0;
    while (true) {
                    int sum = 0;
                    for (int a = 0; a < i * (i + 2)/2; a++){
                        sum += bias[a]
                    }
        int triangle = i * (i + 1) / 2;
        if (triangle + sum > x){
            int[] toReturn = {last,i};
            return toReturn;
        }
        last = triangle;
        i++;
    }
}

在随机数滚动时:

int sum = sumOfArray(bias); // bias is the array;
int roll = random.nextInt(91 + sum);
int[] triNum = triLessThan(roll);
int num1 = triNum[1];
int num2 = roll - triNum[0]; //now split into parts and make bias[] add chances to one number.

其中SumOfArray只是找到总和(这个公式很简单)。这行得通吗?

编辑:使用弗洛里斯的想法:

在随机数字滚动中:

int[] bias = {1,1,1,...,1,1,1} // 91 elements
int roll = random.nextInt(sumOfBias());
int num1 = roll;
int num2 = 0;
while (roll > 0){
    roll -= bias[num2];
    num2++;
}
num1 = (int) (Math.sqrt(8 * num2 + 1) - 1)/2;
num2 -= num1 * (num1 + 1) / 2;

共有1个答案

何升
2023-03-14

你已经知道如何将一个0到91之间的数字转换成一个卷(从上一个问题的答案)。我建议您创建一个由N个元素组成的数组,其中N

这将创建一个数组,其中采样频率将表示问题被错误解决的次数,但如果问题在下一次被问及时被正确解决,则不会再次降低采样频率。

另一种更好的解决方案,一个更接近您的(但不同的)的解决方案,创建一个包含 91 个频率的数组 - 每个频率最初设置为 1 - 并跟踪总和(最初为 91)。但是现在,当您选择一个随机数(介于 0 和总和之间)时,您将遍历数组,直到累积总和大于您的随机数 - bin 的数字是您选择的滚动,并使用之前派生的公式进行转换。如果答案是错误的,则增加箱并更新总和;如果正确,则递减总和,但从不递减到小于 1 的值,然后更新总和。重复。

这应该能准确地告诉你你在问什么:给定一个91个数字(“bin”)的数组,随机选择一个bin,使该bin的概率与其中的值成比例。返回bin的索引(可以使用以前的方法将其转换为数字的组合)。调用函数时,bin(频率)数组作为第一个参数,累积和作为第二个参数。您可以查找前n个元素的累积和首先超过按频率之和缩放的随机数的位置:

private int chooseBin(float[] freq, float fsum) {
// given an array of frequencies (probabilities) freq
// and the sum of this array, fsum
// choose a random number between 0 and 90
// such that if this function is called many times
// the frequency with which each value is observed converges
// on the frequencies in freq
    float x, cs=0; // x stores random value, cs is cumulative sum
    int ii=-1;     // variable that increments until random value is found

    x = Math.rand();

    while(cs < x*fsum && ii<90) { 
    // increment cumulative sum until it's bigger than fraction x of sum
        ii++;
        cs += freq[ii];
    }
return ii;
}

(注意——这是用matlab绘制的,所以X从1到91,而不是从0到90)。

这是另一个想法(这并没有真正回答这个问题,但它可能更有趣):

你可以通过抽样而不是均匀分布来歪曲你选择一个特定问题的概率。例如,均匀抽样随机变量的平方将有利于较小的数字。这给了我们一个有趣的可能性:

首先,把你的91个数字随机排列

接下来,从非均匀分布中挑选一个数字(倾向于较小的数字)。由于这些数字是随机打乱的,事实上它们被选中的可能性是相等的。但现在这里有一个窍门:如果问题(由挑选的数字表示)被正确解决,你将问题数字移动到“堆栈的顶部”,在那里它最不可能被再次选择。如果玩家选错了,它会被移到堆栈的底部,在那里它最有可能被再次选中。随着时间的推移,困难的问题转移到堆栈的底部。

您可以使用

roll = (int)(91*(asin(Math.rand()*a)/asin(a)))

当您使a更接近1时,该函数倾向于支持较低的数字,而较高数字的概率几乎为零:

我相信以下代码部分可以实现我所描述的功能:

private int[] chooseProblem(float bias, int[] currentShuffle) { 
// if bias == 0, we choose from uniform distribution
// for 0 < bias <= 1, we choose from increasingly biased distribution
// for bias > 1, we choose from uniform distribution
// array currentShuffle contains the numbers 0..90, initially in shuffled order
// when a problem is solved correctly it is moved to the top of the pile
// when it is wrong, it is moved to the bottom.
// return value contains number1, number2, and the current position of the problem in the list
    int problem, problemIndex;

    if(bias < 0 || bias > 1) bias = 0;

    if(bias == 0) {
        problem = random.nextInt(91);
        problemIndex = problem;
    }
    else {
        float x = asin(Math.random()*bias)/asin(bias);
        problemIndex = Math.floor(91*x);
        problem = currentShuffle[problemIndex];
    }

    // now convert "problem number" into two numbers:
    int first, last;    
    first = (int)((Math.sqrt(8*problem + 1)-1)/2);
    last = problem - first * (first+1) / 2;

    // and return the result:
    return {first, last, problemIndex};
}


private void shuffleProblems(int[] currentShuffle, int upDown) {
// when upDown==0, return a randomly shuffled array
// when upDown < 0, (wrong answer) move element[-upDown] to zero
// when upDown > 0, (correct answer) move element[upDown] to last position
// note - if problem 0 is answered incorrectly, don't call this routine!

    int ii, temp, swap;

    if(upDown == 0) {

        // first an ordered list:
        for(ii=0;ii<91;ii++) {
            currentShuffle[ii]=ii;
        }

        // now shuffle it:
        for(ii=0;ii<91;ii++) {
            temp = currentShuffle[ii];
            swap = ii + random.nextInt(91-ii);
            currentShuffle[ii]=currentShuffle[swap];
            currentShuffle[swap]=temp;
        }
        return;
    }

    if(upDown < 0) {
        temp = currentShuffle[-upDown];
        for(ii = -upDown; ii>0; ii--) {
            currentShuffle[ii]=currentShuffle[ii-1];
        }
        currentShuffle[0] = temp;
    }
    else {
        temp = currentShuffle[upDown];
        for(ii = upDown; ii<90; ii++) { 
            currentShuffle[ii]=currentShuffle[ii+1];
        }
        currentShuffle[90] = temp;
    }
    return;
}


// main problem posing loop:

int[] currentShuffle = new int[91];
int[] newProblem;
int keepGoing = 1;

// initial shuffle:
shuffleProblems( currentShuffle, 0); // initial shuffle

while(keepGoing) {
    newProblem = chooseProblem(bias, currentShuffle);
    // pose the problem, get the answer
    if(wrong) {
        if(newProblem > 0) shuffleProblems( currentShuffle, -newProblem[2]);
    }
    else shuffleProblems( currentShuffle, newProblem[2]);
    // decide if you keep going...
}
 类似资料:
  • 问题内容: 我正在创建一个测验,每当我开始测验时,我都希望将问题打乱,以免每次出现时都不会以相同的顺序出现。 我在我的html代码中有这个: 这在我的控制器中 不幸的是,这根本没有用。希望有人可以帮助我吗? 问题答案: 谢谢 http://bost.ocks.org/mike/shuffle/ 使用此改组功能: 它的特殊之处在于,输入数组保持可绑定性,因为改组不会创建新的数组,而是 对同一引用 执

  • 嗨,伙计们,我有这个阵列,可以打印5x5 1 我想做的是随机地将这些1中的三(3)个设为0。实例 我该怎么做?提前感谢您!

  • 编辑:这个问题解决了。如果您想在另一个问题上提供帮助,请访问Java偏置三角形数组中的随机数。 我在做一个乘法游戏,所以我选了两个0到12之间的数字。如果我这样做: 正方形(0x0、1x1、2x2等)的拾取时间为一半(因为1x2与2x1相同)。如何使所有组合以相同的频率拾取?有91种可能的组合(n(n1)/2)。如果有帮助的话,这里有一个13乘13的三角形阵列: 我试着选择第一个数字,然后给第二个

  • 问题内容: 我想尝试一个直角三角形的星号。但是我只得到以下 输出:( 我不能在这里放置星号) 我想要的是这样的: 这是我编写的代码: 任何想法分享,我们将不胜感激。我是Java新手。谢谢。 问题答案: 您的代码从不打印任何空格,这应该是一个问题。 您可以使用以下简单方法: 逻辑很简单:您的字符串带有两个空格和三个at符号。输出的第一行必须是两个空格和一个at符号,因此这是字符串的前三个字符。第二行

  • 问题内容: 在Java中,如何生成随机数,但如何使该随机数偏向特定数字。例如,我想生成一个介于1到100之间的数字,但是我希望该数字偏向75。但是我仍然希望能够获得该范围内的其他数字,但是我希望获得数字的更多变化接近75,而不是仅仅获得整个范围内的随机数。谢谢 问题答案: 尝试http://download.oracle.com/javase/6/docs/api/java/util/Random

  • 问题内容: 当他每次运行程序时都不断获得相同的数字时,我试图向Java解释随机数生成器。我为同一件事创建了自己的简单版本,每次运行该程序时,我也得到了与他得到的确切数字相同的数字。 我究竟做错了什么? 100个数字中的最后五个数字是: 问题答案: 您已经为随机数生成器提供了恒定的值。它是确定性的,因此每次运行都会生成相同的值。 我不确定您为什么选择使用作为种子,但是种子值与生成的值范围无关(这是由