Exercises from labs 2023-2024
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

923 lines
31 KiB

  1. import java.util.Calendar;
  2. import java.util.Random;
  3. import java.util.Scanner;
  4. import java.util.concurrent.ThreadLocalRandom;
  5. class runLabs {
  6. public static void main(String[] args) {
  7. // new Lab4();
  8. // new Lab5();
  9. new Lab6();
  10. // new Lab7();
  11. }
  12. }
  13. class Exercise {
  14. private int _exerciseNumber;
  15. public Exercise(int s) {
  16. this._exerciseNumber = s;
  17. this.printExercise();
  18. }
  19. public void printExercise() {
  20. String title = String.format("Starting exercise %s", this._exerciseNumber);
  21. System.out.println("-".repeat(title.length()));
  22. System.out.println(String.format("%s", title));
  23. System.out.println("-".repeat(title.length()));
  24. }
  25. public int get_exerciseNumber() {
  26. return _exerciseNumber;
  27. }
  28. public void set_exerciseNumber(int _exerciseNumber) {
  29. this._exerciseNumber = _exerciseNumber;
  30. }
  31. }
  32. class Lab {
  33. private int _labNumber;
  34. public Exercise currentExercise;
  35. public Lab(int lN) {
  36. String title = String.format("|Starting Lab %s|", lN);
  37. this._labNumber = lN;
  38. System.out.println("*".repeat(title.length()));
  39. System.out.println(title);
  40. System.out.println("*".repeat(title.length()));
  41. }
  42. public Exercise getCurrentExercise() {
  43. return currentExercise;
  44. }
  45. public void setCurrentExercise(Exercise currentSection) {
  46. this.currentExercise = currentSection;
  47. }
  48. public static void printSection(String section) {
  49. String title = String.format("Starting exercise %s", section);
  50. System.out.println("-".repeat(title.length()));
  51. System.out.println(String.format("%s", title));
  52. System.out.println("-".repeat(title.length()));
  53. }
  54. public int getLabNumber() {
  55. return this._labNumber;
  56. }
  57. }
  58. class Lab4 extends Lab {
  59. public Lab4() {
  60. super(4);
  61. // ex44();
  62. ex46();
  63. }
  64. // public static void main(String[] args) {
  65. // }
  66. public static void ex41() {
  67. String labSection = "4.1";
  68. // System.out.println(String.format("Starting section %s", labSection));
  69. printSection(labSection);
  70. int testYear1 = 1996; // true
  71. int testYear2 = 1997; // false
  72. int testYear3 = 2000; // true
  73. int testYear4 = 9332; // true
  74. int testYear5 = 1900; // false
  75. int randomYear = ThreadLocalRandom.current().nextInt(1, 9999 + 1);
  76. System.out.println(String.format("Testing %s", testYear1));
  77. System.out.println(String.format("%s", isLeap(testYear1)));
  78. System.out.println(String.format("Testing %s", testYear2));
  79. System.out.println(String.format("%s", isLeap(testYear2)));
  80. System.out.println(String.format("Testing %s", testYear3));
  81. System.out.println(String.format("%s", isLeap(testYear3)));
  82. System.out.println(String.format("Testing %s", testYear4));
  83. System.out.println(String.format("%s", isLeap(testYear4)));
  84. System.out.println(String.format("Testing %s", randomYear));
  85. System.out.println(String.format("%s", isLeap(randomYear)));
  86. System.out.println(String.format("Testing %s", testYear5));
  87. }
  88. public static void ex44() {
  89. String labSection = "4.4";
  90. printSection(labSection);
  91. // System.out.println("------------------------");
  92. // System.out.println("Starting lab section " + labSection);
  93. // System.out.println("------------------------");
  94. String month1 = "oct";
  95. int year1 = 2000;
  96. System.out.println(String.format("Month: %s\tYear: %d\tDays in month: %d",
  97. month1, year1, monthLen(month1, year1)));
  98. String month2 = "feb";
  99. int year2 = 2000;
  100. System.out.println(String.format("Month: %s\tYear: %d\tDays in month: %d",
  101. month2, year2, monthLen(month2, year2)));
  102. String month3 = "feb";
  103. int year3 = 1997;
  104. System.out.println(String.format("Month: %s\tYear: %d\tDays in month: %d",
  105. month3, year3, monthLen(month3, year3)));
  106. String month4 = "apr";
  107. int year4 = 2001;
  108. System.out.println(String.format("Month: %s\tYear: %d\tDays in month: %d",
  109. month4, year4, monthLen(month4, year4)));
  110. }
  111. /**
  112. * Lab section 4.5
  113. *
  114. * Write a program that can calculate how many whole years old someone is from
  115. * today’s date and their date of birth. You could store each date as three
  116. * integers (day, month, year)
  117. */
  118. public static void ex46() {
  119. String labSection = "4.6";
  120. printSection(labSection);
  121. // calculate whole years' old to date
  122. Calendar today = Calendar.getInstance();
  123. System.out.println("Today:\t" + today.getTime());
  124. Calendar dob1 = Calendar.getInstance();
  125. dob1.set(1990, 1, 1);
  126. System.out.println(String.format(
  127. "DOB 1:\t%s (difference:\t%d years)",
  128. dob1.getTime(),
  129. yearsOld(today, dob1)));
  130. Calendar dob2 = Calendar.getInstance();
  131. dob2.set(1994, 11, 22);
  132. System.out.println(String.format(
  133. "DOB 2:\t%s (difference:\t%d years)",
  134. dob2.getTime(),
  135. yearsOld(today, dob2)));
  136. Calendar dob3 = Calendar.getInstance();
  137. dob3.set(2000, 8, 19); // 23 years old
  138. System.out.println(String.format(
  139. "DOB 3:\t%s (difference:\t%d years)",
  140. dob3.getTime(),
  141. yearsOld(today, dob3)));
  142. Calendar dob4 = Calendar.getInstance();
  143. dob4.set(2000, 8, 20); // 23 years old
  144. System.out.println(String.format(
  145. "DOB 4:\t%s (difference:\t%d years)",
  146. dob4.getTime(),
  147. yearsOld(today, dob4)));
  148. Calendar dob5 = Calendar.getInstance();
  149. dob5.set(2000, 8, 21); // 22 years old
  150. System.out.println(String.format(
  151. "DOB 5:\t%s (difference:\t%d years)",
  152. dob5.getTime(),
  153. yearsOld(today, dob5)));
  154. }
  155. public static boolean isLeap(int year) {
  156. if (year % 4 != 0) {
  157. return false;
  158. } else {
  159. if (year % 100 == 0) {
  160. if (year % 400 == 0) {
  161. return true;
  162. } else {
  163. return false;
  164. }
  165. }
  166. return true;
  167. }
  168. }
  169. public static int monthLen(String month, int year) {
  170. if (month == "feb") {
  171. if (isLeap(year)) {
  172. return 29;
  173. } else {
  174. return 28;
  175. }
  176. } else if (
  177. (month == "apr") ||
  178. (month == "jun") ||
  179. (month == "sep") ||
  180. (month == "nov")) {
  181. return 30;
  182. } else {
  183. return 31;
  184. }
  185. }
  186. public static int yearsOld(Calendar laterDate, Calendar earlierDate)
  187. {
  188. int birthdayModifier = 0; // we assume they've had their birthday
  189. // we could probably do this with one if, checking DAY_OF_YEARs,
  190. // but since problem spec mentioned months and days we should really
  191. // pay attention to those
  192. if (earlierDate.get(Calendar.MONTH) > laterDate.get(Calendar.MONTH)) {
  193. // ie 8 (August) < 9 (September)
  194. birthdayModifier = -1; // not had their birthday yet so take 1 year off difference
  195. } else if (earlierDate.get(Calendar.MONTH) == laterDate.get(Calendar.MONTH)) {
  196. if (earlierDate.get(Calendar.DAY_OF_MONTH) > laterDate.get(Calendar.DAY_OF_MONTH)) {
  197. birthdayModifier = -1;
  198. }
  199. }
  200. return (int) Math.abs(laterDate.get(Calendar.YEAR) -
  201. earlierDate.get(Calendar.YEAR) +
  202. birthdayModifier
  203. );
  204. }
  205. }
  206. /**
  207. * Keyboard input
  208. */
  209. class Lab5 extends Lab {
  210. public Lab5() {
  211. super(5);
  212. // new five1();
  213. // new five5();
  214. // new five6();
  215. new five7();
  216. }
  217. class five1 extends Exercise {
  218. /**
  219. * We will now look at how we can get user input from the keyboard. We will
  220. * gloss over some
  221. * of the details here, but give you just the information you need to start
  222. * getting input and
  223. * processing it.
  224. */
  225. public five1() {
  226. super(1);
  227. Scanner keyboard = new Scanner(System.in);
  228. System.out.println("Please enter your name, followed by the return key?");
  229. String userEntry = keyboard.nextLine();
  230. System.out.println("Hello " + userEntry);
  231. System.out.println(String.format("%s", keyboard));
  232. System.out.println("Please enter your age");
  233. int userAge = keyboard.nextInt();
  234. // keyboard.nextLine();
  235. System.out.println("You are " + userAge + " years old");
  236. System.out.println("What is your favourite colour?");
  237. String col = keyboard.nextLine();
  238. }
  239. }
  240. /**
  241. * Prompt for input and summarise a circle
  242. *
  243. */
  244. class five5 extends Exercise {
  245. public five5() {
  246. super(5);
  247. userCircles();
  248. }
  249. public void userCircles() {
  250. Scanner kbIn = new Scanner(System.in);
  251. System.out.println(String.format("Please supply a radius, that I might describe you a circle"));
  252. double radius = kbIn.nextDouble();
  253. kbIn.nextLine();
  254. summariseCircle(radius);
  255. kbIn.close();
  256. }
  257. public void summariseCircle(double radius) {
  258. System.out.println(String.format("A circle with radius %.2f has circumference %.2f and radius %.2f",
  259. radius, compCircumference(radius), compArea(radius)));
  260. }
  261. public double compCircumference(double radius) {
  262. return (2 * Math.PI * radius);
  263. }
  264. public double compArea(double radius) {
  265. return (Math.PI * Math.pow(radius, 2));
  266. }
  267. }
  268. /**
  269. * {@link Scanner} understanding - actually process input
  270. *
  271. */
  272. class five6 extends Exercise {
  273. public five6() {
  274. super(6);
  275. getNameAndAge();
  276. }
  277. public void getNameAndAge() {
  278. String userName;
  279. int userAge;
  280. Scanner kbIn = new Scanner(System.in);
  281. System.out.println(String.format("Please enter your name and age separated by a space"));
  282. String userInput = kbIn.nextLine();
  283. Scanner inputOps = new Scanner(userInput);
  284. userName = inputOps.next();
  285. // TOASK -- is this what 'add an extra line that fixes this problem' was going for?
  286. while (!inputOps.hasNextInt()) {
  287. userName += " " + inputOps.next();
  288. }
  289. if (inputOps.hasNextInt()) {
  290. userAge = inputOps.nextInt();
  291. } else {
  292. userAge = 0;
  293. }
  294. System.out.println(String.format("Your name is %s and your age is %d",
  295. userName, userAge));
  296. kbIn.close();
  297. inputOps.close();
  298. }
  299. }
  300. /**
  301. * Get DOB from user input and calculate age using {@link Lab4.ex46()}
  302. *
  303. */
  304. class five7 extends Exercise {
  305. public five7() {
  306. super(7);
  307. showUserAge();
  308. }
  309. public void showUserAge() {
  310. Scanner userInput = new Scanner(System.in);
  311. System.out.println(String.format("Please input your DOB"));
  312. System.out.println(String.format("input format is YYYY M D"));
  313. String inputString = userInput.nextLine();
  314. Scanner processInput = new Scanner(inputString);
  315. int dobYear = processInput.nextInt();
  316. int dobMonth = processInput.nextInt();
  317. int dobDay = processInput.nextInt();
  318. // input sanitisation could be nice...
  319. Calendar userDOB = Calendar.getInstance();
  320. // recall months are zero-indexed!
  321. userDOB.set(dobYear, dobMonth-1, dobDay);
  322. Calendar today = Calendar.getInstance();
  323. System.out.println(String.format("Today:\t%s", today.getTime()));
  324. System.out.println(String.format(
  325. "DOB :\t%s (difference: %d years)",
  326. userDOB.getTime(),
  327. Lab4.yearsOld(today, userDOB)));
  328. userInput.close();
  329. processInput.close();
  330. }
  331. }
  332. }
  333. /**
  334. * Loops
  335. */
  336. class Lab6 extends Lab {
  337. public Lab6() {
  338. super(6);
  339. new six1();
  340. System.out.println(String.format("%n"));
  341. new six3();
  342. new six6();
  343. new six7();
  344. new six8();
  345. new six9();
  346. // new six5();
  347. }
  348. /**
  349. * Times tables
  350. */
  351. class six1 extends Exercise {
  352. public six1() {
  353. super(1);
  354. int testNum = 6;
  355. System.out.println(String.format("Times table for %d:", testNum));
  356. writeTimesTable(7);
  357. }
  358. }
  359. class six3 extends Exercise {
  360. public six3() {
  361. super(3);
  362. int testNum = 13; // statistically the most prime of all numbers
  363. System.out.println(String.format("Testing primes..."));
  364. System.out.println(String.format("%d prime? %s", testNum, isPrime(testNum)));
  365. System.out.println(String.format("%d prime? %s", 23, isPrime(23)));
  366. System.out.println(String.format("%d prime? %s", 27, isPrime(27)));
  367. System.out.println(String.format("%d prime? %s", 28, isPrime(28)));
  368. System.out.println(String.format("%d prime? %s", 299, isPrime(299)));
  369. System.out.println(String.format("Generating primes..."));
  370. generatePrimes(1024);
  371. System.out.println(String.format("Done!%n"));
  372. }
  373. }
  374. /**
  375. * Number guessing game
  376. * Random number between 0 and 99, user guesses and is told higher / lower / correct
  377. */
  378. class six5 extends Exercise {
  379. private Random random = new Random();
  380. public six5() {
  381. super(5);
  382. numberGuessingGame();
  383. }
  384. public void numberGuessingGame() {
  385. final boolean SUPER_ADVANCED_AI = false; // true - simulated guesses, false - stdin
  386. final Scanner userInput = new Scanner(System.in);
  387. final int HIGHEST = 99;
  388. final int MAX_GUESSES = 10;
  389. int guess;
  390. int chosenNumber = random.nextInt(HIGHEST + 1);
  391. // super advanced AI section
  392. int maxPossible = HIGHEST + 1;
  393. int minPossible = 0;
  394. String guesses = "guess"; // for correct plurals
  395. if (SUPER_ADVANCED_AI) {
  396. guess = random.nextInt(HIGHEST+1);
  397. } else {
  398. guess = getUserGuess(userInput);
  399. }
  400. System.out.printf("Guessing...\t");
  401. for (int i = 0; i < MAX_GUESSES; i++ ) {
  402. System.out.printf("%d", guess);
  403. if (guess == chosenNumber) {
  404. System.out.println(String.format("\nYou guessed right after %d %s! It was indeed %d",
  405. i+1, guesses, chosenNumber));
  406. userInput.close();
  407. return;
  408. }
  409. guesses = "guesses"; // didn't get it on the first try
  410. if (guess < chosenNumber) {
  411. System.out.printf("↑\t");
  412. if (guess > minPossible) { minPossible = guess; }
  413. } else {
  414. System.out.printf("↓\t");
  415. if (guess < maxPossible) {
  416. maxPossible = guess;
  417. }
  418. }
  419. // The better approach is to guess halfway between minPossible and maxPossible
  420. // but that's kinda boring and robotic
  421. if (SUPER_ADVANCED_AI) {
  422. guess = randomBetween(minPossible, maxPossible);
  423. } else {
  424. guess = getUserGuess(userInput);
  425. }
  426. // TODO change the behaviour so it doesn't guess the same number in a row
  427. }
  428. System.out.println(String.format("\nThe answer was: %d. Better luck next time!", chosenNumber));
  429. userInput.close();
  430. }
  431. public int randomBetween(int min, int max) {
  432. if (min < 0) { min = 0; }
  433. if (max == 0) { return 0; }
  434. // System.out.printf(" random.nextInt(%d - %d) + %d ", max, min, min);
  435. return (random.nextInt(max - min) + min);
  436. }
  437. public int getUserGuess(Scanner userInput) {
  438. System.out.println(String.format("Please enter an integer between 0 and 99 to guess"));
  439. int guess = userInput.nextInt();
  440. userInput.nextLine();
  441. return guess;
  442. }
  443. }
  444. /**
  445. * Produce a number triangle
  446. *
  447. * eg:
  448. * 1
  449. * 2 2
  450. * 3 3 3
  451. * 4 4 4 4
  452. */
  453. class six6 extends Exercise {
  454. public six6() {
  455. super(6);
  456. numberTriangle(1);
  457. numberTriangle(4);
  458. numberTriangle(8);
  459. numberTriangle(29);
  460. }
  461. }
  462. class six7 extends Exercise {
  463. public six7() {
  464. super(7);
  465. describeDD(4.2, 1.6);
  466. describeDD(47.42, 7.9);
  467. }
  468. /** Simple exposition of double division
  469. * @param num1 Dividend
  470. * @param num2 Divisor
  471. */
  472. public void describeDD(double num1, double num2) {
  473. System.out.println(String.format("Double division of %.2f by %.2f:\t", num1, num2));
  474. DoubleDivisionResult result = doubleDivision(num1, num2);
  475. System.out.println(String.format("Quotient: %d (ie %.2f ✕ %d = %.2f)\tRemainder: %.2f",
  476. result.getQuotient(),
  477. num2,
  478. result.getQuotient(),
  479. (num2 * result.getQuotient()),
  480. result.getRemainder()));
  481. }
  482. }
  483. /**
  484. * Exercise 8 - String pad with specified character
  485. */
  486. class six8 extends Exercise {
  487. public six8() {
  488. super(8);
  489. describeStringPadding("NoNeed", 4, '!');
  490. describeStringPadding("Simon", 10, '@');
  491. describeStringPadding("Zaphod Beeblebrox", 42, '?');
  492. // describeStringPadding("Unicode", 10, '🤯'); aww
  493. }
  494. /**
  495. * Print for display what we're padding and the result
  496. *
  497. * @param toPad The string to pad eg "Simon"
  498. * @param length Desired length
  499. * @param padChar Character to pad with
  500. */
  501. public void describeStringPadding(String toPad, int paddedLength, char padChar) {
  502. System.out.println(String.format("Padding '%s' to length %d using padding character: %s",
  503. toPad, paddedLength, padChar));
  504. System.out.println(stringLPad(toPad, paddedLength, padChar));
  505. }
  506. /**
  507. * (Left-)pad a string with the specific character
  508. *
  509. * @param toPad The string to pad eg "Simon"
  510. * @param length Desired length
  511. * @param padChar Character to pad with
  512. * @return The padded result
  513. */
  514. public static String stringLPad(String toPad, int paddedLength, char padChar) {
  515. // early out - return unmodified
  516. if (toPad.length() >= paddedLength) {
  517. return toPad;
  518. }
  519. // note that we could do this with String.repeat(), but since this is in the 'Loops'
  520. // part of the lab, we should probably do this with a loop
  521. // String paddedString = String.valueOf(padChar) + toPad;
  522. String paddedString = toPad;
  523. while (paddedString.length() < paddedLength) {
  524. paddedString = String.valueOf(padChar) + paddedString;
  525. }
  526. return paddedString;
  527. }
  528. }
  529. class six9 extends Exercise {
  530. private Random random = new Random(); // initialise once
  531. // see https://stackoverflow.com/a/35277291, to pick a random member of an enum, first convert it to an array
  532. private Throw[] throwsArray = Throw.values(); // can't call it 'throws' for obvious reasons
  533. final Throw randomThrow() {
  534. return throwsArray[random.nextInt(throwsArray.length)];
  535. }
  536. public six9() {
  537. super(9);
  538. Throw player1 = Throw.ROCK; // "Good ol' rock, nothing beats that"
  539. Throw player2 = randomThrow();
  540. System.out.println(String.format("Playing three games to warm up:"));
  541. playRockPaperScissors(player1, player2);
  542. player2 = randomThrow();
  543. playRockPaperScissors(player1, player2);
  544. player2 = randomThrow();
  545. playRockPaperScissors(player1, player2);
  546. System.out.println(String.format("Grand. Now it's your turn!"));
  547. player1 = getUserThrow();
  548. playRockPaperScissors(player1, player2);
  549. }
  550. }
  551. public Throw getUserThrow() {
  552. Scanner userInput = new Scanner(System.in);
  553. // Throw userThrow = null;
  554. while (true) {
  555. System.out.println(String.format("Please enter your throw:"));
  556. System.out.println(String.format("\t0 (rock), 1 (paper), 2 (scissors)"));
  557. System.out.println(String.format("\tor the word corresponding to the throw you'd like"));
  558. System.out.println(String.format("\t[q / quit] quits"));
  559. // check for number
  560. if (userInput.hasNextInt()) {
  561. int choiceNumber = userInput.nextInt();
  562. if ((choiceNumber < 0) || (choiceNumber > 2)) {
  563. continue;
  564. } else {
  565. userInput.close();
  566. Throw[] throwsArray = Throw.values();
  567. return throwsArray[choiceNumber];
  568. }
  569. } else if (userInput.hasNext()) {
  570. String choiceString = userInput.nextLine();
  571. switch (choiceString.toLowerCase()) {
  572. case "rock":
  573. case "stone":
  574. userInput.close();
  575. return Throw.ROCK;
  576. case "paper":
  577. userInput.close();
  578. return Throw.PAPER;
  579. case "scissors":
  580. userInput.close();
  581. return Throw.SCISSORS;
  582. case "q":
  583. case "quit":
  584. userInput.close();
  585. System.exit(0);
  586. default:
  587. continue;
  588. }
  589. }
  590. }
  591. }
  592. public void playRockPaperScissors (Throw player1, Throw player2) {
  593. // slight semantic overload with throwing an error but I think that's the term
  594. // for plays in RPS
  595. String result;
  596. // early out - TOASK why this doesn't work when it works in a REPL!!
  597. // answered - umm, I forgot the else >_<
  598. if (player1 == player2) {
  599. result = "a draw";
  600. } else {
  601. switch (player1) {
  602. case ROCK:
  603. if (player2 == Throw.SCISSORS) { result = "R>S Player 1 wins"; }
  604. else { result = "R<P Player 2 wins"; } // must be paper
  605. break;
  606. case PAPER:
  607. if (player2 == Throw.SCISSORS) { result = "P<S Player 2 wins"; }
  608. else { result = "P>R Player 1 wins"; } // must be rock
  609. break;
  610. case SCISSORS:
  611. if (player2 == Throw.ROCK) { result = "S<R Player 2 wins"; }
  612. else { result = "S>P Player 1 wins"; } // must be paper
  613. break;
  614. default:
  615. result = "undefined behaviour";
  616. break;
  617. }
  618. }
  619. writeRPSPlay(player1, player2, result);
  620. }
  621. public String getThrowName(Throw thrown) {
  622. // This could probably be done in the enum itself
  623. switch (thrown) {
  624. case ROCK: return six8.stringLPad("rock", 8, ' '); // pad to 'scissors' length so everything stays lined-up
  625. case PAPER: return six8.stringLPad("paper", 8, ' ');
  626. case SCISSORS: return "scissors";
  627. default: return "uh?";
  628. }
  629. }
  630. public void writeRPSPlay (Throw player1, Throw player2, String result) {
  631. System.out.printf("Player 1 throws... %s\t", getThrowName(player1));
  632. System.out.printf("Player 2 throws... %s\t", getThrowName(player2));
  633. System.out.println(String.format("The result is... %s", result));
  634. }
  635. enum Throw {
  636. ROCK,
  637. PAPER,
  638. SCISSORS
  639. }
  640. /* TOASK - is there a better way of returning multiple values in Java?
  641. à la python, ie: return (quotient, remainder)
  642. */
  643. /**
  644. * Wrapper class for returning results from double division
  645. */
  646. final class DoubleDivisionResult {
  647. private int quotient; // that's the number of times something goes into something else
  648. private double remainder; // that's the bit left over
  649. public DoubleDivisionResult(int quotient, double remainder) {
  650. this.quotient = quotient;
  651. this.remainder = remainder;
  652. }
  653. public int getQuotient() {
  654. return quotient;
  655. }
  656. public double getRemainder() {
  657. return remainder;
  658. }
  659. }
  660. /**
  661. * Perform 'double division'
  662. *
  663. * @param dividend Number to be divided
  664. * @param divisor Number to divide by
  665. * @return a {@link DoubleDivisionResult} with the (int) quotient and (double) remainder
  666. */
  667. public DoubleDivisionResult doubleDivision(double dividend, double divisor) {
  668. // example used is 4.2 and 1.6
  669. // should return 2 and 1.0
  670. final boolean DEBUG = false;
  671. double dQuotient = dividend / divisor;
  672. int iQuotient = (int)dQuotient;
  673. double remainder = dividend - (iQuotient * divisor);
  674. if (DEBUG) {
  675. System.out.println(String.format("float quotient: %.2f", dQuotient));
  676. System.out.println(String.format("int quotient: %d", iQuotient));
  677. // TOASK: is there a neater way to do this casting?
  678. }
  679. return new DoubleDivisionResult(iQuotient, remainder);
  680. }
  681. /**
  682. * @param num Size of triangle
  683. */
  684. public void numberTriangle(int num) {
  685. /* Observations:
  686. - for even-sized triangles, preceding number of spaces starts at n=rows and decrements
  687. - for even-sized triangles even numbers have odd spaces and vice versa
  688. TODO: handle multi-digit numbers
  689. */
  690. System.out.println(String.format(""));
  691. int spaces = num;
  692. for (int i = 1; i <= num; i++) {
  693. System.out.println(" ".repeat(spaces)
  694. + String.format("%s ", i).repeat(i)
  695. + " ".repeat(spaces-1)
  696. );
  697. spaces--;
  698. }
  699. System.out.println(String.format(""));
  700. }
  701. /**
  702. * @param num The number to write the times table for
  703. * @param limit How many multiples to show
  704. */
  705. public void writeTimesTable(int num, int limit) {
  706. for (int i = 0; i < (limit + 1); i++) {
  707. System.out.printf("%d\t", num * i);
  708. }
  709. }
  710. /* TOASK - overload example.
  711. Question: is there a better way of doing optional function parameters in java?
  712. */
  713. /**
  714. * Write times table for num (10 entries)
  715. * @param num Number to show times table for
  716. */
  717. public void writeTimesTable(int num) {
  718. int DEFAULT_LIMIT = 10;
  719. writeTimesTable(num, DEFAULT_LIMIT);
  720. }
  721. public void generatePrimes(int upperLimit) {
  722. // handle 2 as a special case
  723. System.out.println(String.format("2"));
  724. // for (int i = 3; i <= upperLimit; i += 2) {
  725. for (int i = 2; i <= upperLimit; i++) {
  726. // TODO: figure out smarter way of doing this, I'm sure primes must be at least 6 apart...
  727. // Something about 2n ± 1 ?
  728. // seive of Erasthotenes ..?
  729. if (isPrime(i)) {
  730. System.out.printf("%d\t", i);
  731. }
  732. }
  733. }
  734. /**
  735. * But is it prime?
  736. * @param num Integer to test for primality
  737. * @return if it's prime
  738. */
  739. public boolean isPrime(int num) {
  740. boolean DEBUG = false;
  741. if ((num == 2) || (num == 1)) {
  742. return true;
  743. }
  744. if (num % 2 == 0){
  745. return false;
  746. } else {
  747. int divisor = 3;
  748. double numSquareRoot = Math.sqrt((double)num);
  749. while (divisor <= numSquareRoot) {
  750. if (num % divisor == 0) {
  751. return false;
  752. }
  753. divisor += 2;
  754. if (DEBUG) {
  755. System.out.printf("%d\t", divisor);
  756. }
  757. }
  758. return true;
  759. }
  760. }
  761. }
  762. /**
  763. * String formatting
  764. *
  765. */
  766. class Lab7 extends Lab {
  767. public Lab7() {
  768. super(7);
  769. writeTimesTable(8.24579, 10);
  770. writeTimesTable(93.12279, 22);
  771. writeTimesTable(193.12279, 22);
  772. writeTimesTable(13.9, 122);
  773. }
  774. /**
  775. * @param num The number to write the times table for (0 <= num <= 99)
  776. * @param limit How many multiples to show (0 <= limit <= 99)
  777. */
  778. public void writeTimesTable(double num, int limit) {
  779. final double MINNUM = 0;
  780. final double MAXNUM = 99;
  781. final int MINLIMIT = 0;
  782. final int MAXLIMIT = 99;
  783. if ((num < MINNUM) || (num > MAXNUM)) {
  784. System.err.println(String.format("Please specify a number between %.2f and %.2f (supplied: %.2f)",
  785. MINNUM, MAXNUM, num));
  786. return;
  787. }
  788. if ((limit < MINLIMIT) || (limit > MAXLIMIT)) {
  789. System.err.println(String.format("Please specify a limit between %d and %d (supplied: %d)",
  790. MINLIMIT, MAXLIMIT, limit));
  791. return;
  792. }
  793. for (int i = 0; i < (limit + 1); i++) {
  794. // output specification:
  795. // ~~.~~~ x ~~ = ~~~~~.~~~
  796. System.out.printf("%2.3f x %02d = %5.3f%n", num, i, (num*i));
  797. }
  798. }
  799. }