import java.util.*;

public class WhichChars {
    private Hashtable used = new Hashtable();

    public WhichChars(String str) {
	for (int i = 0; i < str.length(); i++) {
	    char ch = str.charAt(i);
	    Integer highByte =
		new Integer((ch >> 8) & 0xF);	// look up high byte in table
	    BitSet bits = (BitSet)used.get(highByte);
	    if (bits == null)
		bits = new BitSet();
	    bits.set(ch & 0xF);		// set bit for low byte of char
	    used.put(highByte, bits);
	}
    }

    public String toString() {
	StringBuffer desc = new StringBuffer(2 + used.size());

	desc.append('[');
	Enumeration enum = used.keys();
	while (enum.hasMoreElements()) {
	    Integer highByte = (Integer)enum.nextElement();
	    BitSet bits = (BitSet)used.get(highByte);
	    int size = bits.size();
	    for (int i = 0; i < size; i++) {
		if (bits.get(i))
		    desc.append((char)((highByte.intValue() << 8) | i));
	    }
	}
	desc.append(']');

	return desc.toString();
    }

    public Enumeration characters() {
	return new EnumerateWhichChars(used);
    }
}

class EnumerateWhichChars implements Enumeration {
    private Hashtable    table;
    private Enumeration  enum;		// enumeration for given hashtable
    private Integer      highByte;	// high byte for current set
    private BitSet       bits;		// bit set of low bytes for high byte
    private int          pos = 0;	// next position to test in bit set
    private int          setSize = 0;	// size of bit set

    EnumerateWhichChars(Hashtable table) {
	this.table = table;
	enum = table.keys();
    }

    public boolean hasMoreElements() {
	while (true) {
	    while (pos < setSize && !bits.get(pos))
		pos++;
	    if (pos < setSize)
		return true;
	    if (!enum.hasMoreElements())
		return false;
	    highByte = (Integer)enum.nextElement();
	    bits = (BitSet)table.get(highByte);
	    setSize = bits.size();
	    pos = 0;
	}
    }

    public Object nextElement() {
	if (hasMoreElements())
	    return new Character((char)((highByte.intValue() << 8) | pos));
	else
	    return null;
    }
}
