1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.hipparchus.util;
18
19 import java.util.ArrayList;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.NoSuchElementException;
23
24
25
26
27
28
29
30
31
32
33 class PermutationsIterator<T> implements Iterator<List<T>> {
34
35
36 private final List<T> permuted;
37
38
39 private final int[] value;
40
41
42 private final int[] direction;
43
44
45 private boolean exhausted;
46
47
48
49
50 PermutationsIterator(final List<T> list) {
51
52 this.permuted = new ArrayList<>(list);
53
54 this.value = new int[list.size()];
55 this.direction = new int[list.size()];
56 for (int i = 0; i < value.length; ++i) {
57 value[i] = i;
58 direction[i] = i == 0 ? 0 : -1;
59 }
60
61 exhausted = false;
62
63 }
64
65
66 @Override
67 public boolean hasNext() {
68 return !exhausted;
69 }
70
71
72 @Override
73 public List<T> next() {
74
75 if (exhausted) {
76 throw new NoSuchElementException();
77 }
78
79
80 final List<T> current = new ArrayList<>(permuted);
81
82
83 int selectedIndex = -1;
84 int selectedValue = -1;
85 int selectedDirection = -1;
86 for (int i = 0; i < value.length; ++i) {
87 if (direction[i] != 0 && value[i] > selectedValue) {
88 selectedIndex = i;
89 selectedValue = value[i];
90 selectedDirection = direction[i];
91 }
92 }
93 if (selectedIndex < 0) {
94 exhausted = true;
95 } else {
96
97
98
99
100 final int selectedPeer = selectedIndex + selectedDirection;
101 final T tmp = permuted.get(selectedIndex);
102 permuted.set(selectedIndex, permuted.get(selectedPeer));
103 permuted.set(selectedPeer, tmp);
104 value[selectedIndex] = value[selectedPeer];
105 value[selectedPeer] = selectedValue;
106 direction[selectedIndex] = direction[selectedPeer];
107 if (selectedPeer == 0 || selectedPeer == permuted.size() - 1 ||
108 value[selectedPeer + selectedDirection] > selectedValue) {
109
110 direction[selectedPeer] = 0;
111 } else {
112
113 direction[selectedPeer] = selectedDirection;
114 }
115
116
117 for (int i = 0; i < selectedIndex; ++i) {
118 if (value[i] > selectedValue) {
119 direction[i] = +1;
120 }
121 }
122 for (int i = selectedIndex + 1; i < value.length; ++i) {
123 if (value[i] > selectedValue) {
124 direction[i] = -1;
125 }
126 }
127
128 }
129
130 return current;
131
132 }
133
134 }