RosenNumberPartitionIterator.java
- /* Copyright 2011 Axel Kramer
- * Licensed to the Hipparchus project under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The Hipparchus project licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.hipparchus.util;
- import java.util.Iterator;
- import java.util.NoSuchElementException;
- import org.hipparchus.exception.LocalizedCoreFormats;
- import org.hipparchus.exception.MathIllegalArgumentException;
- /**
- * An iterator that generates all partitions of <code>n</code> elements, into <code>k</code> parts
- * containing the number of elements in each part, based on Rosen's algorithm.
- * <p>
- * This is a copy of the class (with slight edits) with the same name from the
- * <a href="https://github.com/axkr/symja_android_library">Symja Library</a>.
- * The original file was published under the terms of the GPLV3 license,
- * but the Hipparchus project was <a
- * href="https://github.com/Hipparchus-Math/hipparchus/issues/197#issuecomment-1193259547">explicitly allowed</a>
- * to include it relicensed to Apache V2.
- * </p>
- * <p>
- * See Kenneth H. Rosen, Discrete Mathematics and Its Applications, 2nd edition (NY: McGraw-Hill,
- * 1991), pp. 284-286
- * </p>
- */
- public class RosenNumberPartitionIterator implements Iterator<int[]> {
- /** Number of elements. */
- private final int n;
- /** Subset/sample size. */
- private final int k;
- /** Work array. */
- private int[] a;
- /** Count of unique combinations. */
- private long count;
- /** Simple constructor.
- * @param n the number of elements
- * @param k divided into k parts
- */
- public RosenNumberPartitionIterator(final int n, final int k) {
- this.n = n - 1;
- this.k = k - 1;
- if (k > n || k < 1) {
- throw new MathIllegalArgumentException(LocalizedCoreFormats.OUT_OF_RANGE_SIMPLE, k, 1, n);
- }
- reset();
- }
- /**
- * {@inheritDoc}
- *
- * @see java.util.Iterator#hasNext()
- */
- @Override
- public final boolean hasNext() {
- return count > 0;
- }
- /**
- * {@inheritDoc}
- *
- * @see java.util.Iterator#next()
- */
- @Override
- public final int[] next() {
- if (count == 0) {
- throw new NoSuchElementException();
- }
- // rosenNext start
- if (a == null) {
- this.a = new int[k];
- for (int i = 0; i < k; ++i) {
- this.a[i] = i;
- }
- } else {
- int i = k - 1;
- while (a[i] == n - k + i) {
- i--;
- }
- final int t = ++a[i] - i++;
- int j = i;
- while (j < k) {
- a[j] = t + j++;
- }
- }
- --count;
- // rosenNext end
- final int kPlus1 = k + 1;
- final int[] temp = new int[kPlus1];
- for (int i = 0; i < kPlus1; i++) {
- if (i == 0) {
- temp[i] = a[i] + 1;
- } else {
- if (i == k) {
- temp[i] = n - a[i - 1];
- } else {
- temp[i] = a[i] - a[i - 1];
- }
- }
- }
- return temp;
- }
- /** Reset this iterator to the start condition.
- */
- public void reset() {
- count = 1;
- for (int i = 0; i < k; ++i) {
- count = count * (n - i) / (i + 1);
- }
- a = null;
- }
- }