// Week 1 – Solutions of the practice exercises
// Run: java Exercises01.java
public class Exercises01 {

    // E1. How many bits are needed to store an integer n >= 0?
    static int bitsNeeded(long n) {
        int bits = 1;
        while (n > 1) {
            n = n / 2;
            bits++;
        }
        return bits;
    }

    // E2. The binary form of a number (repeated division by 2).
    static String toBinary(int n) {
        if (n == 0) return "0";
        String result = "";
        while (n > 0) {
            result = (n % 2) + result;
            n = n / 2;
        }
        return result;
    }

    // E3. Lower case -> upper case using the character code ('a' - 'A' == 32).
    static char toUpper(char c) {
        if (c >= 'a' && c <= 'z') {
            return (char) (c - ('a' - 'A'));
        }
        return c;
    }

    // E4. Equality of two real numbers with a tolerance.
    static boolean almostEqual(double x, double y) {
        return Math.abs(x - y) < 1e-9;
    }

    // E5. Printing a truth table.
    static void truthTable() {
        System.out.println("  a      b      a&&b   a||b   !a     a^b");
        boolean[] values = { false, true };
        for (boolean a : values) {
            for (boolean b : values) {
                System.out.printf("  %-6b %-6b %-6b %-6b %-6b %-6b%n", a, b, a && b, a || b, !a, a ^ b);
            }
        }
    }

    // E6. Detecting overflow before adding.
    static boolean addWouldOverflow(int x, int y) {
        if (y > 0) return x > Integer.MAX_VALUE - y;
        if (y < 0) return x < Integer.MIN_VALUE - y;
        return false;
    }

    public static void main(String[] args) {
        System.out.println("E1. bitsNeeded(255) = " + bitsNeeded(255) + ", bitsNeeded(256) = " + bitsNeeded(256));
        System.out.println("E2. toBinary(50) = " + toBinary(50) + "  (check: " + Integer.toBinaryString(50) + ")");
        System.out.println("E3. toUpper('g') = " + toUpper('g') + ", toUpper('7') = " + toUpper('7'));
        System.out.println("E4. almostEqual(0.1+0.2, 0.3) = " + almostEqual(0.1 + 0.2, 0.3));
        System.out.println("E5.");
        truthTable();
        System.out.println("E6. MAX_VALUE + 1 overflows? " + addWouldOverflow(Integer.MAX_VALUE, 1));
        System.out.println("    1000 + 2000 overflows?    " + addWouldOverflow(1000, 2000));
    }
}
