要素の重複有りの順列(Permutation)を Java で、いろんなオブジェクトに対して作成できるようにする。
import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * RepeatablePermutation */ public class RepeatablePermutation<T>{ private int r, u; private int[] c; private int[] p; private List<List<T>> result; private List<T> list; private RepeatablePermutation(List<T> list){ this.list = list; c = new int[list.size()]; p = new int[list.size()]; for(int i=0; i < c.length; i++) c[i] = i; } public static <T> RepeatablePermutation<T> of(List<T> list){ return new RepeatablePermutation<>(list); } public static <T> RepeatablePermutation<T> of(T[] ary){ return new RepeatablePermutation<>(Arrays.asList(ary)); } public List<List<T>> compute(int len){ if (len > list.size()) throw new IllegalArgumentException("list size over"); result = new ArrayList<>(); r = len; u = c[c.length-1] - len; for(int i=0; i <= c.length; i++) calc(0, i); return result; } private void calc(int i, int j){ p[i] = j; if (i == r - 1){ List<T> t = new ArrayList<>(); for(int k=0; k < r; k++){ if (p[k] < c.length) t.add(list.get(c[p[k]])); } if (t.size()==r) result.add(t); } if (i < r - 1){ int k=0; for(; k <= r;k++) calc(i+1, k); if (u > 0){ for(int n=0; n < u; n++) calc(i+1, c[k + n] ); } } } }
サンプル
文字列 "A", "B", "C”, "D" から、3個の順列(重複あり)
RepeatablePermutation<String> r = RepeatablePermutation.of(Arrays.asList("A", "B", "C", "D")); r.compute(3).stream() .map(e->e.stream().collect(Collectors.joining(""))) .forEach(System.out::println);
整数の場合
RepeatablePermutation<Integer> r = RepeatablePermutation.of(Arrays.asList(0, 1, 2, 3, 4)); r.compute(3).stream() .map(e->e.stream().map(i->i.toString()).collect(Collectors.joining(""))) .forEach(System.out::println);