/*
 * $Id$
 */

package edu.jas.util;


import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;


/**
 * Cartesian product of infinite components with iterator. Works also for finite
 * iterables.
 * @author Heinz Kredel
 */
public class CartesianProductInfinite implements Iterable> {


    /**
     * data structure.
     */
    public final List> comps;


    /**
     * CartesianProduct constructor.
     * @param comps components of the Cartesian product.
     */
    public CartesianProductInfinite(List> comps) {
        if (comps == null || comps.size() == 0) {
            throw new IllegalArgumentException("null components not allowed");
        }
        this.comps = comps;
    }


    /**
     * Get an iterator over subsets.
     * @return an iterator.
     */
    public Iterator> iterator() {
        if (comps.size() == 1) {
            return new CartesianOneProductInfiniteIterator(comps.get(0));
        }
        //         if ( comps.size() == 2 ) { // this part is not realy required
        //             return new CartesianTwoProductInfiniteIterator(comps.get(0),comps.get(1));
        //         }
        int n = comps.size();
        int k = n / 2 + n % 2; // ceiling
        Iterable> c0 = new CartesianProductInfinite(comps.subList(0, k));
        Iterable> c1 = new CartesianProductInfinite(comps.subList(k, n));
        return new CartesianTwoProductInfiniteIteratorList(c0, c1);
    }

}


/**
 * Cartesian product infinite iterator, one factor.
 * @author Heinz Kredel
 */
class CartesianOneProductInfiniteIterator implements Iterator> {


    /**
     * data structure.
     */
    final Iterator compit;


    /**
     * CartesianProduct iterator constructor.
     * @param comps components of the cartesian product.
     */
    public CartesianOneProductInfiniteIterator(Iterable comps) {
        if (comps == null) {
            throw new IllegalArgumentException("null comps not allowed");
        }
        compit = comps.iterator();
    }


    /**
     * Test for availability of a next tuple.
     * @return true if the iteration has more tuples, else false.
     */
    public synchronized boolean hasNext() {
        return compit.hasNext();
    }


    /**
     * Get next tuple.
     * @return next tuple.
     */
    public synchronized List next() {
        List res = new ArrayList(1);
        res.add(compit.next());
        return res;
    }


    /**
     * Remove a tuple if allowed.
     */
    public void remove() {
        throw new UnsupportedOperationException("cannnot remove tuples");
    }

}


/**
 * Cartesian product infinite iterator, two factors.
 * @author Heinz Kredel
 */
class CartesianTwoProductInfiniteIterator implements Iterator> {


    /**
     * data structure.
     */
    final Iterator compit0;


    final Iterator compit1;


    final List fincomps0;


    final List fincomps1;


    Iterator fincompit0;


    Iterator fincompit1;


    List current;


    boolean empty;


    long level;


    /**
     * CartesianProduct iterator constructor.
     * @param comps components of the Cartesian product.
     */
    public CartesianTwoProductInfiniteIterator(Iterable comps0, Iterable comps1) {
        if (comps0 == null || comps1 == null) {
            throw new IllegalArgumentException("null comps not allowed");
        }
        empty = false;
        level = 0;
        current = new ArrayList(2);

        compit0 = comps0.iterator();
        E e = compit0.next();
        current.add(e);
        fincomps0 = new ArrayList();
        fincomps0.add(e);
        fincompit0 = fincomps0.iterator();
        //E d = 
        fincompit0.next(); // remove current

        compit1 = comps1.iterator();
        e = compit1.next();
        current.add(e);
        fincomps1 = new ArrayList();
        fincomps1.add(e);
        fincompit1 = fincomps1.iterator();
        //@SuppressWarnings("unused")
        //d = 
        fincompit1.next(); // remove current
        //System.out.println("current   = " + current);
    }


    /**
     * Test for availability of a next tuple.
     * @return true if the iteration has more tuples, else false.
     */
    public synchronized boolean hasNext() {
        return !empty;
    }


    /**
     * Get next tuple.
     * @return next tuple.
     */
    public synchronized List next() {
        if (empty) {
            throw new NoSuchElementException("invalid call of next()");
        }
        List res = current; // new ArrayList(current); // copy
        if (fincompit0.hasNext() && fincompit1.hasNext()) {
            E e0 = fincompit0.next();
            E e1 = fincompit1.next();
            current = new ArrayList();
            current.add(e0);
            current.add(e1);
            return res;
        }
        level++;
        if (level % 2 == 1) {
            Collections.reverse(fincomps0);
        } else {
            Collections.reverse(fincomps1);
        }
        if (compit0.hasNext() && compit1.hasNext()) {
            fincomps0.add(compit0.next());
            fincomps1.add(compit1.next());
        } else {
            empty = true;
            return res;
        }
        if (level % 2 == 0) {
            Collections.reverse(fincomps0);
        } else {
            Collections.reverse(fincomps1);
        }
        //System.out.println("list(0) = " + fincomps0);
        //System.out.println("list(1) = " + fincomps1);
        fincompit0 = fincomps0.iterator();
        fincompit1 = fincomps1.iterator();
        E e0 = fincompit0.next();
        E e1 = fincompit1.next();
        current = new ArrayList();
        current.add(e0);
        current.add(e1);
        return res;
    }


    /**
     * Remove a tuple if allowed.
     */
    public void remove() {
        throw new UnsupportedOperationException("cannnot remove tuples");
    }

}


/**
 * Cartesian product infinite iterator, two factors list version.
 * @author Heinz Kredel
 */
class CartesianTwoProductInfiniteIteratorList implements Iterator> {


    /**
     * data structure.
     */
    final Iterator> compit0;


    final Iterator> compit1;


    final List> fincomps0;


    final List> fincomps1;


    Iterator> fincompit0;


    Iterator> fincompit1;


    List current;


    boolean empty;


    long level;


    /**
     * CartesianProduct iterator constructor.
     * @param comps components of the Cartesian product.
     */
    public CartesianTwoProductInfiniteIteratorList(Iterable> comps0, Iterable> comps1) {
        if (comps0 == null || comps1 == null) {
            throw new IllegalArgumentException("null comps not allowed");
        }
        current = new ArrayList();
        empty = false;
        level = 0;

        compit0 = comps0.iterator();
        List e = compit0.next();
        current.addAll(e);
        fincomps0 = new ArrayList>();
        fincomps0.add(e);
        fincompit0 = fincomps0.iterator();
        //List d = 
        fincompit0.next(); // remove current

        compit1 = comps1.iterator();
        e = compit1.next();
        current.addAll(e);
        fincomps1 = new ArrayList>();
        fincomps1.add(e);
        fincompit1 = fincomps1.iterator();
        //@SuppressWarnings("unused")
        //d = 
        fincompit1.next(); // remove current
        //System.out.println("current   = " + current);
    }


    /**
     * Test for availability of a next tuple.
     * @return true if the iteration has more tuples, else false.
     */
    public synchronized boolean hasNext() {
        return !empty;
    }


    /**
     * Get next tuple.
     * @return next tuple.
     */
    public synchronized List next() {
        if (empty) {
            throw new NoSuchElementException("invalid call of next()");
        }
        List res = current; // new ArrayList(current);
        if (fincompit0.hasNext() && fincompit1.hasNext()) {
            List e0 = fincompit0.next();
            List e1 = fincompit1.next();
            current = new ArrayList();
            current.addAll(e0);
            current.addAll(e1);
            return res;
        }
        level++;
        if (level % 2 == 1) {
            Collections.reverse(fincomps0);
        } else {
            Collections.reverse(fincomps1);
        }
        if (compit0.hasNext() && compit1.hasNext()) {
            fincomps0.add(compit0.next());
            fincomps1.add(compit1.next());
        } else {
            empty = true;
            return res;
        }
        if (level % 2 == 0) {
            Collections.reverse(fincomps0);
        } else {
            Collections.reverse(fincomps1);
        }
        //System.out.println("list(0) = " + fincomps0);
        //System.out.println("list(1) = " + fincomps1);
        fincompit0 = fincomps0.iterator();
        fincompit1 = fincomps1.iterator();
        List e0 = fincompit0.next();
        List e1 = fincompit1.next();
        current = new ArrayList();
        current.addAll(e0);
        current.addAll(e1);
        return res;
    }


    /**
     * Remove a tuple if allowed.
     */
    public void remove() {
        throw new UnsupportedOperationException("cannnot remove tuples");
    }

}

 

Ads help maintain this website.