import java.util.* ;

class Simul {

  /**************************************************/
  /* Modélisation du client en attente dans la file */
  /**************************************************/

  static class Client {
    // Temps d'attente mini et maxi
    final static int waitMin = 120 ;
    final static int waitMax = 1800 ;

    // NB: l'heure de départ est calculée dans le constructeur
    int arrival, departure ;
    Client (int t) {
      arrival = t ;
      departure = t+Simul.uniform(waitMin, waitMax) ;
    }
  }


  /******************************************/
  /* File vite codée, merci la bibliothèque */
  /******************************************/

  static class Fifo extends LinkedList<Client> { }

  /****************************/
  /* Source pseudo-aléatoire  */
  /****************************/

  // Comme on utilise une variable de classe, tout est privé
  static private Random rand = new Random () ;

  // Loi uniforme sur [min..max[
  static private int uniform(int min, int max) {
    return min + rand.nextInt(max-min) ;
  }
  
  // Survenue d'un évenement de probailité prob
  static private boolean occurs(double prob) {
    return rand.nextDouble() < prob ;
  }


  // Diverses constantes employées dans simul
  final static int tMax = 8 * 60 * 60 ; // huit heures
  final static int serviceMin = 30 ;
  final static int serviceMax = 300 ;

  /******************************************/
  /* Simulation proprement dite,            */
  /*   renvoie le ratio de clients dégoutés */
  /******************************************/

  static double simul(double probNewClient) {
    Fifo f = new Fifo () ;
    int nbClients = 0, nbFedUp = 0 ;
    int tFree = 0 ; // Le guichet est libre au temps tFree 

    for (int t = 0 ; t < tMax ; t++) {
      // Tirer l'arrivée d'un client dans [t..t+1[
      if (occurs(probNewClient)) {
        nbClients++ ;
        f.add(new Client(t)) ;
      }
      if (tFree <= t) {
        // Le guichet est libre, servir un client (si il y en a encore un)
        while (!f.isEmpty()) {
          Client c = f.remove() ;
          if (c.departure >= t) { // Le client c est encore là
            tFree = t + uniform(serviceMin, serviceMax) ;
            break ; // Sortir de la boucle while
          } else {
            nbFedUp++ ;
          }
        }
      }
    }
    return ((double)nbFedUp)/nbClients ;
  }

  // Réaliser les expériences, moyennes sur ntries essais
  public static void main(String [] arg) {
    final double delta = 0.00025 ;
    final int ntries = 10 ;
    for (double prob = delta ; prob < 0.025 ; prob += delta) {
      double sum = 0.0 ;
      for (int k = 0 ; k < ntries ; k++)
        sum += simul(prob) ;
      double ratio = sum/ntries ;
      if (!Double.isNaN(ratio) && !Double.isInfinite(ratio)) 
        System.out.println(prob + " " + ratio) ;
    }
  }
}
