// Purpose.  Lots of client effort to manage a list of Processors

public class ChainBefore {

interface Image { String process(); }
static class IR implements Image { public String process() { return "IR"; } }
static class LS implements Image { public String process() { return "LS"; } }

static class Processor {
   private static java.util.Random rn = new java.util.Random();
   private static int nextId = 1;
   private int id = nextId++;
   public boolean handle( Image img ) {
      if (rn.nextInt(2) != 0) {
         System.out.println( "   Processor " + id + " is busy" );
         return false;
      }
      System.out.println( "Processor " + id + " - " + img.process() );
      return true;
}  }

public static void main( String[] args ) {
   Image[] input = { new IR(), new IR(), new LS(), new IR(), new LS(), new LS() };
   Processor[] procs = { new Processor(), new Processor(), new Processor() };
   for (int i=0, j; i < input.length; i++) {
      j = 0;
      while ( ! procs[j].handle( input[i] ))
         j = (j+1) % procs.length;
}  }}

// Processor 1 - IR
//    Processor 1 is busy
//    Processor 2 is busy
//    Processor 3 is busy
//    Processor 1 is busy
//    Processor 2 is busy
// Processor 3 - IR
//    Processor 1 is busy
// Processor 2 - LS
// Processor 1 - IR
// Processor 1 - LS
//    Processor 1 is busy
//    Processor 2 is busy
//    Processor 3 is busy
// Processor 1 - LS



// Purpose.  Chain of Responsibility design pattern

public class ChainAfter {

interface Image { String process(); }
static class IR implements Image { public String process() { return "IR"; } }
static class LS implements Image { public String process() { return "LS"; } }

static class Processor {
   private static java.util.Random rn = new java.util.Random();
   private static int nextId = 1;
   private int       id = nextId++;
   private Processor next;
   public void add( Processor nextP ) {
      if (next != null) next.add( nextP );
      else next = nextP;
   }
   public void wrapAround( Processor firstP ) {
      if (next != null) next.wrapAround( firstP );
      else next = firstP;
   }
   public void handle( Image img ) {
      if (rn.nextInt(2) != 0) {
         System.out.println( "   Processor " + id + " is busy" );
         next.handle( img );
      } else
         System.out.println( "Processor " + id + " - " + img.process() );
}  }

static public Processor setUp() {
   Processor root = new Processor();
   for (int i=0; i < 2; i++) root.add( new Processor() );
   root.wrapAround( root );
   return root;
}

public static void main( String[] args ) {
   Image[] input = { new IR(), new IR(), new LS(), new IR(), new LS(), new LS() };
   Processor chain = setUp();
   for (int i=0; i < input.length; i++)
      chain.handle( input[i] );
}}

//    Processor 1 is busy
//    Processor 2 is busy
//    Processor 3 is busy
// Processor 1 - IR
// Processor 1 - IR
//    Processor 1 is busy
// Processor 2 - LS
// Processor 1 - IR
//    Processor 1 is busy
//    Processor 2 is busy
// Processor 3 - LS
//    Processor 1 is busy
//    Processor 2 is busy
// Processor 3 - LS



// Purpose.  Chain of Responsibility design pattern

// 1. Put a "next" pointer in the base class
// 2. The "chain" method in the base class always delegates to the next object
// 3. If the derived classes cannot handle, they delegate to the base class

abstract class Component {
   private int       value;
   private Component next;             // 1. "next" pointer in the base class
   public Component( int v )              { this( v, null ); }
   public Component( int v, Component n ) { value = v;  next = n; }
   public void setNext( Component n )     { next = n; }
   public void traverse()                 { System.out.print( value + " " ); }
   // 2. The "chain" method in the base class always delegates to the next obj
   public void volunteer()                { next.volunteer(); }
}

class Primitive extends Component {
   public Primitive( int val )              { this( val, null ); }
   public Primitive( int val, Component n ) { super( val, n ); }
   public void volunteer() {
      super.traverse();
      // 3. Primitive objects don't handle volunteer requests 5 times out of 6
      if ((int)(Math.random()*100) % 6 != 0)
         // 3. Delegate to the base class
         super.volunteer();
}  }

class Composite extends Component {
   private Component[] children = new Component[9];
   private int         total    = 0;
   public Composite( int val )              { this( val, null ); }
   public Composite( int val, Component n ) { super( val, n ); }
   public void add( Component c )           { children[total++] = c; }
   public void traverse() {
      super.traverse();                              // 1
      for (int i=0; i < total; i++)                  // |
         children[i].traverse();                     // +-- 2
   }                                                 // |   |
   // 3. Composite objects never handle volunteer    // |   +-- 4 5
   public void volunteer() {            // requests  // |
      super.volunteer();                             // +-- 3
}  }                                                 // |   |
                                                     // |   +-- 6 7
public class ChainDemo {                             // |
   public static void main( String[] args ) {        // +-- 8 9
      Component seven = new Primitive( 7 );          //
      Component six   = new Primitive( 6, seven );   // tra: 1 2 4 5 3 6 7 8 9
      Composite three = new Composite( 3, six );     // 4
      three.add( six );  three.add( seven );         // 4 5 6 7
      Component five  = new Primitive( 5, three );   // 4 5 6 7 8 9
      Component four  = new Primitive( 4, five );    // 4 5 6 7 8
      Composite two   = new Composite( 2, four );    // 4 5 6 7
      two.add( four );   two.add( five );            // 4 5 6 7 8 9 4 5 6 7
      Composite one   = new Composite( 1, two );     // 4
      Component nine  = new Primitive( 9, one );     // 4 5 6 7 8 9 4 5 6 7 8
      Component eight = new Primitive( 8, nine );
      one.add( two );  one.add( three );  one.add( eight );  one.add( nine );
      seven.setNext( eight );
      System.out.print( "tra: " );  one.traverse();  System.out.println();
      for (int i=0; i < 8; i++) {
         one.volunteer();  System.out.println();
}  }  }



// Purpose.  Chain of Responsibility - links bid on job, chain assigns job
//
// 1. Base class maintains a "next" pointer
// 2. Each "link" does its part to handle (and/or pass on) the request
// 3. Client "launches and leaves" each request with the chain
// 4. The current bid and bidder are maintained in chain static members
// 5. The last link in the chain assigns the job to the low bidder

public class ChainBidDemo {

   static class Link {
      private int  id;
      private Link next;                       // 1. "next" pointer

      private static int  theBid = 999;        // 4. Current bid and bidder
      private static Link bidder;

      public Link( int num ) {
         id = num;
      }
      public void addLast( Link l ) {
         if (next != null) next.addLast( l );  // 2. Handle and/or pass on
         else              next = l;
      }
      public void bid() {
         int num = ((int)(Math.random() * 100)) % 9;
         System.out.print( id + "-" + num + "  " );
         if (num < theBid) {
            theBid = num;                      // 4. Current bid and bidder
            bidder = this;
         }
         if (next != null) next.bid();         // 2. Handle and/or pass on
         else              bidder.execute();   // 5. The last 1 assigns the job
      }
      public void execute() {
         System.out.println( id + " is executing" );
         theBid = 999;
   }  }

   static Link setUpChain() {
      Link first = new Link( 1 );
      for (int i=2; i < 7; i++)
         first.addLast( new Link( i ) );
      return first;
   }

   public static void main( String[] args ) {
      Link chain = setUpChain();
      for (int i=0; i < 10; i++)
         chain.bid();                          // 3. Client "launches & leaves"
}  }

// 1-1  2-6  3-0  4-3  5-1  6-0  3 is executing
// 1-1  2-1  3-1  4-0  5-7  6-1  4 is executing
// 1-0  2-1  3-0  4-6  5-1  6-2  1 is executing
// 1-6  2-3  3-8  4-0  5-1  6-4  4 is executing
// 1-8  2-0  3-5  4-8  5-4  6-2  2 is executing
// 1-1  2-0  3-8  4-8  5-7  6-0  2 is executing
// 1-1  2-1  3-3  4-1  5-6  6-2  1 is executing
// 1-2  2-1  3-0  4-3  5-6  6-8  3 is executing
// 1-7  2-5  3-4  4-2  5-1  6-2  5 is executing
// 1-3  2-6  3-7  4-7  5-6  6-0  6 is executing



// Purpose.  The number to be factored is passed through a chain of Factor-
// Elements until none of them is able to decompose the number any further.

import java.io.*;
public class ChainContrib {

static class Memento {
      private boolean[] done;
      private int       sp      = 0;
      private int[]     factors = new int[10];
   public Memento( int num )    { done = new boolean[num]; }
   public void add( int n )     { factors[sp++] = n; }
   public void setDone( int i ) { done[i] = true; }
   public boolean isDone() {
      for (int i=0; i < done.length; i++) if ( ! done[i]) return false;
      return true;
   }
   public String toString() {
      StringBuffer sb = new StringBuffer();
      for (int i=0; i < sp; i++) { sb.append( factors[i] );  sb.append( ' ' ); }
      sp = 0;
      for (int i=0; i < done.length; i++) done[i] = false;
      return sb.toString();
}  }

static class FactorElement {
      private        int           index, divisor;
      private        FactorElement next;
      private static Memento       mem;
   public FactorElement( int i, int d, FactorElement fe ) {
      index = i;   divisor = d;   next = fe;
   }
   public void   setNext( FactorElement fe ) { next = fe; }
   public String getResults()                { return mem.toString(); }
   public void getFactors( int[] num ) {
      if (num[0] % divisor == 0) {
         mem.add( divisor );
         num[0] = num[0] / divisor;
      } else
         mem.setDone( index );
      if ( ! mem.isDone())
         next.getFactors( num );
   }
   public static FactorElement setUp() {
      int[] divisors = { 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47 };
      int size = divisors.length;
      mem = new Memento( size );
      FactorElement last = new FactorElement( size-1, divisors[size-1], null );
      FactorElement current = last;
      for (int i=size-2; i > -1; i--)
         current = new FactorElement( i, divisors[i], current );
      last.setNext( current );
      return current;
}  }

public static void main( String[] args ) throws IOException {
   BufferedReader rdr = new BufferedReader( new InputStreamReader( System.in ));
   int[]          num = new int[1];
   String         str;
   FactorElement  root = FactorElement.setUp();
   while (true) {
      System.out.print( "Enter number: " );
      str = rdr.readLine();
      if (str.equals("0")) break;
      num[0] = Integer.parseInt( str );
      root.getFactors( num );
      System.out.println( "   " + root.getResults() + "- " + num[0] );
}  }}

// Enter number: 30
//    2 3 5 - 1
// Enter number: 31
//    31 - 1
// Enter number: 32
//    2 2 2 2 2 - 1
// Enter number: 127
//    - 127
// Enter number: 60
//    2 3 5 2 - 1
// Enter number: 180
//    2 3 5 2 3 - 1
// Enter number: 216
//    2 3 2 3 2 3 - 1
// Enter number: 2310
//    2 3 5 7 11 - 1
// Enter number: 4620
//    2 3 5 7 11 2 - 1
// Enter number: 13860
//    2 3 5 7 11 2 3 - 1
// Enter number: 0