/*
 * $Id$
 */

package edu.jas.util;


import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;


/**
 * K-Subset with iterator.
 * @author Heinz Kredel
 */
public class KsubSet implements Iterable> {


    /**
     * data structure.
     */
    public final List set; // Iterable also ok


    public final int k;


    /**
     * KsubSet constructor.
     * @param set generating set.
     * @param k size of subsets.
     */
    public KsubSet(List set, int k) {
        if (set == null) {
            throw new IllegalArgumentException("null set not allowed");
        }
        if (k < 0 || k > set.size()) {
            throw new IllegalArgumentException("k out of range");
        }
        this.set = set;
        this.k = k;
    }


    /**
     * Get an iterator over subsets.
     * @return an iterator.
     */
    public Iterator> iterator() {
        if (k == 0) {
            return new ZeroSubSetIterator(set);
        }
        if (k == 1) {
            return new OneSubSetIterator(set);
        }
        return new KsubSetIterator(set, k);
    }

}


/**
 * Power set iterator.
 * @author Heinz Kredel
 */
class KsubSetIterator implements Iterator> {


    /**
     * data structure.
     */
    public final List set;


    public final int k;


    final List rest;


    private E current;


    private Iterator> recIter;


    private final Iterator iter;


    /**
     * KsubSetIterator constructor.
     * @param set generating set.
     * @param k subset size.
     */
    public KsubSetIterator(List set, int k) {
        if (set == null || set.size() == 0) {
            throw new IllegalArgumentException("null or empty set not allowed");
        }
        if (k < 2 || k > set.size()) {
            throw new IllegalArgumentException("k out of range");
        }
        this.set = set;
        this.k = k;
        iter = this.set.iterator();
        current = iter.next();
        //System.out.println("current = " + current);
        rest = new LinkedList(this.set);
        rest.remove(0);
        //System.out.println("rest = " + rest);
        if (k == 2) {
            recIter = new OneSubSetIterator(rest);
        } else {
            recIter = new KsubSetIterator(rest, k - 1);
        }
    }


    /**
     * Test for availability of a next subset.
     * @return true if the iteration has more subsets, else false.
     */
    public boolean hasNext() {
        return recIter.hasNext() || (iter.hasNext() && rest.size() >= k);
    }


    /**
     * Get next subset.
     * @return next subset.
     */
    public List next() {
        if (recIter.hasNext()) {
            List next = new LinkedList(recIter.next());
            next.add(0, current);
            return next;
        }
        if (iter.hasNext()) {
            current = iter.next();
            //System.out.println("current = " + current);
            rest.remove(0);
            //System.out.println("rest = " + rest);
            if (rest.size() < k - 1) {
                throw new NoSuchElementException("invalid call of next()");
            }
            if (k == 2) {
                recIter = new OneSubSetIterator(rest);
            } else {
                recIter = new KsubSetIterator(rest, k - 1);
            }
            return this.next(); // retry
        }
        throw new NoSuchElementException("invalid call of next()");
    }


    /**
     * Remove the last subset returned from underlying set if allowed.
     */
    public void remove() {
        throw new UnsupportedOperationException("cannnot remove subsets");
    }

}


/**
 * One-subset iterator.
 * @author Heinz Kredel
 */
class OneSubSetIterator implements Iterator> {


    /**
     * data structure.
     */
    public final List set;


    private Iterator iter;


    /**
     * OneSubSetIterator constructor.
     * @param set generating set.
     */
    public OneSubSetIterator(List set) {
        this.set = set;
        if (set == null || set.size() == 0) {
            iter = null;
            return;
        }
        iter = this.set.iterator();
    }


    /**
     * Test for availability of a next subset.
     * @return true if the iteration has more subsets, else false.
     */
    public boolean hasNext() {
        if (iter == null) {
            return false;
        }
        return iter.hasNext();
    }


    /**
     * Get next subset.
     * @return next subset.
     */
    public List next() {
        List next = new LinkedList();
        next.add(iter.next());
        return next;
    }


    /**
     * Remove the last subset returned from underlying set if allowed.
     */
    public void remove() {
        throw new UnsupportedOperationException("cannnot remove subsets");
    }

}


/**
 * Zero-subset iterator.
 * @author Heinz Kredel
 */
class ZeroSubSetIterator implements Iterator> {


    /**
     * data structure.
     */
    private boolean hasNext;


    /**
     * ZeroSubSetIterator constructor.
     * @param set generating set (ignored).
     */
    public ZeroSubSetIterator(List set) {
        hasNext = true;
    }


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


    /**
     * Get next subset.
     * @return next subset.
     */
    public List next() {
        List next = new LinkedList();
        hasNext = false;
        return next;
    }


    /**
     * Remove the last subset returned from underlying set if allowed.
     */
    public void remove() {
        throw new UnsupportedOperationException("cannnot remove subsets");
    }

}

 

Ads help maintain this website.