import java.io.CharArrayReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.Reader;
import java.io.StringReader;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.FileChannel.MapMode;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.InputMismatchException;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.Scanner;
import java.util.regex.Pattern;

/** Classe regroupant les fonctions pratiques pour le Tronc Commun.*/
public class TC {

  private static final Object readMonitor = new Object();
  private static volatile Scanner scanner = scanner(new InputStreamReader(System.in));
  private static Scanner scanner(Reader in) {
    Scanner scanner = new Scanner(in);
    scanner.useLocale(Locale.US);
    return scanner;
  }

  private static final Object writeMonitor = new Object();
  private static volatile PrintStream output = System.out;

  /** lecture d'un int sur l'entr\u00e9e 
   * @throws NumberFormatException quand l'entr\u00e9e disponible n'est pas un entier
   * @throws NoSuchElementException quand il n'y a plus d'entr\u00e9e*/
  public static int lireInt() {
    synchronized (readMonitor) {
      try {
        return scanner.nextInt();
      }
      catch (InputMismatchException e) {
        throw new NumberFormatException("input "+scanner.next()+" is not an int");
      }
    }
  }
  
  /** reads an int from the input.
   * @throws NumberFormatException when available input is not an int
   * @throws NoSuchElementException when no input is available*/
  public static int readInt() {
    return lireInt(); 
  }
  
  /** lecture d'un long sur l'entr\u00e9e 
   * @throws NumberFormatException quand l'entr\u00e9e disponible n'est pas un entier
   * @throws NoSuchElementException quand il n'y a plus d'entr\u00e9e*/
  public static long lireLong() {
    synchronized (readMonitor) {
      try {
        return scanner.nextLong();
      }
      catch (InputMismatchException e) {
        throw new NumberFormatException("input "+scanner.next()+" is not a long");
      }
    }
  }
  
  /** reads a long from the input.
   * @throws NumberFormatException when available input is not a long
   * @throws NoSuchElementException when no input is available*/
  public static long readLong() {
    return lireLong(); 
  }
  
  /** lecture d'un double sur l'entr\u00e9e    
   * @throws NumberFormatException quand l'entr\u00e9e disponible n'est pas un flottant
   * @throws NoSuchElementException quand il n'y a plus d'entr\u00e9e*/
  public static double lireDouble() {
    synchronized (readMonitor) {
      try {
        return scanner.nextDouble();
      }
      catch (InputMismatchException e) {
        throw new NumberFormatException("input "+scanner.next()+" is not a double");
      }
    }
  }
  
  /** reads a double from the input.
   * @throws NumberFormatException when available input is not a double
   * @throws NoSuchElementException when no input is available*/
  public static double readDouble() {
    return lireDouble();
  }

  /** lecture d'un mot sur l'entr\u00e9e 
   * @throws NoSuchElementException quand il n'y a plus d'entr\u00e9e
   * @deprecated utiliser {@link #lireMot() lireMot} \u00e0 la place*/
  @Deprecated public static String lireMotSuivant() {
    return lireMot();
  }
  
  /** lecture d'un mot sur l'entr\u00e9e 
   * @throws NoSuchElementException quand il n'y a plus d'entr\u00e9e */
  public static String lireMot() {  
    synchronized (readMonitor) {
      return scanner.next();
    }
  }
  
  /** reads a word from the input.
   * @throws NoSuchElementException when no input is available*/
  public static String readWord() {
    return lireMot(); 
  }

  /** lecture d'un mot sur l'entr\u00e9e (retourn\u00e9 sous forme de tableau de char)
   * @throws NoSuchElementException quand il n'y a plus d'entr\u00e9e*/
  public static char[] lireMotCommeTableauChar() {
    return lireMot().toCharArray();
  }
  
  /** reads a word from the input as char array.
   * @throws NoSuchElementException when no input is available*/
  public static char[] readWordAsCharArray() {
    return lireMotCommeTableauChar();
  }

  /** lecture d'une ligne sur l'entr\u00e9e
   * @throws NoSuchElementException quand il n'y a plus d'entr\u00e9e*/
  public static String lireLigne() {
    synchronized (readMonitor) {
      return scanner.nextLine();
    }
  }
  
  /** reads a line from the input.
   * @throws NoSuchElementException when no input is available*/
  public static String readLine() {
    return lireLigne();
  }

  /** lecture d'une ligne sur l'entr\u00e9e (retourn\u00e9 sous forme de tableau de char)
   * @throws NoSuchElementException quand il n'y a plus d'entr\u00e9e*/
  public static char[] lireLigneTableauChar() {
    return lireLigne().toCharArray();
  }
  
  /** reads a line from the input as char array.
   * @throws NoSuchElementException when no input is available*/
  public static char[] readLineAsCharArray() {
    return lireLigneTableauChar();
  }
  
  private static final Pattern DOT = Pattern.compile(".",Pattern.DOTALL);
  
  /** lecture du prochain caract\u00e8re sur l'entr\u00e9e 
   * @throws NoSuchElementException quand il n'y a plus d'entr\u00e9e */
  public static char lireChar() {
    synchronized (readMonitor) {
      String match = scanner.findWithinHorizon(DOT,1);
      if (match==null)
        throw new NoSuchElementException();
      return match.charAt(0);
    }
  }
  
  /** reads next character from the input.
   * @throws NoSuchElementException when no input is available*/
  public static char readChar() {
    return lireChar();
  }
  
  private static Pattern BLANKS = Pattern.compile("\\p{javaWhitespace}*");
  
  /** lecture du prochain caract\u00e8re non blanc sur l'entr\u00e9e 
   * @throws NoSuchElementException quand il n'y a plus d'entr\u00e9e */
  public static char lireCharNonBlanc() {
    synchronized (readMonitor) {
      scanner.skip(BLANKS);
      String match = scanner.findWithinHorizon(DOT,1);
      if (match==null)
        throw new NoSuchElementException();
      return match.charAt(0);
    }
  }
  
  /** reads next non-blank character from the input.
   * @throws NoSuchElementException when no input is available*/
  public static char readUnblankChar() {
    return lireCharNonBlanc();
  }
  
  /** affiche un caract\u00e8re sur la sortie 
   * @param c le caract\u00e8re \u00e0 afficher
   */
  public static void print(char c) {
    ecrire(c);
  }
  /** affiche un caract\u00e8re sur la sortie 
   * @param c le caract\u00e8re \u00e0 afficher
   */
  public static void ecrire(char c) {
    synchronized (writeMonitor) {
      output.print(c);
    }    
  }
  
  /** affiche un double sur la sortie 
   * @param d le double \u00e0 afficher
   */
  public static void print(double d) {
    ecrire(d);
  }
  /** affiche un double sur la sortie 
   * @param d le double \u00e0 afficher
   */
  public static void ecrire(double d) {
    synchronized (writeMonitor) {
      output.print(d);
    }
  }

  /** affiche un int sur la sortie 
   * @param i l'int \u00e0 afficher
   */
  public static void print(int i) {
    ecrire(i);
  }
  /** affiche un int sur la sortie 
   * @param i l'int \u00e0 afficher
   */
  public static void ecrire(int i) {
    synchronized (writeMonitor) {
      output.print(i);
    }
  }
  
  /** affiche un long sur la sortie 
   * @param l le long \u00e0 afficher
   */
  public static void print(long l) {
    ecrire(l);
  }
  /** affiche un long sur la sortie 
   * @param l le long \u00e0 afficher
   */
  public static void ecrire(long l) {
    synchronized (writeMonitor) {
      output.print(l);
    }
  }

  /** affiche une cha\u00eene sur la sortie 
   * @param s la cha\u00eene \u00e0 afficher
   */
  public static void print(String s) {
    ecrire(s);
  }
  /** affiche une cha\u00eene sur la sortie 
   * @param s la cha\u00eene \u00e0 afficher
   */
  public static void ecrire(String s) {
    synchronized (writeMonitor) {
      output.print(s);
    }
  }

  /** affiche une cha\u00eene pass\u00e9e comme un tableau de char sur la sortie 
   * @param s la cha\u00eene \u00e0 afficher
   */
  public static void print(char[] s) {
    ecrire(s);
  }
  /** affiche une cha\u00eene pass\u00e9e comme un tableau de char sur la sortie 
   * @param s la cha\u00eene \u00e0 afficher
   */
  public static void ecrire(char[] s) {
    synchronized (writeMonitor) {
      for (char c:s)
        output.print(c);
    }
  }
  
  /** saute les blancs sur l'entr\u00e9e (inutile pour les m\u00e9thodes lire sauf {@link #lireChar() lireChar}
   *  et {@link #lireLigne() lireLigne})
   */
  public static void passerBlancs() {
    synchronized (readMonitor) {
      scanner.skip(scanner.delimiter());
    }
  }
  
  /** skip blanks from input, automatic for all read method except {@link #readLine() readLine} and {@link #readChar() readChar}
   * @see #readUnblankChar()
   */
  public static void skipBlanks() {
    passerBlancs();
  }

  /** va \u00e0 la ligne sur l'entr\u00e9e */
  public static void println() {
    retourALaLigne();
  }
  /** va \u00e0 la ligne sur l'entr\u00e9e */
  public static void retourALaLigne() {
    synchronized (writeMonitor) {
      output.println();
    }
  }

  /** affiche un double sur la sortie puis va \u00e0 la ligne
   * @param d le double \u00e0 afficher
   */
  public static void println(double d) {
    ecrireSuiviParRetourALaligne(d);
  }
  /** affiche un double sur la sortie puis va \u00e0 la ligne
   * @param d le double \u00e0 afficher
   */
  public static void ecrireSuiviParRetourALaligne(double d) {
    synchronized (writeMonitor) {
      output.println(d);
    }
  }

  /** affiche un int sur la sortie puis va \u00e0 la ligne
   * @param i le int \u00e0 afficher
   */
  public static void println(int i) {
    ecrireSuiviParRetourALaligne(i);
  }
  /** affiche un int sur la sortie puis va \u00e0 la ligne
   * @param i le int \u00e0 afficher
   */
  public static void ecrireSuiviParRetourALaligne(int i) {
    synchronized (writeMonitor) {
      output.println(i);
    }
  }
  
  /** affiche un long sur la sortie puis va \u00e0 la ligne
   * @param l le long \u00e0 afficher
   */
  public static void println(long l) {
    ecrireSuiviParRetourALaligne(l);
  }
  /** affiche un long sur la sortie puis va \u00e0 la ligne
   * @param l le long \u00e0 afficher
   */
  public static void ecrireSuiviParRetourALaligne(long l) {
    synchronized (writeMonitor) {
      output.println(l);
    }
  }

  /** affiche une cha\u00eene sur la sortie puis va \u00e0 la ligne
   * @param s la cha\u00eene \u00e0 afficher
   */
  public static void println(String s) {
    ecrireSuiviParRetourALaligne(s);
  }
  /** affiche une cha\u00eene sur la sortie puis va \u00e0 la ligne
   * @param s la cha\u00eene \u00e0 afficher
   */
  public static void ecrireSuiviParRetourALaligne(String s) {
    synchronized (writeMonitor) {
      output.println(s);
    }
  }

  /** affiche une cha\u00eene pass\u00e9e comme un tableau de char sur la sortie puis va \u00e0 la ligne
   * @param s la cha\u00eene \u00e0 afficher
   */
  public static void println(char[] s) {
    ecrireSuiviParRetourALaligne(s);
  }
  /** affiche une cha\u00eene pass\u00e9e comme un tableau de char sur la sortie puis va \u00e0 la ligne
   * @param s la cha\u00eene \u00e0 afficher
   */
  public static void ecrireSuiviParRetourALaligne(char[] s) {
    synchronized (writeMonitor) {
      for (char c:s)
        output.print(c);
      output.println();
    }
  }
 
  /**
   * Tests if non blank characters are available from the input
   * @return true if non blank characters are available from the input.
   */
  public static boolean hasMoreWords() {
    return motsDisponibles();
  }
  
  /**
   * Teste s'il reste des caract\u00e8res non blancs sur l'entr\u00e9e
   * @return true s'il reste des caract\u00e8res non blancs sur l'entr\u00e9e.
   */
  public static boolean motsDisponibles() {
    synchronized (readMonitor) {
      return scanner.hasNext();
    }
  }
  
  /**
   * Tests if characters (possibly only blanks) are available from the input
   * @return true if non blank characters are available from the input.
   */
  public static boolean hasMoreLines() {
    return lignesDisponibles();
  }
  
  /**
   * Teste s'il reste des caract\u00e8res (\u00e9ventuellement que des blancs) sur l'entr\u00e9e
   * @return true s'il reste des caract\u00e8res non blancs sur l'entr\u00e9e.
   */
  public static boolean lignesDisponibles() {
    synchronized (readMonitor) {
      return scanner.hasNextLine();
    }
  }
  
  /**
   * Tests if non blank characters are available from the input
   * @return false if non blank characters are available from the input.
   */
  @Deprecated public static boolean eof() {
    return finEntree();
  }
  
  /**
   * Tests if non blank characters are available from the input
   * @return false if non blank characters are available from the input.
   */
  @Deprecated public static boolean endOfInput() {
    return finEntree();
  }
  
  /**
   * Teste s'il reste des caract\u00e8res non blancs sur l'entr\u00e9e
   * @return false s'il reste des caract\u00e8res non blancs sur l'entr\u00e9e.
   */
  @Deprecated public static boolean finEntree() {
    synchronized (readMonitor) {
      return !scanner.hasNext();
    }
  }
  
  /**
   * Teste s'il reste des caract\u00e8res sur l'entr\u00e9e
   * @return false s'il reste des caract\u00e8res sur l'entr\u00e9e.
   */
  @Deprecated public static boolean fin() {
    synchronized (readMonitor) {
      return !scanner.hasNextLine();
    }
  }
  
  /**
   * Tests if character (possibly white) are available from the input
   * @return false if non blank character are available from the input.
   */
  @Deprecated public static boolean endOfStream() {
    return finEntree();
  }


  /**
   * Redirige la sortie des m\u00e9thodes afficher et print vers un fichier. Ce dernier sera \u00e9cras\u00e9 s'il existe.
   * @param fileName le nom du fichier
   * @throws IllegalArgumentException quand on ne peut \u00e9crire dans le fichier
   */
  public static void sortieFichier(String fileName) {
    sortieFichier(fileName,false);
  }
  
  /**
   * Ajoute la sortie des m\u00e9thodes {@code ecrire} et {@code print} \u00e0 la fin d'un fichier.
   * @param fileName le nom du fichier
   * @throws IllegalArgumentException quand on ne peut \u00e9crire dans le fichier
   */
  public static void sortieAjouteeEnFinDeFichier(String fileName) {
    sortieFichier(fileName,true);
  }
  
  /**
   * Redirect outputs of methods {@code ecrire} and {@code print} to a file. The file will be overwritten if it exists.
   * @param fileName the file name
   * @throws IllegalArgumentException when the system cannot write to the file
   */
  public static void outputToFile(String fileName) {
    sortieFichier(fileName);
  }
  
  /**
   * Append outputs of methods {@code ecrire} and {@code print} to a file.
   * @param fileName the file name
   * @throws IllegalArgumentException when the system cannot write to the file
   */
  public static void appendOutputToFile(String fileName) {
    sortieAjouteeEnFinDeFichier(fileName);
  } 
  
  
  private static void sortieFichier(String fileName, boolean append) {
    synchronized(writeMonitor) {
      try {
        output.close();
        output=new PrintStream(new FileOutputStream(fileName,append));
      }
      catch (FileNotFoundException e) {
        throw new IllegalArgumentException(e.getMessage());
      }
    }
  }
  
  /**
   * Change l'entr\u00e9e des m\u00e9thodes lire pour que la lecture se fasse \u00e0 partir d'un fichier
   * @param fileName le nom du fichier
   * @throws IllegalArgumentException quand on ne peut lire dans le fichier ou qu'il n'existe pas
   */
  public static void lireFichier(String fileName) {
    synchronized (readMonitor) {
      try {
        scanner.close();
        scanner=scanner(new FileReader(fileName));   
      } catch (FileNotFoundException e) {
        throw new IllegalArgumentException(e.getMessage());
      }
    }
  }
  
  /**
   * Change input of read method to a file
   * @param fileName the name of the file
   * @throws IllegalArgumentException when file does not exist or is not readable
   */
  public static void readFromFile(String fileName) {
    lireFichier(fileName);
  }
  
  /**
   * Change l'entr\u00e9e des m\u00e9thodes lire pour que la lecture se fasse \u00e0 partir d'une cha\u00eene
   * @param input la cha\u00eene
   */
  public static void lireDeString(String input) {
    synchronized (readMonitor) {
      scanner.close();
      scanner=scanner(new StringReader(input)); 
    }
  }
  
  /**
   * Change input of read method to a String
   * @param input the input
   */
  public static void readFromString(String input) {
    lireDeString(input);
  }
  
  /**
   * Change l'entr\u00e9e des m\u00e9thodes lire pour que la lecture se fasse \u00e0 partir d'une
   * cha\u00eene pass\u00e9e comme un tableau de char.
   * @param input la cha\u00eene
   */
  public static void lireDeChaine(char[] input) {
    synchronized (readMonitor) {
      scanner.close();
      scanner=scanner(new CharArrayReader(input)); 
    }
  }
  
  /**
   * Change input of read method to a char array
   * @param input the input
   */
  public static void readFromString(char[] input) {
    lireDeChaine(input);
  }

  /**
   * Lit tous le contenu d'un fichier et le retourne sous forme de tableau de char
   * @param fileName le nom de fichier
   * @return le contenu du fichier
   * @throws IllegalArgumentException en cas d'erreur de lecture ou de fichier inexistant
   */
  public static char[] charDeFichier(String fileName) {
    File file = new File(fileName);
    long size = file.length();
    ByteBuffer buffer;
    try {
      buffer = new FileInputStream(file).getChannel().map(MapMode.READ_ONLY, 0, size);
    } catch (IOException e) {
      throw new IllegalArgumentException(e.getMessage());
    }
    CharBuffer charBuffer = Charset.defaultCharset().decode(buffer);
    char[] charArray = new char[charBuffer.limit()];
    charBuffer.get(charArray);
    return charArray;
  }
  
  /**
   * reads the whole content of a file and returns it as a char array
   * @param fileName the file name
   * @return the content of the file
   * @throws IllegalArgumentException when file does not exist or is not readable
   */
  public static char[] charFromFile(String fileName) {
    return charDeFichier(fileName);
  }

  /**
   * Lit tous le contenu d'un fichier et le retourne sous forme de cha\u00eene java
   * @param fileName le nom de fichier
   * @return le contenu du fichier
   */
  public static String chaineDeFichier(String fileName) {
    return new String(charDeFichier(fileName));
  }
  
  /**
   * reads the whole content of a file and returns it as a java String
   * @param fileName the file name
   * @return the content of the file
   */
  public static String stringFromFile(String fileName) {
    return chaineDeFichier(fileName);
  }

  
  /**
   * Lit tous le contenu d'un fichier et le retourne sous forme de tableau de char
   * @param fileName le nom de fichier
   * @return le contenu du fichier
   * @deprecated {@link #chaineDeFichier(String) chaineDeFichier} \u00e0 la place (ce nom ne respecte pas 
   * les conventions de nommage qui stipule que les m\u00e9thode doivent commencer par une minuscule)
   */
  @Deprecated
  public static String StringDeFichier(String fileName) {
    return new String(charDeFichier(fileName));
  }

  /**
   * Lit tout le contenu d'une cha\u00eene contenant des entier et les retourne
   * @param input la cha\u00eene
   * @return le tableau des entiers lus
   * @throws InputMismatchException quand la cha\u00eene contient autre chose que des entiers
   */
  public static long[] longDeChaine(String input) {
    return longDeScanner(new Scanner(input));
  }
  
  /**
   * Reads the whole content of a String containing integers and returns them in an array
   * @param input the input
   * @return the array of integers read
   * @throws InputMismatchException when file does not contain only integers
   */
  public static long[] longFromString(String input) {
    return longDeChaine(input);
  }
  
  /**
   * Lit tout le contenu d'un fichier contenant des entier et les retourne
   * @param fileName le nom de fichier
   * @return le tableau des entiers lus
   * @throws InputMismatchException quand le fichier contient autre chose que des entiers
   */
  public static long[] longDeFichier(String fileName) {
    Scanner scanner;
    try {
      scanner = new Scanner(new File(fileName));
      return longDeScanner(scanner);
    } catch (FileNotFoundException e) {
      throw new IllegalArgumentException(e.getMessage());
    }
  }
  
  /**
   * Reads the whole content of a file containing integers and returns them in an array
   * @param fileName the nom of the file
   * @return the array of integers read
   * @throws InputMismatchException when file does not contain only integers
   */
  public static long[] longFromFile(String fileName) {
    return longDeFichier(fileName);
  }
 
  
  private static long[] longDeScanner(Scanner scanner) {
    ArrayList<Long> list = new ArrayList<Long>();
    scanner.useLocale(Locale.US);
    while (scanner.hasNext())
      list.add(scanner.nextLong());
    long[] ans = new long[list.size()];
    for(int i=0;i<ans.length;i++)
      ans[i]=list.get(i);
    return ans;
  }

  
  /**
   * Lit tout le contenu d'une cha\u00eene contenant des entier et les retourne
   * @param input la cha\u00eene
   * @return le tableau des entiers lus
   * @throws InputMismatchException quand la cha\u00eene contient autre chose que des entiers
   */
  public static int[] intDeChaine(String input) {
    return intDeScanner(new Scanner(input));
  }
  
  /**
   * Reads the whole content of a String containing integers and returns them in an array
   * @param input the input
   * @return the array of integers read
   * @throws InputMismatchException when file does not contain only integers
   */
  public static int[] intFromString(String input) {
    return intDeChaine(input);
  }
  
  
  /**
   * Lit tout le contenu d'un fichier contenant des entier et les retourne
   * @param fileName le nom de fichier
   * @return le tableau des entiers lus
   * @throws InputMismatchException quand le fichier contient autre chose que des entiers
   */
  public static int[] intDeFichier(String fileName) {
    Scanner scanner;
    try {
      scanner = new Scanner(new File(fileName));
      return intDeScanner(scanner);
    } catch (FileNotFoundException e) {
      throw new IllegalArgumentException(e.getMessage());
    }
  }
  
  /**
   * Reads the whole content of a file containing integers and returns them in an array
   * @param fileName the nom of the file
   * @return the array of integers read
   * @throws InputMismatchException when file does not contain only integers
   */
  public static int[] intFromFile(String fileName) {
    return intDeFichier(fileName);
  }
  
  private static int[] intDeScanner(Scanner scanner) {
    ArrayList<Integer> list = new ArrayList<Integer>();
    scanner.useLocale(Locale.US);
    while (scanner.hasNext())
      list.add(scanner.nextInt());
    int[] ans = new int[list.size()];
    for(int i=0;i<ans.length;i++)
      ans[i]=list.get(i);
    return ans;
  }

  /**
   * Lit tout le contenu d'une cha\u00eene contenant des flottants et les retourne
   * @param input la cha\u00eene
   * @return le tableau des flottants lus
   * @throws InputMismatchException quand la cha\u00eene contient autre chose que des flottants
   */
  public static double[] doubleDeChaine(String input) {
    return doubleDeScanner(new Scanner(input));
  }
  
  /**
   * Reads the whole content of a String containing floating point numbers and returns them in an array
   * @param input the input
   * @return the array of floating point numbers read
   * @throws InputMismatchException when file does not contain only floating point numbers
   */
  public static double[] doubleFromString(String input) {
    return doubleDeChaine(input);
  }
  
  /**
   * Lit tout le contenu d'un fichier contenant des flottants et les retourne
   * @param fileName le nom de fichier
   * @return le tableau des flottants lus
   * @throws InputMismatchException quand le fichier contient autre chose que des flottants
   */
  public static double[] doubleDeFichier(String fileName) {
    Scanner scanner;
    try {
      scanner = new Scanner(new File(fileName));
      return doubleDeScanner(scanner);
    } catch (FileNotFoundException e) {
      throw new IllegalArgumentException(e.getMessage());
    }
  }
  
  /**
   * Reads the whole content of a file containing floating point numbers and returns them in an array
   * @param fileName the nom of the file
   * @return the array of floating point numbers read
   * @throws InputMismatchException when file does not contain only floating point numbers
   */
  public static double[] doubleFromFile(String fileName) {
    return doubleDeFichier(fileName);
  }
  
  private static double[] doubleDeScanner(Scanner scanner) {
    ArrayList<Double> list = new ArrayList<Double>();
    scanner.useLocale(Locale.US);
    while (scanner.hasNext())
      list.add(scanner.nextDouble());
    double[] ans = new double[list.size()];
    for(int i=0;i<ans.length;i++)
      ans[i]=list.get(i);
    return ans;
  }
 
  /**
   * Lit tout le contenu d'une cha\u00eene et retourne la tableau des mots
   * @param input la cha\u00eene
   * @return le tableau des mots lus
   */ 
  public static String[] motsDeChaine(String input) {
    return motsDeScanner(new Scanner(input));
  }
  
  /**
   * splits a String in words
   * @param input the input
   * @return the array of words of the input
   */ 
  public static String[] wordsOfString(String input) {
    return motsDeChaine(input);
  }
  
  /**
   * Lit tout le contenu d'un fichier et retourne la tableau des mots
   * @param fileName le nom de fichier
   * @return le tableau des mots lus
   */
  public static String[] motsDeFichier(String fileName) {
    Scanner scanner;
    try {
      scanner = new Scanner(new File(fileName));
      return motsDeScanner(scanner);
    } catch (FileNotFoundException e) {
      throw new IllegalArgumentException(e.getMessage());
    }
  }
  
  /**
   * read the whole content of a file and returns read words
   * @param fileName the file name
   * @return the array of words read from the file
   */ 
  public static String[] wordsOfFile(String fileName) {
    return motsDeFichier(fileName);
  }
  
  private static String[] motsDeScanner(Scanner scanner) {
    ArrayList<String> list = new ArrayList<String>();
    scanner.useLocale(Locale.US);
    while (scanner.hasNext())
      list.add(scanner.next());
    return list.toArray(new String[list.size()]);
  }
  
  /**
   * Lit tout le contenu d'une cha\u00eene et retourne la tableau des mots sous forme de tableau
   * de caract\u00e8res. Les tableaux peuvent donc \u00eatre de longueurs distinctes.
   * @param input la cha\u00eene
   * @return le tableau des mots lus
   */ 
  public static char[][] motsTableauDeChaine(String input) {
    return motsTableauDeScanner(new Scanner(input));
  }
  
  /**
   * splits a String in words and returns them as character array
   * @param input the input
   * @return the array of words of the input
   */ 
  public static char[][] wordsAsCharArrayOfString(String input) {
    return motsTableauDeChaine(input);
  }
  
  /**
   * Lit tout le contenu d'un fichier et retourne la tableau des mots sous forme de tableau
   * de caract\u00e8res. Les tableaux peuvent donc \u00eatre de longueurs distinctes.
   * @param fileName le nom du fichier
   * @return le tableau des mots lus
   */ 
  public static char[][] motsTableauDeFichier(String fileName) {
    Scanner scanner;
    try {
      scanner = new Scanner(new File(fileName));
      return motsTableauDeScanner(scanner);
    } catch (FileNotFoundException e) {
      throw new IllegalArgumentException(e.getMessage());
    }
  }
  
  /**
   * read the whole content of a file and returns read words as character array
   * @param fileName the file name
   * @return the array of words read from the file
   */ 
  public static char[][] wordsAsCharArrayFromFile(String fileName) {
    return motsTableauDeFichier(fileName);
  }
  
  private static char[][] motsTableauDeScanner(Scanner scanner) {
    ArrayList<char[]> list = new ArrayList<char[]>();
    scanner.useLocale(Locale.US);
    while (scanner.hasNext())
      list.add(scanner.next().toCharArray());
    return list.toArray(new char[list.size()][]);
  }
  
  /**
   * Lit tout le contenu d'une cha\u00eene et retourne la tableau des lignes
   * @param input la cha\u00eene
   * @return le tableau des lignes lues
   */ 
  public static String[] lignesDeChaine(String input) {
    return lignesDeScanner(new Scanner(input));
  }
  
  /**
   * splits a String in lines
   * @param input the input
   * @return the array of lines of the input
   */ 
  public static String[] linesOfString(String input) {
    return lignesDeChaine(input);
  }

  
  /**
   * Lit tout le contenu d'un fichier et retourne la tableau des lignes
   * @param fileName le nom de fichier
   * @return le tableau des lignes lus
   */
  public static String[] lignesDeFichier(String fileName) {
    Scanner scanner;
    try {
      scanner = new Scanner(new File(fileName));
      return lignesDeScanner(scanner);
    } catch (FileNotFoundException e) {
      throw new IllegalArgumentException(e.getMessage());
    }
  }
  

  /**
   * read the whole content of a file and returns read lines
   * @param fileName the file name
   * @return the array of lines read from the file
   */ 
  public static char[][] linesFromFile(String fileName) {
    return lignesTableauDeFichier(fileName);
  }
  
  private static String[] lignesDeScanner(Scanner scanner) {
    ArrayList<String> list = new ArrayList<String>();
    scanner.useLocale(Locale.US);
    while (scanner.hasNextLine())
      list.add(scanner.nextLine());
    return list.toArray(new String[list.size()]);
  }
  
  /**
   * Lit tout le contenu d'une cha\u00eene et retourne la tableau des lignes sous forme de tableau
   * de caract\u00e8res. Les tableaux peuvent donc \u00eatre de longueurs distinctes.
   * @param input la cha\u00eene
   * @return le tableau des lignes lus
   */ 
  public static char[][] lignesTableauDeChaine(String input) {
    return lignesTableauDeScanner(new Scanner(input));
  }
  
  /**
   * splits a String in lines and returns them as character array
   * @param input the input
   * @return the array of lines of the input
   */ 
  public static char[][] linesAsCharArrayOfString(String input) {
    return lignesTableauDeChaine(input);
  }
  
  /**
   * Lit tout le contenu d'un fichier et retourne la tableau des lignes sous forme de tableau
   * de caract\u00e8res. Les tableaux peuvent donc \u00eatre de longueurs distinctes.
   * @param fileName le nom du fichier
   * @return le tableau des lignes lus
   */ 
  public static char[][] lignesTableauDeFichier(String fileName) {
    Scanner scanner;
    try {
      scanner = new Scanner(new File(fileName));
      return lignesTableauDeScanner(scanner);
    } catch (FileNotFoundException e) {
      throw new IllegalArgumentException(e.getMessage());
    }
  }

  /**
   * read the whole content of a file and returns read lines as character array
   * @param fileName the file name
   * @return the array of lines read from the file
   */ 
  public static char[][] linesAsCharArrayFromFile(String fileName) {
    return lignesTableauDeFichier(fileName);
  }
  
  private static char[][] lignesTableauDeScanner(Scanner scanner) {
    ArrayList<char[]> list = new ArrayList<char[]>();
    scanner.useLocale(Locale.US);
    while (scanner.hasNextLine())
      list.add(scanner.nextLine().toCharArray());
    return list.toArray(new char[list.size()][]);
  }
  
  
  /**
   * Retourne le contenu d'une cha\u00eene sous forme de tableau de char
   * @param input la cha\u00eene
   * @return le contenu sous forme de tableau de char
   */
  public static char[] charDeChaine(String input) {
    return input.toCharArray();
  }
  
  /**
   * Converts a java String to a char array
   * @param input the input
   * @return the characters of the input
   */
  public static char[] charFromString(String input) {
    return charDeChaine(input);
  }
  
  /**
   * Cr\u00e9e une nouvelle cha\u00eene Java \u00e0 partir d'un tableau de char
   * @param chaine le tableau
   * @return la cha\u00eene de caract\u00e8res Java
   */
  public static String stringDeTableauChar(char[] chaine) {
    return new String(chaine);
  }
  
  /**
   * Makes a new java String which characters are taken from an array.
   * @param string the array of characters
   * @return a new java String from an array of characters
   */
  public static String stringFromCharArray(char[] string) {
    return stringDeTableauChar(string);
  }
  
  private long nano=System.nanoTime();
  private long time=System.currentTimeMillis();
  
  /**
   * D\u00e9marre le chronom\u00e8tre.
   * @see #tempsChrono()
   * @see #tempsNanoChrono()
   */
  public void demarrerChrono() {
     time=System.currentTimeMillis();
     nano=System.nanoTime();
  }
  
  /**
   * Starts the stop-watch
   */
  public void startStopWatch() {
    demarrerChrono();
  }
  
  /**
   * Nombre de millisecondes \u00e9coul\u00e9es depuis le d\u00e9marrage du chronom\u00e8tre.
   * @return le nombre de millisecondes \u00e9coul\u00e9es depuis le d\u00e9marrage du chronom\u00e8tre
   */
  public long tempsChrono() {
    return System.currentTimeMillis()-time;
  }
  
  /**
   * Read elapsed milliseconds from the stop watch
   * @return milliseconds elapsed from the stop watch
   */
  public long stopWatchMilliseconds() {
    return tempsChrono();
  }

  /**
   * Nombre de nanosecondes \u00e9coul\u00e9es depuis le d\u00e9marrage du chronom\u00e8tre.
   * @return le nambre de nanosecondes \u00e9coul\u00e9es depuis le d\u00e9marrage du chronom\u00e8tre
   */
  public long tempsNanoChrono() {
    return System.nanoTime()-nano;
  }
  
  /**
   * Read elapsed microseconds from the stop watch
   * @return microseconds elapsed from the stop watch
   */
  public long stopWatchMicroseconds() {
    return tempsChrono();
  }
  
  /**
   * Pause l'ex\u00e9cution d'un nombre de millisecondes donn\u00e9es/Pauses calling process during a given number of milliseconds
   * @param millis le temps en microsecondes \u00e0 attendre/the number of milliseconds to wait
   */
  public void pause(int millis) {
    try {
      Thread.sleep(millis);
    }
    catch(InterruptedException e) {
      // nothing; 
    }
  }
}

