class R1 {

// helper functions to display arrays

    // print contents of $x$, each number padded to fill 4 columns
    public static void showints(int[] x) {
        int i = 0;
        while (i < x.length) {
            String s = "" + x[i];
            while (s.length() < 4) {
                s = " " + s;
            }
            System.out.print(s);
            i += 1;
        }
        System.out.println();
    }

    // print contents of $x$
    public static void showdoubles(double[] x) {
        int i = 0;
        while (i < x.length) {
            System.out.print(" " + x[i]);
            i += 1;
        }
        System.out.println();
    }
    
// run code below on sample data

    public static void main(String[] args) {
        String s = "this is the string whose vowels should be replaced";
        System.out.println(s);
/*R1.1*/System.out.println(star(s));
/*R1.2*/System.out.println(dupvowels(s));
/*R1.3*/int[] tosort = new int[] { 6, 0, -3, -5, 4, 5, 1, -9, 0, 3 };
        int[][] sort = sortbysign(tosort);
        System.out.print("tosort = "); showints(tosort);
        System.out.print("pos    = "); showints(sort[0]);
        System.out.print("zero   = "); showints(sort[1]);
        System.out.print("neg    = "); showints(sort[2]);
/*R1.4*/double[] toave = new double[] { 6, 0, -3, -5, 4, 5, 1, -9, 0, 3 };
        double[] ave = aveneighbor(toave);
        System.out.print("toave = "); showdoubles(toave);
        System.out.print("ave   = "); showdoubles(ave);
/*R1.5*/calendar();
/*R1.6 see links for P6 on Projects website*/
/*R1.7*/double degrees = 67;
        System.out.println("cos(" + degrees + ") = " 
                            + Math.cos(degrees * Math.PI/180));
        System.out.println("approximation = " +cosine(degrees, 100));
/*R1.8*/showints(rand2(10));
/*R1.9*/int N = 100;
        System.out.println(N + " drunken steps moved distance " + drunk(N));
    }

// R1.1

    // given string $s$ in lower case, 
    // return string with vowels replaced with $'*'$s
    public static String star(String s) {
        char[] c = s.toCharArray();
        int i = 0;
        while (i < c.length) {
            if (c[i]=='a' | c[i]=='e' | c[i]=='i' | c[i]=='o' | c[i]=='u') {
                c[i] = '*';
            }
            i += 1;
        }
        return new String(c);

    /* matlab:
        i = 1; c = s;
        while i <= length(c)
            if any(c(i) == 'aeiou')
                c(i) = '*';
            end
        end
    */
    }
    
// R1.2
    // given string $s$ in lower case, return string with each vowel duplicated
    public static String dupvowels(String s) {
        String out = "";
        char[] c = s.toCharArray();
        int i = 0;
        while (i < c.length) {
            out += c[i];
            if (c[i]=='a' | c[i]=='e' | c[i]=='i' | c[i]=='o' | c[i]=='u') {
                out += c[i];
            }
            i += 1;
        }
        return new String(out);

    /* matlab:
        out = '';
        i = 1; c = s;
        while i <= length(c)
            out = [out c(i)];
            if any(c(i) == 'aeiou')
                out = [out c(i)];
            end
        end
    */
    }
// R1.3
    // given integer array, return 2D array whose 3 rows are, respectively:
    // all positive elements, all zero elements, all negative elements --
    // relative order is preserved
    public static int[][] sortbysign(int[] in) {
        // count number of each
            int npos = 0; // number of positive elements seen so far
            int nneg = 0; // number of negative elements seen so far
            int nzero = 0; // number of zero elements seen so far
            int i = 0; // number of elements seen so far
            // inv: maintain variable definitions above
            while (i < in.length) {
                if (in[i] > 0) {
                    npos += 1;
                } else if (in[i] < 0) {
                    nneg += 1;
                } else {
                    nzero += 1;
                }
                i += 1;
            }
        int[][] each = 
                new int[][] { new int[npos], new int[nzero], new int[nneg] };
        // move negative and positive elements into correct place in $each$.
        // inv: $nzero-1$ is next free spot for negative numbers,
        //      $npos-1$ is next free spot for positive numbers,
        //      $in[0..i-1]$ hold remaining elements to process
        while (i > 0) {
            i -= 1;
            if (in[i] > 0) {
                npos -= 1;
                each[0][npos] = in[i];
            } else if (in[i] < 0) {
                nneg -= 1;
                each[2][nneg] = in[i];
            }       
        }
        return each;
    }
// R1.4
    // given array of numbers, return array with each number replaced by
    // the average of its neighbors; the first and last elements are neighbors
    public static double[] aveneighbor(double[] x) {
        int n = x.length;
        double[] ave = new double[n];
        int i = 0;
        while (i < n) {
            int next = (i+1) % n;
            int prev = (i+n-1) % n;
            ave[i] = (x[prev] + x[next]) / 2.0;
            i += 1;
        }
        return ave;
        /* matlab:
            n = length(x);
            ave = zeros(1,n);
            i = 1;
            while i <= n
                next = rem(i,n) + 1;
                prev = rem(i+n-1,n) + 1;
                ave(i) = (x(prev) + x(next))/2;
                i = i+1;
            end
        */
    }
// R1.5
    // print dates 1/1 .. 12/31
    public static void calendar() {
        // $days[i]$ = number of days in $i$-th month, $i=1..12$
            int[] days = 
              new int[] { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
        int month = 0;
        while (month < 12) {
            month += 1;
            int day = 0;
            while (day < days[month]) {
                day += 1;
                System.out.print(month + "/" + day + " ");
            }
            System.out.println();
        }
        /* matlab:

            days = [31 28 31 30 31 30 31 31 30 31 30 31];
            for month = 1:12
                for day = 1:days(month)
                    fprintf('%d/%d ', month, day);
                end
                fprintf('\n');
            end
        */
    }
// R1.6 see links for P6 on Projects website
// R1.7
    // return series approximation to cosine for angle of $degrees$ degrees
    // using $terms$ terms in taylor series
    public static double cosine(double degrees, int terms) {
        double radians = degrees * Math.PI / 180;
        double total = 0.0; // sum so far of terms
        int i = 0; // number of terms summed in $total$ so far
        int minus1 = 1; // $(-1) ** i$
        double r2i = 1.0; // $radians ** (2*i)$
        double fact = 1.0; // $factorial(2*i)$
        // inv: maintain variable definitions above
        while (i < terms) {
            total += minus1 * r2i / fact;
            minus1 = -minus1;
            r2i *= radians*radians;
            fact *= (2*i+1) * (2*i+2);
            i += 1;
        }
        return total;
    /* matlab:

        radians = pi * d / 180; % angle in radians
        total = 0; % approximation so far
        for i = 0 : terms-1
            total = total + (-1)^i*r^(2*i)/factorial(2*i);
        end
    */
    }
// R1.8
    // return $N$ random integers in the range $[-2,2]$
    public static int[] rand2(int N) {
        int[] x = new int[N];
        int i = 0;
        while (i < N) {
            x[i] = (int) (Math.floor(5 * Math.random() - 2));
            i += 1;
        }
        return x;
    /* matlab:

        x = zeros(1,N);
        for i = 1:N
            x(i) = floor(5*rand)-2;
        end
    */
    }
// R1.9
    // return distance from start after $N$ drunken steps
    public static double drunk(int N) {
        int[] count = new int[4]; // # of steps north, south, east, west
        while (N > 0) {
            count[(int) (Math.random()*4)] += 1;
            N = N-1;
        }
        int y = count[0] - count[1];
        int x = count[2] - count[3];
        return Math.sqrt(x*x + y*y);
    /* matlab:

        count = [0 0 0 0]; % number of steps north, south, east, west
        while N > 0
            dir = ceil(4*rand); % generate random direction
            count(dir) = 1+count(dir); % update #steps in direction $dir$
            N = N-1;
        end
        y = count(1) - count(2);
        x = count(3) - count(4);
        distance = sqrt(x*x + y*y);
    */
    }
}