import java.awt.*;
import java.awt.event.ItemListener;
import java.awt.event.ItemEvent;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.applet.Applet;

class GraphTriangle extends java.applet.Applet
{

        int modulo=2;
        int numbers=1;
        int filter=-1;

        int red = 255;
        int green = 255;
        int blue = 0;
        int color;
        int cm = 200;
        int wart_mod = 0;

        int max1 = 470;
        int x=(int)(max1 / 2);
        int max = 420;
        int y=2;

        /* table where we'll place next numbers */
        int [][] tab = new int [max+1][max+1];
		int [] f = new int [max+1];    
       
		public GraphTriangle( int mod, int nnumbers, int nfilter)
		{
				modulo = mod;
				numbers = nnumbers;
				filter = nfilter;

		}
		
		     
        /* main function which draws triangle */
        public void paint( Graphics g )
        {        

                drawTriangle( g, modulo, filter);
                
        }
               
		/* *** */
        public int power(int base, int exponent, int modulo) {
        	
        	int result = 1;
        	
        	if (base == 0 && exponent != 0) {
        		return 0;	
        	}
        	
       		base = base % modulo;
        	       		
        	for (int i=1; i<=exponent;i++) {
        		
        		if (result == result*base % modulo) { break; }
        		
        		result = result*base % modulo;
        		
        		if (result == 0) break;
        		
        	}
        		
        	return result;
        		
        }
        
 
        void drawTriangle( Graphics g, int mod, int filter)
        {
                
                /* description */
                Font ft = new Font ( "Tahoma", Font.PLAIN, 12 );
                Font ftb = new Font ( "Tahoma", Font.BOLD, 12 );
                
                g.setFont (ft);
                g.drawString ("Triangles for", 30, 20 );

                g.setFont (ftb);
                g.drawString ("Fractal Numbers", 15, 35 );
                
                g.drawLine(15,40,165,40);
        
                g.setFont (ft);
                g.drawString ("Scale of rest:", 15, 60 );
                g.drawString ("Filter - show only certain rest", 15, 110 );
                
                g.drawString ("0", 15, 90 );
                g.drawString (new Integer(mod-1).toString(), 140, 90 );
				
				int [] rr = new int[3];
				
                if (filter > modulo) {
                        max = 0;
                }
                
                if (mod > 6*cm) {
                        cm = 255;
                }
				
				/* Fibonacci numbers */
				f[0] = 0;
                f[1] = 1;
                for (int i=2;i<=max; i++) {
                        
                        f[i] = (f[i-1] + f[i-2]) % mod;

                }

				
				/* main assumptation */
                for (int i=0; i<=max; i++) {
                        tab[i][0] = 0;
                        
                        if (numbers == 4) {
                                tab[i][0] = 1;
                        }
                        if (i == 0) {
                                tab[0][0] = 1;
                        } else {
                                tab[0][i] = 0;
                        }
                        if (numbers == 11)
                        for (int j=0; j<=max; j++) {
                                tab[i][j] = 0;
                        }
                }
                
                if (numbers == 4) {
                        tab[0][0] = 1;
                        
                }
                
                 /* drawing the scale of rest */
                for (int i=0; i<130;i++) {
                
                        color = (int)(6*cm/130*i);
                        int a = (int)((i*mod)/130);
                        
                        color=(int)(((6*cm)/mod) * a);
                        
                        if (color <= cm) {
                                red=cm;
                                green=color;
                                blue=0;
                        }else if (color <= 2*cm) {
                                      red = cm - (color-cm);
                                       green = cm;
                                       blue = 0;
                        }else if (color <= 3*cm) {
                                       red = 0;
                                       green = cm;
                                       blue = (color - 2*cm);
                        }else if (color <= 4*cm) {
                                       red = 0;
                                       green = cm - (color - 3*cm);
                                       blue = cm;
                        }else if (color <= 5*cm) {
                                       red = (color - 4*cm);
                                       green = 0;
                                       blue = cm;
                        }else if (color <= 6*cm) {
                                       red = cm;
                                       green = 0;
                                       blue = cm - (color - 5*cm);
                        }
                           
                        switch (a) {
                                case 0: red=230;green=230;blue=230;
                                        break;
                        }
                                
                        g.setColor(new Color(red,green,blue));
                        g.drawLine(15+i,65,15+i,75);
                        
                }

                
                
                /* main loop */
                for (int n=1; n<=max; n++) {
                        for (int k=1; k<=n; k++) {
                                
                                
                                /* RECCURENCES */                               
                                if (n == k) {
                                        tab[n][k] = 1;
                                } else if (n == 0 || k == 0) {
                                        
                                        tab[n][k] = 0;
                                        
                                } else {
                                        
                                        /* numbers */
                                        if (numbers == 1) {
                                                tab[n][k] = (tab[n-1][k-1] + tab[n-1][k]) % mod;
                                        }
                                        if (numbers == 2) {
                                                tab[n][k] = (tab[n-1][k-1] + (n-1)*tab[n-1][k]) % mod;
                                        }
                                        if (numbers == 3) {
                                                tab[n][k] = (tab[n-1][k-1] + k*tab[n-1][k]) % mod;
                                        }
                                        if (numbers == 6) {
                                                tab[n][k] = (tab[n-1][k-1] + tab[n-1][k]*tab[n-1][k]) % mod;
                                        }
                                        if (numbers == 7) {
                                                tab[n][k] = (tab[n-1][k-1]*tab[n-1][k-1] + tab[n-1][k]) % mod;
                                        }
                                        if (numbers == 8) {
                                                tab[n][k] = (tab[n-1][k-1]*tab[n-1][k-1] + tab[n-1][k]*tab[n-1][k]) % mod;
                                        }
                                        if (numbers == 9) {
                                                tab[n][k] = ((n-1)*tab[n-1][k-1] + (k+1)*tab[n-1][k]) % mod;
                                        }
                                        if (numbers == 10) {
                                                tab[n][k] = ((n+1)*tab[n-1][k-1] + (k-1)*tab[n-1][k]) % mod;
                                        }
                                        if (numbers == 4) {
                                                tab[n][k] = ((n-k)*tab[n-1][k-1] + (k+1)*tab[n-1][k]) % mod;
                                                
                                                if (n == k) {
                                                        tab[n][k] = 0;
                                                }
                                        }
                                        if (numbers == 5) {
                                                tab[n][k] = ((2*n-k-1)*tab[n-1][k-1] + (k+1)*tab[n-1][k]) % mod;
                                                
                                                if (n == k) {
                                                        tab[n][k] = 0;
                                                }
                                        }
                                        
										if (numbers == 11) {
											
											if (n==k) {
												tab[n][k] = 1 % mod;
											} else{
												tab[n][k] = (f[n-k-1]*tab[n-1][k-1] + f[k+1]*tab[n-1][k]) % mod;
											}

                                        }
                                        if (numbers == 12) {
                                                
                                                if (n==k) {
                                                        tab[n][k] = 1 % mod;
                                                } else{
                                                        tab[n][k] = (f[n-k+1]*tab[n-1][k-1] + f[k-1]*tab[n-1][k]) % mod;
                                                }

                                        }
                                        if (numbers == 13) {
                                                
                                                if (n==k) {
                                                        tab[n][k] = 1 % mod;
                                                } else{
                                                        tab[n][k] = (tab[n-1][k-1] + f[k]*tab[n-1][k]) % mod;
                                                }

                                        }
                                        if (numbers == 14) {
                                                
                                                if (n==k) {
                                                        tab[n][k] = 1 % mod;
                                                } else{
                                                        tab[n][k] = (tab[n-1][k-1] + f[n]*tab[n-1][k]) % mod;
                                                }

                                        } 
                                        
                                        if (numbers == 15) {
                                                
                                                tab[n][k] = (tab[n-1][k+1] + tab[n-1][k] + tab[n-1][k-1]) % mod;
                                                
                                        }
                                        if (numbers == 16) {
                                                tab[n][k] = (tab[n-1][k+1] + tab[n-1][k-1]) % mod;

                        	        	}
				        	if (numbers == 17) {
								if (n > 1) tab[n][k] = (tab[n-1][k+1] + tab[n-2][k] + tab[n-1][k-1]) % mod;
										else tab[n][k] = (tab[n-1][k+1] + mod + tab[n-1][k-1]) % mod;
				        	}
				        	if (numbers == 18) {
				        		tab[n][k] = (power(tab[n-1][k-1],tab[n-1][k],mod) + power(tab[n-1][k],tab[n-1][k-1],mod)) % mod;
				        	}
				        	if (numbers == 19) {
				        		tab[n][k] = (tab[n-1][k-1] + power(tab[n-1][k],tab[n-1][k-1],mod)) % mod;
				        	}
				        	if (numbers == 20) {
				        		tab[n][k] = (tab[n-1][k] + power(tab[n-1][k],tab[n-1][k-1],mod)) % mod;
				        	}
				        	if (numbers == 21) {
					        	tab[n][k] = (tab[n-1][k] + power(tab[n-1][k-1],tab[n-1][k],k)) % mod;
				        	}
				        	if (numbers == 22) {
					        	tab[n][k] = (tab[n-1][k] + power(tab[n-1][k-1],tab[n-1][k],n)) % mod;
				        	}
				        	if (numbers == 23) {
					        	tab[n][k] = (tab[n-1][k] + power(tab[n-1][k-1],tab[n-1][k],mod-tab[n-1][k-1])) % mod;
				        	}
				        	if (numbers == 24) {
					        	tab[n][k] = (tab[n-1][k] + power(tab[n-1][k-1],tab[n-1][k],mod-tab[n-1][k])) % mod;
				        	}
				        	//if (numbers == 25) {
					        //	tab[n][k] = f(n,k,mod) % mod;	
				        	//}
				        				        
						}
				
						/* COLOR */
				
						color=(int)(((6*cm)/mod) * tab[n][k]);
						
						if (color <= cm) {
				        		red=cm;
				        		green=color;
				        		blue=0;
						}else if (color <= 2*cm) {
				        		red = cm - (color-cm);
				        		green = cm;
				        		blue = 0;
						}else if (color <= 3*cm) {
				        		red = 0;
				        		green = cm;
				        		blue = (color - 2*cm);
						}else if (color <= 4*cm) {
				        		red = 0;
				        		green = cm - (color - 3*cm);
				        		blue = cm;
						}else if (color <= 5*cm) {
				        		red = (color - 4*cm);
				        		green = 0;
				        		blue = cm;
						}else if (color <= 6*cm) {
				        		red = cm;
				        		green = 0;
				        		blue = (color - 5*cm);
						}
						
						
						if (tab[n][k] == 0) { red=230;green=230;blue=230; }
		
						if (filter != -1 && tab[n][k] != filter) {
				        		red=255;
				        		green=255;
				        		blue=255;
						}
						if (filter != -1 && tab[n][k] == filter) {
				        		red = 0;
				        		green = 0;
				        		blue = 0;
						}
						
						if (filter == modulo) {
				        		red = 0;
				        		green = 0;
				        		blue = 0;
						}
						
						g.setColor(new Color(red,green,blue));
						
						/* drawing the point */
						g.drawLine(x+(k-1)+((int)(n / 2)),y,x+(k-1)+((int)(n / 2)),y);
		        	}
		        	
		        	x--;
		        	y++;
				}
    
        }
  
};


public class FractalTriangles extends Applet implements ItemListener, ActionListener
{
        Choice modL, numbersL, filterL;
        Button czyscButton;
        GraphTriangle tablet;
        int modulo=2;
        int numbers=1;
        int filter=-1;
		
        public void init()
        {        
			/* wyswietlanie na ekranie */
		
			tablet = new GraphTriangle(modulo,numbers,filter);
		
			numbersL = new Choice();
			/* numbersL.addItem("01 - Wspó³czynniki Dwumienne");
			numbersL.addItem("02 - numbers Stirlinga I rodzaju");
			numbersL.addItem("03 - numbers Stirlinga II rodzaju");
			numbersL.addItem("04 - numbers Eulera I rzedu");
			numbersL.addItem("05 - numbers Eulera II rzedu");
			numbersL.addItem("06 - f[n,k] = f[n-1,k-1] + f[n-1,k]^2)");
			numbersL.addItem("07 - f[n,k] = f[n-1,k-1]^2 + f[n-1,k])");
			numbersL.addItem("08 - f[n,k] = f[n-1,k-1]^2 + f[n-1,k]^2)");
			numbersL.addItem("09 - f[n,k] = (n-1)*f[n-1,k-1] + (k+1)*f[n-1,k])");
			numbersL.addItem("10 - f[n,k] = (n+1)*f[n-1,k-1] + (k-1)*f[n-1,k])");
			numbersL.addItem("11 - Fibonacci Cobweb Posets");
			numbersL.addItem("12 - fib mod");
			numbersL.addItem("13 - sII mod");
			numbersL.addItem("14 - sI mod");
			numbersL.addItem("15 - suma trzech sasiednich");
			numbersL.addItem("16 - suma dwoch sasiadow z gory");
			numbersL.addItem("17 - prostokaty"); 
			numbersL.addItem("18 - f[n-1][k-1]^f[n-1][k] + f[n-1][k]^f[n-1][k-1])"); */
			
			numbersL.addItem("01 - Pascal Trian");
			numbersL.addItem("02 - Stirl I");
			numbersL.addItem("03 - Stirl II");
			numbersL.addItem("04 - Euler I");
			numbersL.addItem("05 - Euler II");
			numbersL.addItem("06 - f[n,k] = ...");
			numbersL.addItem("07 - f[n,k] = ...");
			numbersL.addItem("08 - f[n,k] = ...");
			numbersL.addItem("09 - f[n,k] = ...");
			numbersL.addItem("10 - f[n,k] = ...");
			numbersL.addItem("11 - Fib CobPos");
			numbersL.addItem("12 - fib mod");
			numbersL.addItem("13 - sII mod");
			numbersL.addItem("14 - sI mod");
			numbersL.addItem("15 - sum 3 sas");
			numbersL.addItem("16 - sum 2 sas");
			numbersL.addItem("17 - rectangle");
			numbersL.addItem("18 - PowerBinom");
			numbersL.addItem("19 - PowerBinom");
			numbersL.addItem("20 - PowerBinom");
			numbersL.addItem("21 - PowerBinom");
			numbersL.addItem("22 - PowerBinom");
			numbersL.addItem("23 - PowerBinom");
			numbersL.addItem("24 - PowerBinom");
			
			
			czyscButton = new Button("Clear");
	
			modL = new Choice();               
			for (int i=2; i<=1530; i++)
		        	modL.addItem( new Integer(i).toString() );
			
			filterL = new Choice();
			filterL.addItem("all");
			for (int i=0; i<=1530; i++)
		        	filterL.addItem( new Integer(i).toString() );
			
			
			setLayout( new BorderLayout() );
					
			Panel sPanel = new Panel();
			sPanel.setLayout( new FlowLayout() );
			sPanel.add( new Label("Numbers:") );
			sPanel.add( numbersL );
			sPanel.add( new Label("Modulo:") );
			sPanel.add( modL );
			sPanel.add( new Label("filter:") );
			sPanel.add( filterL );
			
			sPanel.add( czyscButton );
			
			add( "South", sPanel );
			add( "Center", tablet );
			numbersL.addItemListener( this );
			modL.addItemListener( this );
			filterL.addItemListener( this );
			czyscButton.addActionListener( this );
	
       	}
        

        public void itemStateChanged( ItemEvent evt )
        {        
		
			if ( evt.getSource() == modL )
			{
		        String s = evt.getItem().toString();
		        modulo = Integer.parseInt( s );
			}
			if ( evt.getSource() == numbersL )
			{
		        String s = evt.getItem().toString();
		        numbers = Integer.parseInt(s.substring(0,2));
			}
			if ( evt.getSource() == filterL )
			{
		        String s = evt.getItem().toString();
		        if (s.length() >= 3 && s.substring(0,3) == "all") {
					filter = -1;
		        } else {
					filter = Integer.parseInt( s );		        
				}
			
			}
		
			remove( tablet );
			tablet = new GraphTriangle(modulo,numbers,filter);
			add( "Center", tablet );
			validate();
		
        }

	public void actionPerformed( ActionEvent evt )
        {
			remove( tablet );
			tablet = new GraphTriangle(2,1,-2);
			add( "Center", tablet );
			validate();
        }

}
