source: src/main/java/agents/anac/y2019/harddealer/math3/util/IntegerSequence.java

Last change on this file was 204, checked in by Katsuhide Fujita, 5 years ago

Fixed errors of ANAC2019 agents

  • Property svn:executable set to *
File size: 12.2 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17package agents.anac.y2019.harddealer.math3.util;
18
19import java.util.Iterator;
20import agents.anac.y2019.harddealer.math3.exception.MaxCountExceededException;
21import agents.anac.y2019.harddealer.math3.exception.NullArgumentException;
22import agents.anac.y2019.harddealer.math3.exception.MathUnsupportedOperationException;
23import agents.anac.y2019.harddealer.math3.exception.NotStrictlyPositiveException;
24import agents.anac.y2019.harddealer.math3.exception.ZeroException;
25
26/**
27 * Provides a sequence of integers.
28 *
29 * @since 3.6
30 */
31public class IntegerSequence {
32 /**
33 * Utility class contains only static methods.
34 */
35 private IntegerSequence() {}
36
37 /**
38 * Creates a sequence {@code [start .. end]}.
39 * It calls {@link #range(int,int,int) range(start, end, 1)}.
40 *
41 * @param start First value of the range.
42 * @param end Last value of the range.
43 * @return a range.
44 */
45 public static Range range(int start,
46 int end) {
47 return range(start, end, 1);
48 }
49
50 /**
51 * Creates a sequence \( a_i, i < 0 <= n \)
52 * where \( a_i = start + i * step \)
53 * and \( n \) is such that \( a_n <= max \) and \( a_{n+1} > max \).
54 *
55 * @param start First value of the range.
56 * @param max Last value of the range that satisfies the above
57 * construction rule.
58 * @param step Increment.
59 * @return a range.
60 */
61 public static Range range(final int start,
62 final int max,
63 final int step) {
64 return new Range(start, max, step);
65 }
66
67 /**
68 * Generates a sequence of integers.
69 */
70 public static class Range implements Iterable<Integer> {
71 /** Number of integers contained in this range. */
72 private final int size;
73 /** First value. */
74 private final int start;
75 /** Final value. */
76 private final int max;
77 /** Increment. */
78 private final int step;
79
80 /**
81 * Creates a sequence \( a_i, i < 0 <= n \)
82 * where \( a_i = start + i * step \)
83 * and \( n \) is such that \( a_n <= max \) and \( a_{n+1} > max \).
84 *
85 * @param start First value of the range.
86 * @param max Last value of the range that satisfies the above
87 * construction rule.
88 * @param step Increment.
89 */
90 public Range(int start,
91 int max,
92 int step) {
93 this.start = start;
94 this.max = max;
95 this.step = step;
96
97 final int s = (max - start) / step + 1;
98 this.size = s < 0 ? 0 : s;
99 }
100
101 /**
102 * Gets the number of elements contained in the range.
103 *
104 * @return the size of the range.
105 */
106 public int size() {
107 return size;
108 }
109
110 /** {@inheritDoc} */
111 public Iterator<Integer> iterator() {
112 return Incrementor.create()
113 .withStart(start)
114 .withMaximalCount(max + (step > 0 ? 1 : -1))
115 .withIncrement(step);
116 }
117 }
118
119 /**
120 * Utility that increments a counter until a maximum is reached, at
121 * which point, the instance will by default throw a
122 * {@link MaxCountExceededException}.
123 * However, the user is able to override this behaviour by defining a
124 * custom {@link MaxCountExceededCallback callback}, in order to e.g.
125 * select which exception must be thrown.
126 */
127 public static class Incrementor implements Iterator<Integer> {
128 /** Default callback. */
129 private static final MaxCountExceededCallback CALLBACK
130 = new MaxCountExceededCallback() {
131 /** {@inheritDoc} */
132 public void trigger(int max) throws MaxCountExceededException {
133 throw new MaxCountExceededException(max);
134 }
135 };
136
137 /** Initial value the counter. */
138 private final int init;
139 /** Upper limit for the counter. */
140 private final int maximalCount;
141 /** Increment. */
142 private final int increment;
143 /** Function called at counter exhaustion. */
144 private final MaxCountExceededCallback maxCountCallback;
145 /** Current count. */
146 private int count = 0;
147
148 /**
149 * Defines a method to be called at counter exhaustion.
150 * The {@link #trigger(int) trigger} method should usually throw an exception.
151 */
152 public interface MaxCountExceededCallback {
153 /**
154 * Function called when the maximal count has been reached.
155 *
156 * @param maximalCount Maximal count.
157 * @throws MaxCountExceededException at counter exhaustion
158 */
159 void trigger(int maximalCount) throws MaxCountExceededException;
160 }
161
162 /**
163 * Creates an incrementor.
164 * The counter will be exhausted either when {@code max} is reached
165 * or when {@code nTimes} increments have been performed.
166 *
167 * @param start Initial value.
168 * @param max Maximal count.
169 * @param step Increment.
170 * @param cb Function to be called when the maximal count has been reached.
171 * @throws NullArgumentException if {@code cb} is {@code null}.
172 */
173 private Incrementor(int start,
174 int max,
175 int step,
176 MaxCountExceededCallback cb)
177 throws NullArgumentException {
178 if (cb == null) {
179 throw new NullArgumentException();
180 }
181 this.init = start;
182 this.maximalCount = max;
183 this.increment = step;
184 this.maxCountCallback = cb;
185 this.count = start;
186 }
187
188 /**
189 * Factory method that creates a default instance.
190 * The initial and maximal values are set to 0.
191 * For the new instance to be useful, the maximal count must be set
192 * by calling {@link #withMaximalCount(int) withMaximalCount}.
193 *
194 * @return an new instance.
195 */
196 public static Incrementor create() {
197 return new Incrementor(0, 0, 1, CALLBACK);
198 }
199
200 /**
201 * Creates a new instance with a given initial value.
202 * The counter is reset to the initial value.
203 *
204 * @param start Initial value of the counter.
205 * @return a new instance.
206 */
207 public Incrementor withStart(int start) {
208 return new Incrementor(start,
209 this.maximalCount,
210 this.increment,
211 this.maxCountCallback);
212 }
213
214 /**
215 * Creates a new instance with a given maximal count.
216 * The counter is reset to the initial value.
217 *
218 * @param max Maximal count.
219 * @return a new instance.
220 */
221 public Incrementor withMaximalCount(int max) {
222 return new Incrementor(this.init,
223 max,
224 this.increment,
225 this.maxCountCallback);
226 }
227
228 /**
229 * Creates a new instance with a given increment.
230 * The counter is reset to the initial value.
231 *
232 * @param step Increment.
233 * @return a new instance.
234 */
235 public Incrementor withIncrement(int step) {
236 if (step == 0) {
237 throw new ZeroException();
238 }
239 return new Incrementor(this.init,
240 this.maximalCount,
241 step,
242 this.maxCountCallback);
243 }
244
245 /**
246 * Creates a new instance with a given callback.
247 * The counter is reset to the initial value.
248 *
249 * @param cb Callback to be called at counter exhaustion.
250 * @return a new instance.
251 */
252 public Incrementor withCallback(MaxCountExceededCallback cb) {
253 return new Incrementor(this.init,
254 this.maximalCount,
255 this.increment,
256 cb);
257 }
258
259 /**
260 * Gets the upper limit of the counter.
261 *
262 * @return the counter upper limit.
263 */
264 public int getMaximalCount() {
265 return maximalCount;
266 }
267
268 /**
269 * Gets the current count.
270 *
271 * @return the current count.
272 */
273 public int getCount() {
274 return count;
275 }
276
277 /**
278 * Checks whether incrementing the counter {@code nTimes} is allowed.
279 *
280 * @return {@code false} if calling {@link #increment()}
281 * will trigger a {@code MaxCountExceededException},
282 * {@code true} otherwise.
283 */
284 public boolean canIncrement() {
285 return canIncrement(1);
286 }
287
288 /**
289 * Checks whether incrementing the counter several times is allowed.
290 *
291 * @param nTimes Number of increments.
292 * @return {@code false} if calling {@link #increment(int)
293 * increment(nTimes)} would call the {@link MaxCountExceededCallback callback}
294 * {@code true} otherwise.
295 */
296 public boolean canIncrement(int nTimes) {
297 final int finalCount = count + nTimes * increment;
298 return increment < 0 ?
299 finalCount > maximalCount :
300 finalCount < maximalCount;
301 }
302
303 /**
304 * Performs multiple increments.
305 *
306 * @param nTimes Number of increments.
307 * @throws MaxCountExceededException at counter exhaustion.
308 * @throws NotStrictlyPositiveException if {@code nTimes <= 0}.
309 *
310 * @see #increment()
311 */
312 public void increment(int nTimes) throws MaxCountExceededException {
313 if (nTimes <= 0) {
314 throw new NotStrictlyPositiveException(nTimes);
315 }
316
317 if (!canIncrement(0)) {
318 maxCountCallback.trigger(maximalCount);
319 }
320 count += nTimes * increment;
321 }
322
323 /**
324 * Adds the increment value to the current iteration count.
325 * At counter exhaustion, this method will call the
326 * {@link MaxCountExceededCallback#trigger(int) trigger} method of the
327 * callback object passed to the
328 * {@link #withCallback(MaxCountExceededCallback)} method.
329 * If not explicitly set, a default callback is used that will throw
330 * a {@code MaxCountExceededException}.
331 *
332 * @throws MaxCountExceededException at counter exhaustion, unless a
333 * custom {@link MaxCountExceededCallback callback} has been set.
334 *
335 * @see #increment(int)
336 */
337 public void increment() throws MaxCountExceededException {
338 increment(1);
339 }
340
341 /** {@inheritDoc} */
342 public boolean hasNext() {
343 return canIncrement(0);
344 }
345
346 /** {@inheritDoc} */
347 public Integer next() {
348 final int value = count;
349 increment();
350 return value;
351 }
352
353 /**
354 * Not applicable.
355 *
356 * @throws MathUnsupportedOperationException
357 */
358 public void remove() {
359 throw new MathUnsupportedOperationException();
360 }
361 }
362}
Note: See TracBrowser for help on using the repository browser.