import java.util.*;
import java.io.*;
import element;

//******************************************************
// CLASS: state
//******************************************************
// This class handles the state and sub states of the 
// dice rolling 
//******************************************************

class state {
	static int MAX_DIE = 6;
	int score[];
	String name;

	public state() 
		{
			score = new int [0];
			name = "";
		}// of CTOR

	 public Object clone() 
		{
			return new state(score);
		}// of clone 

	public boolean equals(Object other) 
		{
			//System.out.println("name-"+name+",othername-"+((state)other).name);
			return ( name.equals( ((state)other).name ) );
		}// of equal
		
	public state(boolean num[]) 
		{
			score = new int[num.length];
			name = "";
			for ( int i=0; i<num.length; i++ ) 
				{
					score[i] =  (num[i]) ? 1 : 0;
					name +=score[i] ;
				}
		}// of boolean CTOR

	public state(int num[]) 
		{
			int temp_score[] = {0,0,0,0,0,0};
			int num_of_scores =0;
			// sort array to dice values
			for ( int i=0; i<num.length; i++ ) 
				if ( ( num[i] <= MAX_DIE ) && ( num[i] > 0 ) ) 
					{ 
						int index = num[i]-1;
						temp_score[index]++;
						num_of_scores++;
						//System.out.println("die-"+num[i]+",score-"+temp_score[index]);

					}		
			// create name & array
			name = "";
			int count =0;	
			score = new int[num_of_scores];
			for ( int i=0; i<MAX_DIE; i++ )
				for(int j=0; j<temp_score[i]; j++) {
					name += (i+1);
					score[count] = (i+1);
					count++;
					//System.out.println("die-"+i+", num-"+j+", count-"+count);
				}
		}// of int array CTOR
		
	public String name() 
		{
			return name;
		}// of name
		
	public Vector substates() 
		{
			// create all substates as states
			//System.out.println("substate-"+name);
			Vector substate = new Vector(score.length*5);
			int first_score[] = new int[1];
			first_score[0] = score[0]; 
			state first = new state(first_score);
			if (score.length> 1)
				{
					int others_score[] = new int[score.length-1];
					for (int i=1; i<score.length; i++ ) 
						{
							others_score[i-1] = score[i]; 
						}
					state others = new state(others_score);
					Vector others_state = others.substates();
					Enumeration enum = others_state.elements() ;
					while ( enum.hasMoreElements() ) 
						{
							state new_state = (state)first.clone();
							//System.out.print("first_state-"+new_state.name());
						  state orig_state =(state)enum.nextElement();
						  //System.out.print(" orig_state-"+orig_state.name());
			   			new_state.merge(orig_state);
			   			//System.out.print(" new_state-"+new_state.name()+"\n");
							substate.add(orig_state);
							if (!others_state.contains(new_state))
								substate.add(new_state);
						}
				}
				if (!substate.contains(first))
					substate.add(first);
				substate.trimToSize();
				return substate;						
		}// of substates
		
	boolean equal(state other)
		{
			return ( name == other.name); 
		}
		
	void merge(state other)
		{
			int new_score[] = new int[score.length+other.score.length];
			String new_name = "";
			int i=0,j=0,k=0;
			while ( (i<score.length) || (j<other.score.length) ) {
				if (i>= score.length) {
					new_score[k] = other.score[j];
					new_name+= other.score[j];
					j++;
				}
				else if (j>= other.score.length) {
					new_score[k] = score[i];
					new_name+= score[i];
					i++;
				}
				else if ( score[i] < other.score[j] ) {
					new_score[k] = score[i];
					new_name+= score[i];
					i++;
				}
				else	{
					new_score[k] = other.score[j];
					new_name+= other.score[j];
					j++;
				}
				k++;
			}
			score = new_score;
			name = new_name;
		}
		
	public void updateAtIndex(int index,int value) 
		{
			if ( index < score.length )
				score[index] = value;
		}
		
	public int countByValue(int value) 
		// count number of the same as vallue
		{
			int count = 0;
			for (int i=0;i<score.length;i++)
				{
					if (score[i] == value)
						count++;
				}
			return count;	
		}// of countByValue
		
	public int countTheSame(int[] value) 
		// count maximum number of any value
		{
			int max_the_same = 1;
			int max_value=0; 
			for (int i=0;i<=MAX_DIE;i++) 
				{
					int the_same_on_X = countByValue(i);
					if ( max_the_same < the_same_on_X) 
						{
							max_the_same = the_same_on_X;
							max_value = i;
						}
				}
				value[0] = max_value;
				return max_the_same;
		}//of countTheSame
		
	public int numOfDie() 
		{
			return score.length;
		}// of numOfDie

	public void print()
		{
			System.out.print("state");
			for (int i=0;i<score.length;i++)
				{
					System.out.print("-"+score[i]);
				}
				System.out.println();
		}//of print
}