指定された数まで加算可能なすべての合計を含むint配列のint配列を作成します。

私はJavaで全く新しいです。私はAndroidのゲームを書いており、与えられた数に足したすべての可能な和(2を含むか8より大きい組み合わせを除く)を含むint配列の配列を生成する必要があります。

例えば:   ganeratePatterns(5)は配列を返す必要があります

 [patternNumber][summandNumber] = value

 [0][0] = 5

 [1][0] = 1
 [1][1] = 1
 [1][2] = 1
 [1][3] = 1
 [1][4] = 1

 [2][0] = 3
 [2][1] = 1
 [2][2] = 1

 [3][0] = 4
 [3][1] = 1

I already try to do this like there Getting all possible sums that add up to a given number but it's very difficult to me to make it like this http://introcs.cs.princeton.edu/java/23recursion/Partition.java.html

ソリューション

int n = 10; 
int dimension = 0; 
//First we need to count number of posible combinations to create a 2dimensionarray
for(List sumt : new SumIterator(n)) {
  if(!sumt.contains(2) && sumt.size() < 9) {
    dimension++;
  }
}

int[][] combinationPattern = new int[dimension][];
int foo = 0;
for(List sum : new SumIterator(n)) {
  if(!sum.contains(2) && sum.size() < 9) {
      System.out.println(sum);
      combinationPattern[foo] = toIntArray(sum);
      foo++;
  }
}

それは100%正確ではなく、とてもかわいいですが、私のゲームには十分です

I have used SumIterator class from here SumIterator.class I have to changed this code for(int j = n-1; j > n/2; j--) { to this for(int j = n-1; j >= n/2; j--) { because old version doesn't return all combinations (like [5,5] for 10)

そして私はtoIntArray関数を使用しました。私はStackOverflowでhareを創設しましたが、リンクを忘れていますので、ここではソースです:

public static int[] toIntArray(final Collection data){
    int[] result;
   //null result for null input
    if(data == null){
        result = null;
   //empty array for empty collection
    } else if(data.isEmpty()){
        result = new int[0];
    } else{
        final Collection effective;
       //if data contains null make defensive copy
       //and remove null values
        if(data.contains(null)){
            effective = new ArrayList(data);
            while(effective.remove(null)){}
       //otherwise use original collection
        }else{
            effective = data;
        }
        result = new int[effective.size()];
        int offset = 0;
       //store values
        for(final Integer i : effective){
            result[offset++] = i.intValue();
        }
    }
    return result;
}
1
申し訳ありませんが、実装する必要があるアルゴリズムを理解しようとすると、頭が爆発しました。あなたはその定義を言い換えることができますか?編集:心配しないで、最終的に私の頭の周りを得た。
追加された 著者 bezmax,
もし私が尋ねることができれば、それは難しいと思いますか?印刷の代わりに配列を更新する必要があるようです。
追加された 著者 DPM,
私はJavaの再帰で新しいので、私のためのロケット科学です:)と私は配列を初期化する(int [?] [] = value)、すべての可能なパターンから数を数えることはできません
追加された 著者 akuzmitski,

1 答え

これは最も美しいコードではありませんが、参照したコードを修正したものです。それはまたかなり速いです。 (スタックを使用して)再帰から離れ、文字列から整数への変換を完全に回避することで、高速化できます。私は戻ってそれらの変更を編集するかもしれません。かなり古くなったラップトップで実行すると、 50 (すべての204226)のパーティションが5秒以内に印刷されました。

このコードで partition(N)を終了すると、 partitions N のパーティションが保持されます。

  1. まず、スペース区切り形式で合計の文字列表現のArrayListを作成します(例: "1 1 1" )。

  2. 次に、すべての結果を保持できるintの2次元配列を作成します。

  3. ArrayList内の各Stringを、単一の数字だけを含むStringの配列に分割します。
  4. 各文字列に対して、各数値を解析して整数の配列を作成します。
  5. このint配列が2次元配列のintに追加されます。

ご質問がある場合はお知らせください。

    import java.util.ArrayList;
    public class Partition
    {
        static ArrayList list = new ArrayList();
        static int[][] partitions;

        public static void partition(int n)
        {
            partition(n, n, "");
            partitions = new int[list.size()][0];
            for (int i = 0; i < list.size(); i++)
            {
                String s = list.get(i);
                String[] stringAsArray = s.trim().split(" ");
                int[] intArray = new int[stringAsArray.length];
                for (int j = 0; j < stringAsArray.length; j++)
                {
                    intArray[j] = Integer.parseInt(stringAsArray[j]);
                }
                partitions[i] = intArray;
            }
        }

        public static void partition(int n, int max, String prefix)
        {
            if(prefix.trim().split(" ").length > 8 || (prefix + " ").contains(" 2 "))
            {
                return;
            }
            if (n == 0)
            {
                list.add(prefix);
                return;
            }

            for (int i = Math.min(max, n); i >= 1; i--)
            {
                partition(n - i, i, prefix + " " + i);
            }
        }

        public static void main(String[] args)
        {
            int N = 50;
            partition(N);

            /**
             * Demonstrates that the above code works as intended.
             */
            for (int i = 0; i < partitions.length; i++)
            {
                int[] currentArray = partitions[i];
                for (int j = 0; j < currentArray.length; j++)
                {
                    System.out.print(currentArray[j] + " ");
                }
                System.out.println();
            }
        }
    }
1
追加された
おっとっと! 100%正確ではありません。私は数2を含む組み合わせ、または8以上の数の組み合わせを除外しませんでした!私はこれを編集します。
追加された 著者 Zéychin,
私はエラーを修正しました。実行時間のほとんどがI/Oにあったため、多く高速に実行されます。
追加された 著者 Zéychin,
Zeychinありがとう!私の解決策を投稿するために私の質問を編集していたとき、あなた自身の解決策を投稿しています:)。あなたのコードはきれいで、かなり速く動作し、100%正しいです。そして、それは私のコードよりも美しいです...
追加された 著者 akuzmitski,