/* Copyright 2009 Stefan Ram. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ interface Value< Type > { Type value(); } interface Advanceable { /* Advance to the next state. The initial state is the state before the first call to this. @result false means that the advance attempt failed */ boolean advance(); } interface Resetable { /* Reset to the initial state. The object will be in the initial state after construction. This operation is intended to reset it to the initial state after it might have left the initial state. */ void reset(); } interface ResetableAdvanceableValue< Range > extends Value, Advanceable, Resetable { } class Digit implements ResetableAdvanceableValue { final T[] value; int index; @java.lang.Override public T value() { return this.value[ index ]; } public Digit( final T[] value ) { this.value = value; } @java.lang.Override public boolean advance() { ++this.index; if( this.index == this.value.length )return false; return true; } @java.lang.Override public void reset() { this.index = 0; } @java.lang.Override public java.lang.String toString() { return java.lang.String.valueOf( this.value[ index ]); }} class Numeral implements ResetableAdvanceableValue < ResetableAdvanceableValue[] > { final ResetableAdvanceableValue[] value; public Numeral ( final ResetableAdvanceableValue[] value ) { this.value = value; this.reset(); } @java.lang.Override public void reset() { for( int i = 0; i < this.value.length; ++i ) this.value[ i ].reset(); } @java.lang.Override public boolean advance() { return this.advance( 0 ); } @java.lang.Override public ResetableAdvanceableValue[] value() { @java.lang.SuppressWarnings( "unchecked" ) final ResetableAdvanceableValue[] copy = new ResetableAdvanceableValue[ this.value.length ]; java.lang.System.arraycopy( this.value, 0, copy, 0, this.value.length ); return copy; } public ResetableAdvanceableValue[] peek() { return this.value; } public ResetableAdvanceableValue peek( final int i ) { return this.value[ i ]; } public boolean advance( final int pos ) { if( pos >= this.value.length ) return false; else if( this.value[ pos ].advance() ) return true; else { this.value[ pos ].reset(); return this.advance( pos + 1 ); }} @java.lang.Override public java.lang.String toString() { final java.lang.StringBuilder text = new java.lang.StringBuilder(); text.append( "[" ); for( int k = this.value.length - 1; k >= 0; --k ) { text.append( java.lang.String.valueOf( this.value[ k ])); if( k > 0 )text.append( ", " ); } text.append( "]" ); return text.toString(); }} public class Count { public static void main( final java.lang.String[] args ) { { final Digit digit = new Digit ( new java.lang.Character[]{ 'a', 'A', 'x', 'X' }); final Digit digit1 = new Digit ( new java.lang.Character[]{ 'b', 'B', 'y', 'Y' }); final Digit digit2 = new Digit ( new java.lang.Character[]{ 'c', 'C', 'z', 'Z' }); final Numeral numeral = new Numeral ( new ResetableAdvanceableValue[]{ digit2, digit1, digit }); int i = 0; do { java.lang.System.out.printf( "%2d:%s, ", i++, numeral ); } while( numeral.advance() ); }}}