All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.landawn.abacus.util.PermutationIterator Maven / Gradle / Ivy

Go to download

A general programming library in Java/Android. It's easy to learn and simple to use with concise and powerful APIs.

There is a newer version: 5.3.16
Show newest version
/*
 * Copyright (C) 2008 The Guava Authors
 *
 * Licensed 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
 *
 * http://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 com.landawn.abacus.util;

import java.util.Collection;
import java.util.Comparator;
import java.util.List;
import java.util.NoSuchElementException;

import com.landawn.abacus.util.stream.ObjIteratorEx;

/**
 * Copied from Google Guava.
 *
 * Provides static methods for working with {@code Collection} instances.
 *
 * @author Chris Povirk
 * @author Mike Bostock
 * @author Jared Levy
 * @since 2.0
 */
public final class PermutationIterator {

    private PermutationIterator() {
    }

    /**
     * Returns a {@link Collection} of all the permutations of the specified
     * {@link Collection}.
     *
     * 

Notes: This is an implementation of the Plain Changes algorithm * for permutations generation, described in Knuth's "The Art of Computer * Programming", Volume 4, Chapter 7, Section 7.2.1.2. * *

If the input list contains equal elements, some of the generated * permutations will be equal. * *

An empty collection has only one permutation, which is an empty list. * * @param * @param elements the original collection whose elements have to be permuted. * @return an immutable {@link Collection} containing all the different * permutations of the original collection. * @throws NullPointerException if the specified collection is null or has any * null elements. * @since 12.0 */ public static ObjIterator> of(final Collection elements) { return new ObjIteratorEx<>() { final T[] items = (T[]) elements.toArray(); final int[] c = Array.repeat(0, items.length); final int[] o = Array.repeat(1, items.length); int j = Integer.MAX_VALUE; int hasNext = items.length == 0 ? -1 : 1; // 0 = read; 1 = yes, -1 = done. @Override public boolean hasNext() { switch (hasNext) { case -1: return false; case 1: return true; default: computeNext(); } return hasNext == 1; } @Override public List next() { if (!hasNext()) { throw new NoSuchElementException(); } hasNext = 0; return N.asList(items); } private void computeNext() { j = items.length - 1; int s = 0; while (true) { int q = c[j] + o[j]; if (q < 0) { switchDirection(); continue; } if (q == j + 1) { if (j == 0) { break; } s++; switchDirection(); continue; } N.swap(items, j - c[j] + s, j - q + s); c[j] = q; break; } hasNext = j <= 0 ? -1 : 1; } private void switchDirection() { o[j] = -o[j]; j--; } }; } /** * Returns a {@link Collection} of all the permutations of the specified * {@link Iterable}. * *

Notes: This is an implementation of the algorithm for * Lexicographical Permutations Generation, described in Knuth's "The Art of * Computer Programming", Volume 4, Chapter 7, Section 7.2.1.2. The * iteration order follows the lexicographical order. This means that * the first permutation will be in ascending order, and the last will be in * descending order. * *

Duplicate elements are considered equal. For example, the list [1, 1] * will have only one permutation, instead of two. This is why the elements * have to implement {@link Comparable}. * *

An empty iterable has only one permutation, which is an empty list. * *

This method is equivalent to * {@code Collections2.orderedPermutations(list, Ordering.natural())}. * * @param * @param elements the original iterable whose elements have to be permuted. * @return an immutable {@link Collection} containing all the different * permutations of the original iterable. * @throws NullPointerException if the specified iterable is null or has any * null elements. * @since 12.0 */ public static > ObjIterator> ordered(Collection elements) { return ordered(elements, Comparators.naturalOrder()); } /** * Returns a {@link Collection} of all the permutations of the specified * {@link Iterable} using the specified {@link Comparator} for establishing * the lexicographical ordering. * *

Examples:

   {@code
     *
     *   for (List perm : orderedPermutations(asList("b", "c", "a"))) {
     *     println(perm);
     *   }
     *   // -> ["a", "b", "c"]
     *   // -> ["a", "c", "b"]
     *   // -> ["b", "a", "c"]
     *   // -> ["b", "c", "a"]
     *   // -> ["c", "a", "b"]
     *   // -> ["c", "b", "a"]
     *
     *   for (List perm : orderedPermutations(asList(1, 2, 2, 1))) {
     *     println(perm);
     *   }
     *   // -> [1, 1, 2, 2]
     *   // -> [1, 2, 1, 2]
     *   // -> [1, 2, 2, 1]
     *   // -> [2, 1, 1, 2]
     *   // -> [2, 1, 2, 1]
     *   // -> [2, 2, 1, 1]}
* *

Notes: This is an implementation of the algorithm for * Lexicographical Permutations Generation, described in Knuth's "The Art of * Computer Programming", Volume 4, Chapter 7, Section 7.2.1.2. The * iteration order follows the lexicographical order. This means that * the first permutation will be in ascending order, and the last will be in * descending order. * *

Elements that compare equal are considered equal and no new permutations * are created by swapping them. * *

An empty iterable has only one permutation, which is an empty list. * * @param * @param elements the original iterable whose elements have to be permuted. * @param comparator a comparator for the iterable's elements. * @return an immutable {@link Collection} containing all the different * permutations of the original iterable. * @throws NullPointerException If the specified iterable is null, has any * null elements, or if the specified comparator is null. * @since 12.0 */ public static ObjIterator> ordered(final Collection elements, final Comparator comparator) { return new ObjIteratorEx<>() { T[] next = (T[]) elements.toArray(); { N.sort(next, comparator); } int hasNext = next.length == 0 ? -1 : 1; // 0 = read; 1 = yes, -1 = done. @Override public boolean hasNext() { switch (hasNext) { case -1: return false; case 1: return true; default: computeNext(); } return hasNext == 1; } @Override public List next() { if (!hasNext()) { throw new NoSuchElementException(); } hasNext = 0; return N.asList(next); } private void computeNext() { if (next == null) { hasNext = -1; return; } int j = findNextJ(); if (j == -1) { next = null; hasNext = -1; return; } int l = findNextL(j); N.swap(next, j, l); int n = next.length; N.reverse(next, j + 1, n); hasNext = 1; } private int findNextJ() { for (int k = next.length - 2; k >= 0; k--) { if (comparator.compare(next[k], next[k + 1]) < 0) { return k; } } return -1; } private int findNextL(int j) { T ak = next[j]; for (int l = next.length - 1; l > j; l--) { if (comparator.compare(ak, next[l]) < 0) { return l; } } throw new AssertionError("this statement should be unreachable"); } }; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy