|
- import java.util.Calendar;
- import java.util.Random;
- import java.util.Scanner;
- import java.util.concurrent.ThreadLocalRandom;
-
- class runLabs {
- public static void main(String[] args) {
- new Lab4();
- new Lab5();
- new Lab7();
- new Lab6();
- }
- }
-
- class Exercise {
- private int _exerciseNumber;
-
- public Exercise(int s) {
- this._exerciseNumber = s;
- this.printExercise();
- }
-
- public void printExercise() {
- String title = String.format("Starting exercise %s", this._exerciseNumber);
-
- System.out.println("-".repeat(title.length()));
- System.out.println(String.format("%s", title));
- System.out.println("-".repeat(title.length()));
- }
-
- public int get_exerciseNumber() {
- return _exerciseNumber;
- }
-
- public void set_exerciseNumber(int _exerciseNumber) {
- this._exerciseNumber = _exerciseNumber;
- }
- }
-
- class Lab {
- private int _labNumber;
- public Exercise currentExercise;
-
- public Lab(int lN) {
- String title = String.format("|Starting Lab %s|", lN);
- this._labNumber = lN;
-
- System.out.println("*".repeat(title.length()));
- System.out.println(title);
- System.out.println("*".repeat(title.length()));
- }
-
- public Exercise getCurrentExercise() {
- return currentExercise;
- }
-
- public void setCurrentExercise(Exercise currentSection) {
- this.currentExercise = currentSection;
- }
-
- public static void printSection(String section) {
- String title = String.format("Starting exercise %s", section);
-
- System.out.println("-".repeat(title.length()));
- System.out.println(String.format("%s", title));
- System.out.println("-".repeat(title.length()));
- }
-
- public int getLabNumber() {
- return this._labNumber;
- }
- }
-
- class Lab4 extends Lab {
- public Lab4() {
- super(4);
- ex44();
- ex46();
- }
-
- // public static void main(String[] args) {
- // }
-
- public static void ex41() {
- String labSection = "4.1";
- // System.out.println(String.format("Starting section %s", labSection));
- printSection(labSection);
-
- int testYear1 = 1996; // true
- int testYear2 = 1997; // false
- int testYear3 = 2000; // true
- int testYear4 = 9332; // true
- int testYear5 = 1900; // false
-
- int randomYear = ThreadLocalRandom.current().nextInt(1, 9999 + 1);
-
- System.out.println(String.format("Testing %s", testYear1));
- System.out.println(String.format("%s", isLeap(testYear1)));
-
- System.out.println(String.format("Testing %s", testYear2));
- System.out.println(String.format("%s", isLeap(testYear2)));
-
- System.out.println(String.format("Testing %s", testYear3));
- System.out.println(String.format("%s", isLeap(testYear3)));
-
- System.out.println(String.format("Testing %s", testYear4));
- System.out.println(String.format("%s", isLeap(testYear4)));
-
- System.out.println(String.format("Testing %s", randomYear));
- System.out.println(String.format("%s", isLeap(randomYear)));
-
- System.out.println(String.format("Testing %s", testYear5));
- }
-
- public static void ex44() {
- String labSection = "4.4";
- printSection(labSection);
-
- // System.out.println("------------------------");
- // System.out.println("Starting lab section " + labSection);
- // System.out.println("------------------------");
-
- String month1 = "oct";
- int year1 = 2000;
- System.out.println(String.format("Month: %s\tYear: %d\tDays in month: %d",
- month1, year1, monthLen(month1, year1)));
-
- String month2 = "feb";
- int year2 = 2000;
- System.out.println(String.format("Month: %s\tYear: %d\tDays in month: %d",
- month2, year2, monthLen(month2, year2)));
-
- String month3 = "feb";
- int year3 = 1997;
- System.out.println(String.format("Month: %s\tYear: %d\tDays in month: %d",
- month3, year3, monthLen(month3, year3)));
-
- String month4 = "apr";
- int year4 = 2001;
- System.out.println(String.format("Month: %s\tYear: %d\tDays in month: %d",
- month4, year4, monthLen(month4, year4)));
-
- }
-
- /**
- * Lab section 4.5
- *
- * Write a program that can calculate how many whole years old someone is from
- * today’s date and their date of birth. You could store each date as three
- * integers (day,
- * month, year)
- */
- public static void ex46() {
- String labSection = "4.6";
- printSection(labSection);
- // calculate whole years' old to date
-
- Calendar today = Calendar.getInstance();
- System.out.println("Today:\t" + today.getTime());
-
- Calendar dob1 = Calendar.getInstance();
- dob1.set(1990, 1, 1);
-
- System.out.println(String.format(
- "DOB 1:\t%s (difference:\t%d years)",
- dob1.getTime(),
- yearDifference(today, dob1)));
-
- Calendar dob2 = Calendar.getInstance();
- dob2.set(1994, 12, 22);
-
- System.out.println(String.format(
- "DOB 2:\t%s (difference:\t%d years)",
- dob2.getTime(),
- yearDifference(today, dob2)));
- }
-
- public static boolean isLeap(int year) {
- if (year % 4 != 0) {
- return false;
- } else {
- if (year % 100 == 0) {
- if (year % 400 == 0) {
- return true;
- } else {
- return false;
- }
- }
- return true;
- }
- }
-
- public static int monthLen(String month, int year) {
- if (month == "feb") {
- if (isLeap(year)) {
- return 29;
- } else {
- return 28;
- }
- } else if (
- (month == "apr") ||
- (month == "jun") ||
- (month == "sep") ||
- (month == "nov")) {
- return 30;
- } else {
- return 31;
- }
- }
-
- public static int yearDifference(Calendar date1, Calendar date2)
- {
- return (int) Math.abs(date1.get(Calendar.YEAR) -
- date2.get(Calendar.YEAR)
- );
- }
- }
-
- /**
- * Keyboard input
- */
- class Lab5 extends Lab {
- public Lab5() {
- super(5);
- new five1();
- }
-
- class five1 extends Exercise {
- /**
- * We will now look at how we can get user input from the keyboard. We will
- * gloss over some
- * of the details here, but give you just the information you need to start
- * getting input and
- * processing it.
- */
- public five1() {
- super(1);
- System.out.println(String.format("TBC"));
- // Scanner keyboard = new Scanner(System.in);
- // System.out.println("Please enter your name, followed by the return key?");
- // String userEntry = keyboard.nextLine();
- // System.out.println("Hello " + userEntry);
- // System.out.println(String.format("%s", keyboard));
- }
- }
- }
-
- /**
- * Loops
- */
- class Lab6 extends Lab {
- public Lab6() {
- super(6);
- new six1();
- System.out.println(String.format("%n"));
- new six3();
- new six6();
- new six7();
- new six8();
- new six9();
- new six5();
- }
-
- /**
- * Times tables
- */
- class six1 extends Exercise {
- public six1() {
- super(1);
- int testNum = 6;
- System.out.println(String.format("Times table for %d:", testNum));
- writeTimesTable(7);
- }
- }
-
- class six3 extends Exercise {
- public six3() {
- super(3);
- int testNum = 13; // statistically the most prime of all numbers
- System.out.println(String.format("Testing primes..."));
- System.out.println(String.format("%d prime? %s", testNum, isPrime(testNum)));
- System.out.println(String.format("%d prime? %s", 23, isPrime(23)));
- System.out.println(String.format("%d prime? %s", 27, isPrime(27)));
- System.out.println(String.format("%d prime? %s", 28, isPrime(28)));
- System.out.println(String.format("%d prime? %s", 299, isPrime(299)));
- System.out.println(String.format("Generating primes..."));
- generatePrimes(1024);
- System.out.println(String.format("Done!%n"));
- }
- }
-
- /**
- * Number guessing game
- * Random number between 0 and 99, user guesses and is told higher / lower / correct
- */
- class six5 extends Exercise {
- private Random random = new Random();
-
- public six5() {
- super(5);
- System.out.println(String.format("TODO: get stdin working to user can play"));
- numberGuessingGame();
- // System.out.println(String.format("Testing randomBetween..."));
- // int max = 100;
- // int min = 50;
- // for (int i=0; i<125; i++) {
- // System.out.printf("%d ", randomBetween(min, max));
- // }
- // System.out.println(String.format("done."));
- }
-
- public void numberGuessingGame() {
- final boolean SUPER_ADVANCED_AI = true;
- final int HIGHEST = 99;
- final int MAX_GUESSES = 10;
-
- int chosenNumber = random.nextInt(HIGHEST+1);
- int guess = random.nextInt(HIGHEST+1);
- // super advanced AI section
- int maxPossible = HIGHEST+1;
- int minPossible = 0;
-
- String guesses = "guess"; // for correct plurals
-
- System.out.printf("Guessing...\t");
- for (int i = 0; i < MAX_GUESSES; i++ ) {
- System.out.printf("%d", guess);
- if (guess == chosenNumber) {
- System.out.println(String.format("\nYou guessed right after %d %s! It was indeed %d",
- i+1, guesses, chosenNumber));
- return;
- }
- guesses = "guesses"; // didn't get it on the first try
- if (guess < chosenNumber) {
- System.out.printf("↑\t");
- if (guess > minPossible) { minPossible = guess; }
- } else {
- System.out.printf("↓\t");
- if (guess < maxPossible) {
- maxPossible = guess;
- }
- }
-
- // The better approach is to guess halfway between minPossible and maxPossible
- // but that's kinda boring and robotic
- if (SUPER_ADVANCED_AI) {
- guess = randomBetween(minPossible, maxPossible);
- }
- // TODO change the behaviour so it doesn't guess the same number in a row
- }
-
- System.out.println(String.format("\nThe answer was: %d. Better luck next time!", chosenNumber));
-
- }
-
- public int randomBetween(int min, int max) {
- if (min < 0) { min = 0; }
- if (max == 0) { return 0; }
- // System.out.printf(" random.nextInt(%d - %d) + %d ", max, min, min);
- return (random.nextInt(max - min) + min);
- }
- }
- /**
- * Produce a number triangle
- *
- * eg:
- * 1
- * 2 2
- * 3 3 3
- * 4 4 4 4
- */
- class six6 extends Exercise {
- public six6() {
- super(6);
- numberTriangle(1);
- numberTriangle(4);
- numberTriangle(8);
- numberTriangle(29);
- }
- }
-
- class six7 extends Exercise {
- public six7() {
- super(7);
- describeDD(4.2, 1.6);
- describeDD(47.42, 7.9);
- }
-
- /** Simple exposition of double division
- * @param num1 Dividend
- * @param num2 Divisor
- */
- public void describeDD(double num1, double num2) {
- System.out.println(String.format("Double division of %.2f by %.2f:\t", num1, num2));
- DoubleDivisionResult result = doubleDivision(num1, num2);
- System.out.println(String.format("Quotient: %d (ie %.2f ✕ %d = %.2f)\tRemainder: %.2f",
- result.getQuotient(),
- num2,
- result.getQuotient(),
- (num2 * result.getQuotient()),
- result.getRemainder()));
- }
- }
-
- /**
- * Exercise 8 - String pad with specified character
- */
- class six8 extends Exercise {
- public six8() {
- super(8);
- describeStringPadding("NoNeed", 4, '!');
- describeStringPadding("Simon", 10, '@');
- describeStringPadding("Zaphod Beeblebrox", 42, '?');
- // describeStringPadding("Unicode", 10, '🤯'); aww
- }
-
- /**
- * Print for display what we're padding and the result
- *
- * @param toPad The string to pad eg "Simon"
- * @param length Desired length
- * @param padChar Character to pad with
- */
- public void describeStringPadding(String toPad, int paddedLength, char padChar) {
- System.out.println(String.format("Padding '%s' to length %d using padding character: %s",
- toPad, paddedLength, padChar));
- System.out.println(stringLPad(toPad, paddedLength, padChar));
- }
-
- /**
- * (Left-)pad a string with the specific character
- *
- * @param toPad The string to pad eg "Simon"
- * @param length Desired length
- * @param padChar Character to pad with
- * @return The padded result
- */
- public static String stringLPad(String toPad, int paddedLength, char padChar) {
- // early out - return unmodified
- if (toPad.length() >= paddedLength) {
- return toPad;
- }
- // note that we could do this with String.repeat(), but since this is in the 'Loops'
- // part of the lab, we should probably do this with a loop
- // String paddedString = String.valueOf(padChar) + toPad;
- String paddedString = toPad;
- while (paddedString.length() < paddedLength) {
- paddedString = String.valueOf(padChar) + paddedString;
- }
- return paddedString;
- }
-
- }
-
- class six9 extends Exercise {
- private Random random = new Random(); // initialise once
- // see https://stackoverflow.com/a/35277291, to pick a random member of an enum, first convert it to an array
- private Throw[] throwsArray = Throw.values(); // can't call it 'throws' for obvious reasons
-
- final Throw randomThrow() {
- return throwsArray[random.nextInt(throwsArray.length)];
- }
-
- public six9() {
- super(9);
- System.out.println(String.format("TODO: Take input when we have stdin working"));
- Throw player1 = Throw.ROCK; // "Good ol' rock, nothing beats that"
- Throw player2 = randomThrow();
- playRockPaperScissors(player1, player2);
- player2 = randomThrow();
- playRockPaperScissors(player1, player2);
- player2 = randomThrow();
- playRockPaperScissors(player1, player2);
- }
- }
-
- public void playRockPaperScissors (Throw player1, Throw player2) {
- // slight semantic overload with throwing an error but I think that's the term
- // for plays in RPS
- String result;
- // early out - TOASK why this doesn't work when it works in a REPL!!
- if (player1 == player2) {
- result = "a draw";
- } else {
- switch (player1) {
- case ROCK:
- if (player2 == Throw.SCISSORS) { result = "R>S Player 1 wins"; }
- else { result = "R<P Player 2 wins"; } // must be paper
- break;
- case PAPER:
- if (player2 == Throw.SCISSORS) { result = "P<S Player 2 wins"; }
- else { result = "P>R Player 1 wins"; } // must be rock
- break;
- case SCISSORS:
- if (player2 == Throw.ROCK) { result = "S<R Player 2 wins"; }
- else { result = "S>P Player 1 wins"; } // must be paper
- break;
- default:
- result = "undefined behaviour";
- break;
- }
- }
- writeRPSPlay(player1, player2, result);
- }
-
- public String getThrowName(Throw thrown) {
- // This could probably be done in the enum itself
- switch (thrown) {
- case ROCK: return six8.stringLPad("rock", 8, ' '); // pad to 'scissors' length so everything stays lined-up
- case PAPER: return six8.stringLPad("paper", 8, ' ');
- case SCISSORS: return "scissors";
- default: return "uh?";
- }
- }
-
- public void writeRPSPlay (Throw player1, Throw player2, String result) {
- System.out.printf("Player 1 throws... %s\t\t", getThrowName(player1));
- System.out.printf("Player 2 throws... %s\t\t", getThrowName(player2));
- System.out.println(String.format("The result is...\t%s", result));
- }
-
- enum Throw {
- ROCK,
- PAPER,
- SCISSORS
- }
-
- /* TOASK - is there a better way of returning multiple values in Java?
- à la python, ie: return (quotient, remainder)
- */
-
- /**
- * Wrapper class for returning results from double division
- */
- final class DoubleDivisionResult {
- private int quotient; // that's the number of times something goes into something else
- private double remainder; // that's the bit left over
-
- public DoubleDivisionResult(int quotient, double remainder) {
- this.quotient = quotient;
- this.remainder = remainder;
- }
-
- public int getQuotient() {
- return quotient;
- }
-
- public double getRemainder() {
- return remainder;
- }
-
- }
-
- /**
- * Perform 'double division'
- *
- * @param dividend Number to be divided
- * @param divisor Number to divide by
- * @return a {@link DoubleDivisionResult} with the (int) quotient and (double) remainder
- */
- public DoubleDivisionResult doubleDivision(double dividend, double divisor) {
- // example used is 4.2 and 1.6
- // should return 2 and 1.0
- final boolean DEBUG = false;
- double dQuotient = dividend / divisor;
- int iQuotient = (int)dQuotient;
-
- double remainder = dividend - (iQuotient * divisor);
-
- if (DEBUG) {
- System.out.println(String.format("float quotient: %.2f", dQuotient));
- System.out.println(String.format("int quotient: %d", iQuotient));
- // TOASK: is there a neater way to do this casting?
- }
-
- return new DoubleDivisionResult(iQuotient, remainder);
- }
-
- /**
- * @param num Size of triangle
- */
- public void numberTriangle(int num) {
- /* Observations:
- - for even-sized triangles, preceding number of spaces starts at n=rows and decrements
- - for even-sized triangles even numbers have odd spaces and vice versa
-
- TODO: handle multi-digit numbers
- */
- System.out.println(String.format(""));
- int spaces = num;
- for (int i = 1; i <= num; i++) {
- System.out.println(" ".repeat(spaces)
- + String.format("%s ", i).repeat(i)
- + " ".repeat(spaces-1)
- );
- spaces--;
- }
- System.out.println(String.format(""));
- }
-
- /**
- * @param num The number to write the times table for
- * @param limit How many multiples to show
- */
- public void writeTimesTable(int num, int limit) {
- for (int i = 0; i < (limit + 1); i++) {
- System.out.printf("%d\t", num * i);
- }
- }
-
- /* TOASK - overload example.
- Question: is there a better way of doing optional function parameters in java?
- */
- /**
- * Write times table for num (10 entries)
- * @param num Number to show times table for
- */
- public void writeTimesTable(int num) {
- int DEFAULT_LIMIT = 10;
- writeTimesTable(num, DEFAULT_LIMIT);
- }
-
- public void generatePrimes(int upperLimit) {
- // handle 2 as a special case
- System.out.println(String.format("2"));
- // for (int i = 3; i <= upperLimit; i += 2) {
- for (int i = 2; i <= upperLimit; i++) {
- // TODO: figure out smarter way of doing this, I'm sure primes must be at least 6 apart...
- // Something about 2n ± 1 ?
- // seive of Erasthotenes ..?
- if (isPrime(i)) {
- System.out.printf("%d\t", i);
- }
- }
- }
-
- /**
- * But is it prime?
- * @param num Integer to test for primality
- * @return if it's prime
- */
- public boolean isPrime(int num) {
- boolean DEBUG = false;
- if ((num == 2) || (num == 1)) {
- return true;
- }
- if (num % 2 == 0){
- return false;
- } else {
- int divisor = 3;
- double numSquareRoot = Math.sqrt((double)num);
- while (divisor <= numSquareRoot) {
- if (num % divisor == 0) {
- return false;
- }
- divisor += 2;
- if (DEBUG) {
- System.out.printf("%d\t", divisor);
- }
- }
- return true;
- }
- }
- }
-
- /**
- * String formatting
- *
- */
- class Lab7 extends Lab {
- public Lab7() {
- super(7);
- writeTimesTable(8.24579, 10);
- writeTimesTable(93.12279, 22);
- writeTimesTable(193.12279, 22);
- writeTimesTable(13.9, 122);
- }
-
- /**
- * @param num The number to write the times table for (0 <= num <= 99)
- * @param limit How many multiples to show (0 <= limit <= 99)
- */
- public void writeTimesTable(double num, int limit) {
- final double MINNUM = 0;
- final double MAXNUM = 99;
- final int MINLIMIT = 0;
- final int MAXLIMIT = 99;
-
- if ((num < MINNUM) || (num > MAXNUM)) {
- System.err.println(String.format("Please specify a number between %.2f and %.2f (supplied: %.2f)",
- MINNUM, MAXNUM, num));
- return;
- }
-
- if ((limit < MINLIMIT) || (limit > MAXLIMIT)) {
- System.err.println(String.format("Please specify a limit between %d and %d (supplied: %d)",
- MINLIMIT, MAXLIMIT, limit));
- return;
- }
- for (int i = 0; i < (limit + 1); i++) {
- // output specification:
- // ~~.~~~ x ~~ = ~~~~~.~~~
- System.out.printf("%2.3f x %02d = %5.3f%n", num, i, (num*i));
- }
- }
- }
|