//voici quelques commentaires pour ceux qui ne connaissent pas le java
//ce programme n'a pas pu être optimisé par manque de temps
import java.io.*; 
public class BS {
    
    //fonction principale du programme
     public static void main(String args[]) {
      int N;
      float r;
      float s;
      float K;
      float T;
      
      //récupère les arguments qui sont de type "string" et exécute s'ils sont 5
      if (args.length==5) {
        N=Integer.parseInt(args[0]);//transforme le 1er arg en entier
        Float r1=Float.valueOf(args[1]);//transforme le 2ème arg en objet float
        r=r1.floatValue();//transforme l'objet en variable float
        Float s1=Float.valueOf(args[2]);
        s=s1.floatValue();
        Float K1=Float.valueOf(args[3]);
        K=K1.floatValue();
        Float T1=Float.valueOf(args[4]);
        T=T1.floatValue();
        float L=2*K;
        float dX=L/(N-1);
        
        //récupère le tableau de la fonction "fonctionu1"
        float[] u=fonctionu1(r,s,K,N,T);
        
         //affiche dans 3 colonnes les données des 3 fonctions
         for(int i=0;i<=N-1;i++) 
            System.out.println(fonctionx(i,dX)+"   "+u[i]+"   "+fonctionu(i,K,dX));   
        }
     }
     
     
    //fonction qui retourne le tableau des valeurs de la solution de l'edp au temps 0
    public static float[] fonctionu1(float r,float s,float K,int N,float T) {
         float[] U1=new float[N];
         float[] U=new float[N];
         float L=2*K;
         float dX=L/(N-1);
         for(int p=0;p<N;p++)
           U1[p]=fonctionu(p,K,dX);
         float dT=-(dX*dX)/(s*s*L*L+r*L*dX);
         float temps=T;//temps rétrograde
         
            
            //condition de stabilité//
            while(temps>0) {
            dT=-Math.min(Math.abs(dT),temps);
            temps=temps+dT;
            for(int j=1;j<N-1;j++) 
                  U[j]=U1[j]+dT*(-r*fonctionx(j,dX)*(U1[j+1]-U1[j-1])/(2*dX)-(s*s*fonctionx(j,dX)*fonctionx(j,dX))*(U1[j+1]-2*(U1[j])+U1[j-1])/(2*dX*dX)+r*U1[j]);
                
             //conditions limites//
             U[0]=0;
             U[N-1]=U1[N-2]+dX;
             /*Double h= new Double(-K*Math.exp(r*T));
             U[N-1]=(h).floatValue()*/
             
            for(int k=0;k<N;k++)
                U1[k]=U[k];
            }
    return U1;
    }
    
     
     //fonction qui retourne la valeur de la condition finale suivant l'abcisse x
     public static float fonctionu(int indice,float K,float dX) {
        float U=Math.max(0,fonctionx(indice,dX)-K);
        return U;
     }
     
      
      //fonction qui retourne la valeur de l'abcisse x suivant l'indice i
      public static float fonctionx(int indice,float dX) {
        float x=(indice)*dX;
        return x;
     }
    
   
}
     