//servidor:



public class ServidorMatriz{
  public static void main(String[]args) throws Exception {
    ServerSocket ss=new ServerSocket(2600);
    while(true){
      Socket s = ss.accept();
      new ServidorThread(s).start();
    }
  }
}



//servidot thread:



public class ServidorThread extends Thread{

  private final int fil;
  private final int col;

  private Socket s;
  private int [] [] matriz;
  public EnviarArchivo(Socket x){
    s=x;
    fil=1000;
    col=1000;
    matriz = new int [fil][col];
  }

  public void run(){
    try {
      BufferedReader in=new BufferedReader(
			new InputStreamReader(s.getInputStream()));
      for(int i=0;i<fil;i++)
        for(int j;j<col;j++)
          matriz[i][j]=Integer.parseInt(in.readLine());
      in.close();
      PrintWriter out=new PrinterWriter(s.getOutputStream(),true);
      for(int i=0;i<fil;i++)
	out.println(mayor(i));
      out.close();
    }
  }

  private int mayor(int index){
    int max=matriz[index][0];
    for(int i=1;i<fil;i++)
      if(max<matriz[indez][i])
	max=matriz[index][i];
    return max;
  }
}


//cliente:

public class ClienteMatriz{
  private final int fil=1000;
  private final int col=1000;

  public static void main(String[]args)throws Exception {
    Socket s=new Socket(hal.odisea.org,2600);
    int [][] matriz=new int[fil][col];
    int [] minimos =new int[col];
    int [] maximos =new int[fil];

    //utilizamos la funcion que nos dan desde el enunciado y
    //que se encarga de llenar la matriz con numeros al azar
    random(matriz);
    
    //generamos un thread cliente con la matriz y el socket
    ClienteThread ct=new ClienteThread(matriz,s);
    ct.start();

    //calculamos mientras tanto el minimo de cada columna.
    for(int i=0;i<col;i++)
      minimos[i]=matriz[0][i];
    for(int i=0;i<col;i++)
      for(int j=1;j<fil;j++)
	if(minimos[i]<matriz[j][i])
	  minimos[i]=matriz[j][i];

    //Debemos esperar a que termine el thread cliente para hacer
    //el calculo final.
    ct.join();

    //ahora podemos cerrar el socket:
    s.close();

    //obtener el max de cada fila:
    for(int i=0;i<fil;i++)
      maximos[i]=ct.maximoDe(i);

    //ahora debemos buscar si existe un valor repetido dentro
    //de los arreglos maximos y minimos.
    for(int i=0;i<fil;i++)
      for(int j=0;j<col;j++)
	if(minimos[j]==maximos[i]){
	  System.out.println("Punto silla: "+minimos[j]);
	  return;
	}
     System.out.println("Punto silla no encontrado!!!");
  }
}



//clase ClienteThread:



public class ClienteThread{

  private Socket s;
  private int [] [] matriz;
  int [] maximos;
  public ClienteThread(Socket s, int [][] matriz){
    this.s=s;
    this.matriz = matriz;
    maximos=new int[matriz.length];
  }

  public void run(){
    try {
      //imprimir la matriz en el socket:
      PrintWriter out=new PrinterWriter(s.getOutputStream(),true);
      for(int i=0;i<matriz.length;i++)
        for(int j;j<matriz[0].length;j++)
          out.println(matriz[i][j]);
      out.close();
      
      //leer los datos desde el socket:
      BufferedReader in=new BufferedReader(
			new InputStreamReader(s.getInputStream()));
      for(int i=0;i<matriz.length;i++)
          maximos[i]=Integer.parseInt(in.readLine());
      in.close();
    }
  }

  //metodo para obtener los maximos:
  public int maximoDe(int numerodefila){
    if(numerodefila<maximos.length)
      return maximos[numerodefilas];
    return -1;
  }
}

