总数为16的int数组的排列

时间:2014-04-16 03:37:23

标签: java arrays algorithm loops max

我有一个方法会根据值返回一个double。数组中的每个int都在1到6之间,表示连续的掷骰子。

阵列可以是16个大的插槽或小到4个,并且顺序很重要。我不知道如何在java中编写代码来查看总计至少为16的每个排列。在线查找没有任何帮助。

我可怜的代码在下面

public double findMax() {
    int[] dice = new int[gameBoard.length];
    for(int x : dice) x = 1;
    double max = playGame(dice);
    /* 
    int pos = 0;
    for(int i = 0; i < dice.length; i++) {
        double test = playGame(dice);
        if(test > max) test = max;
    */

    //This is where I need help, to use the int[] dice for all combinations
    //playGame(dice) yields a double
}

3 个答案:

答案 0 :(得分:0)

有不同的方法可以做到这一点,但递归对我来说似乎是最好的(比如寻路算法)。看起来这应该是4到16个骰子的排列,总共16或更大(如果数组的长度为16,每个组合可能会产生16或更大的值,所以我不知道是什么目的检查那个长度的排列会产生。)

我可以使用ArrayLists或使用字符串来实现解决方案。我不想在递归函数中使用常规数组,因为它们依赖于固定大小。请务必添加import java.util.ArrayList;

无论如何,这是我使用ArrayLists的代码版本。 (注意,我还没有测试过这段代码)

public ArrayList<ArrayList<int>> findPermutations( int size ) {

    // To allow the function to work with sizes less than 1
    if ( size < 1 )
        return new ArrayList<ArrayList<int>>();

    ArrayList<ArrayList<int>> permutations = new ArrayList<ArrayList<int>>();

    ArrayList<ArrayList<int>> l1 = findPermutations( new ArrayList<int>(), size, 1 );
    l1.addAll( findPermutations( new ArrayList<int>(), size, 2 ) );
    l1.addAll( findPermutations( new ArrayList<int>(), size, 3 ) );
    l1.addAll( findPermutations( new ArrayList<int>(), size, 4 ) );
    l1.addAll( findPermutations( new ArrayList<int>(), size, 5 ) );
    l1.addAll( findPermutations( new ArrayList<int>(), size, 6 ) );


    for( ArrayList<int> a : l1 ) {
        if ( computeSum( a ) >= 16 ) {
            permutations.add( a );
        }
    }

    return permutations;

}

public ArrayList<ArrayList<int>> findPermutations( ArrayList<int> record, int size, int value ) {


    record.add( value );

    if ( record.size() >= size ) {
        ArrayList<ArrayList<int>> bc = new ArrayList<ArrayList<int>>();
        bc.add( record );
        return bc;
    }

    ArrayList<ArrayList<int>> permutations = findPermutations( record.clone(), size, 1 );
    permutations.addAll( findPermutations( record.clone(), size, 2 ) );
    permutations.addAll( findPermutations( record.clone(), size, 3 ) );
    permutations.addAll( findPermutations( record.clone(), size, 4 ) );
    permutations.addAll( findPermutations( record.clone(), size, 5 ) );
    permutations.addAll( findPermutations( record.clone(), size, 6 ) );

    // For variable size array checking
    if ( record.size() >= 4 ) {
        permutations.add( record );
    }


    return permutations;
}


public int computeSum( ArrayList<int> list ) {

    int total = 0;
    for( int x : list ) {
        total += x;
    }

    return total;

}

当你调用这个函数findPermutations( int size )时,你传递大小(数组长度,基本上是游戏板长度),它将生成所有骰子组合(特定顺序),总共至少16.由于这会返回一个ArrayList,如果要将其转换为double数组,可以使用ArrayList类的toArray()函数。

ArrayList<ArrayList<int>> permutations = findPermutations( 16 );
ArrayList<int>[] a = ( ArrayList<int>[] ) permutations.toArray();

这将为您提供一个ArrayList

数组

要将其转换为数组数组,可以使用循环。

int[][] finalVersion = new int[permutations.size()][16];
for( int i = 0; i < permutations.size(); i++ ) {
    finalVersion[i] = ( int[] ) a[i].toArray();
}

希望将它转换回数组数组。

同样,我还没有在代码中测试过这个,所以要小心bug。我现在将对此进行测试,并在不使用ArrayLists的情况下添加另一种执行此计算的方法。

编辑:我稍微改变了一下代码,以便允许 4和大小之间的所有排列(你可以在16中传递)。

答案 1 :(得分:0)

这很简单。初始化一个足够大的数组。递归地填充数组的元素,直到达到16(存储数组)或过冲(丢弃)。每次将数组添加到结果列表时,不要忘记对数组进行深层复制,否则将继续覆盖相同的数组。在代码中:

void createPermutations(int[] prefix, int index, int sum, List<Integer[]> results) {
    if (sum == 16) {
        results.add(createNewIntegerArray(prefix, index));
    } else if (sum < 16) {
        for (int i = 1; i <= 6; i++) {
            prefix[index] = i;
            createPermutations(prefix, index+1, sum+i, results);            
        }
    }
}

Integer[] createNewIntegerArray(int[] array, int length) {
    Integer[] result = new Integer[length];
    for (int i = 0; i < length; i++) {
        result[i] = array[i];
    }
    return result;
}

您可以将其称为:

createPermutations(new int[16], 0, 0, new ArrayList<Integer[]>());

编辑:如果我误解了您的问题,而您并不关心“超出”目标值(16),则应将==更改为>=

答案 2 :(得分:0)

你可以递归地解决它:

Input: list of size n

Solve(n) = { Sum(n,16) } + Solve(n-1)

with: Solve(4) = { Sum(4,16) }

Sum(n,16) = { find n numbers that sum up to 16 }

然后我们有:

Min(n) = 4

Max(n) = 16

Di = Input-List[i]

Di = 1 or 2 or 3 or 4 or 5 or 6

Sum(n,16) = { D1, D2, .. Dn } where D1 + D2 + .. + Dn = 16

要解决Sum(n,16),您可以尝试此算法(写为 Java 代码):

PairList<ArrayList<Byte>,Integer> sum (int n, int sum, ArrayList<Byte> list)
{
    if (list.size() == 1)
        return new Pair<ArrayList<Byte>,Integer>(list, (int)list.get(0));

    PairList<ArrayList<Byte>,Integer> result
                  = new Pair<ArrayList<Byte>,Integer> ();

    for (int i=0; i<n; i++)
    {
        ArrayList<Byte> t = new ArrayList<Byte>(list);
        t.remove(i);
        PairList<ArrayList<Byte>,Integer> r = sum(n-1, sum, t);

        for (ArrayList<Byte> l : r.getFirstList())
            if (r.getSecond(l)+list.get(i) <= sum)
            {
                l.append(list.get(i));
                r.set(l, r.getSecond(l)+list.get(i));
                result.append(r);
            }
    }

    return result;
}

然后Solve(n,16)使用Sum(n,16)

Map<Byte, PairList<ArrayList<Byte>,Integer>>
            solve (int min_n, int max_n, int sum, ArrayList<Byte> list)
{
    Map<Byte, PairList<ArrayList<Byte>,Integer>> solution = null;
    solution = new Map<Byte, Pair<ArrayList<Byte>,Integer>> ();

    for (int i = min_n, i <= max_n; i++)
        solution.put(i, sum(i,sum,list));

   for (int i = min_n, i <= max_n; i++)
   {
       for (int j = 0; j < solution.get(i).count(); j++)
       {
           // remove all pairs that didn't sum up to total sum

           if (solution.get(i).getSecond(j) != sum)
               solution.get(i).removePair(j);
       }
   }

    return solution;
}

注意:上面的代码是伪代码