import java.util.*;

class G18 {

  static interface UnaryFunction<S,T> {
    T apply( S arg );
  }

  public static <T,S> List<T> map( List<S> list, 
		                   UnaryFunction<? super S, ? extends T> fun ){
    List<T> result = new ArrayList<T>(list.size());
    for( S s: list ){
      result.add( fun.apply(s) );
    }
    return result;
  }

  static interface BinaryOperator<T> {
    T apply( T arg1, T arg2 );
  }

  static class IntegerAddition implements BinaryOperator<Integer> {
    public Integer apply( Integer a, Integer b){
       return a+b;
    }
  }

  static class IntegerMaximum implements BinaryOperator<Integer> {
    public Integer apply( Integer a, Integer b){
       return a < b ? b : a;
    }
  }

  public static <T> T fold( List<T> list, T start, BinaryOperator<T> op ){
    T result = start;
    for( T t: list ){
      result = op.apply(result,t);
    }
    return result;
  }
  
  public static <T> LinkedList<T> flatten( List<List<? extends T>> listOfLists ){
    LinkedList<T> list = new LinkedList<T>();
    for( List<? extends T> aList: listOfLists ){
      list.addAll(aList);
    }
    return list;
  }
      
  public static void main( String[] args ){
    List<Integer> numbers = map( fromArrayToList(args),
                                 new UnaryFunction<String,Integer>(){
                                        public Integer apply(String s){
					  return new Integer(s);
					}
                                     }
                               );
    System.out.println(numbers);
    int sum = fold( numbers, 0, new IntegerAddition() );
    System.out.println(sum);
    System.out.println( fold(numbers, numbers.get(0), new IntegerMaximum()) );
  }
  
  public static <T> ArrayList<T> fromArrayToList( T[] a ){
    ArrayList<T> list = new ArrayList<T>(a.length);
    for( T o: a ){
      list.add(o);
    }
    return list;
  }

  public static <T,S> void map( Collection<T> dest,
                                Collection<S> src, 
		                UnaryFunction<? super S, ? extends T> fun ){
    for( S s: src ){
      dest.add( fun.apply(s) );
    }
  }

  public static <T> void flatten( Collection<T> dest,
                                  Collection<Collection<? extends T>> src ){
    for( Collection<? extends T> c: src ){
      dest.addAll(c);
    }
  }
      
}