/////////////////////////////////////////////////////////////////////////
// File: numavg.java

abstract class ALon{
  int num;

  // count number of items in this list
  abstract int count();

  // compute the sum of all items in this list
  abstract int sum();

  // count the number of items in this list, using an accumulator
  // the initial value of the accumulator should be zero
  abstract int accuCount(int aCount);

  // compute the sum of all items inthis llist, using an accumulator
  // the initial value of the accumulator should be zero
  abstract int accuSum(int aSum);

  // compute the average of the numbers in this list
  int avg() {
    return this.sum() / this.count();
  }

  // compute the average of the numbers in this list, using two accumulators
  // one accumulator for the count, and one for the sum of all numbers seen
  // initial values for both accumulators are zero
  abstract int accuAvg(int aCount, int aSum);

}


class OneLon extends ALon{

  OneLon(int n){
    this.num = n;
  }

// Template:
// ...this.num...
// ...this.count()...
// ...this.sum()...
// ...this.accuCount(int aCount)...
// ...this.accuSum(int aSum)...
// ...this.avg()...
// ...this.accuAvg(intaCount, int aSum)...


  int count(){
    return 1;
  }

  int sum(){
    return num;
  }

  // aCount is the total count of items encountered so far - add one to that count
  int accuCount(int aCount){
    return 1 + aCount;
  }

  // aSum is the total sum of items encountered so far - add this num to that sum
  int accuSum(int aSum){
    return this.num + aSum;
  }

  // aCount is the total count of items encountered so far - add one to that count
  // aSum is the total sum of items encountered so far - add this num to that sum
  int accuAvg(int aCount, int aSum){
    return (this.num + aSum) / (1 + aCount);
  }
}

class ConsLon extends ALon {
  ALon rst;

  ConsLon(int n, ALon lst){
    this.num = n;
    this.rst = lst;
  }

// Template:
// ...this.num...
// ...this.rst...
// ...this.count()...
// ...this.rst.count()...
// ...this.sum()...
// ...this.rst.sum()...
// ...this.accuCount(int aCount)...
// ...this.rst.accuCount(int aCount)...
// ...this.accuSum(int aSum)...
// ...this.rst.accuSum(int aSum)...
// ...this.avg()...
// ...this.rst.avg()...
// ...this.accuAvg(intaCount, int aSum)...
// ...this.rst.accuAvg(intaCount, int aSum)...


  int count(){
    return 1 + this.rst.count();
  }

  int sum() {
    return this.num + this.rst.sum();
  }

  // aCount is the total count of items encountered so far:
  // recur, with accumulator value one larger thatn the previous count
  int accuCount(int aCount){
    return this.rst.accuCount(1 + aCount);
  }

  // aSum is the total sum of items encountered so far
  // recur with accumulator value computed by adding this num to the previous sum
  int accuSum(int aSum){
    return this.rst.accuSum(this.num + aSum);
  }

  // aCount is the total count of items encountered so far - add one to that count
  // aSum is the total sum of items encountered so far - add this num to that sum
  // recur with the two new accumulator values
  int accuAvg(int aCount, int aSum){
    return this.rst.accuAvg(1 + aCount, this.num + aSum);
  }

}

//  ALon l1 = new OneLon(3);

//  ALon l2 = new ConsLon(4, new ConsLon(5, new OneLon(6)));

//  ALon l3 = new ConsLon(3, l1);


// "Testing the method count in classes OneLon and ConsLon"


// l1.count() == 1

// l2.count() == 3

// l3.count() == 2


// "Testing the method sum in classes OneLon and ConsLon"


// l1.sum() == 3

// l2.sum() == 15

// l3.sum() == 6



// "Testing the method accuCount in classes OneLon and ConsLon"


// l1.accuCount(0) == 1

// l2.accuCount(0) == 3

// l3.accuCount(0) == 2


// "Testing the method accuSum in classes OneLon and ConsLon"


// l1.accuSum(0) == 3

// l2.accuSum(0) == 15

// l3.accuSum(0) == 6


// "Testing the method avg in classes OneLon and ConsLon"


// l1.avg() == 3

// l2.avg() == 5

// l3.avg() == 3


// "Testing the method accuAvg in classes OneLon and ConsLon"


// l1.accuAvg(0, 0) == 3

// l2.accuAvg(0, 0) == 5

// l3.accuAvg(0, 0) == 3


