Exercises from labs 2023-2024
25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

week1.java 23 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706
  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 Lab7();
  10. new Lab6();
  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,
  117. * month, year)
  118. */
  119. public static void ex46() {
  120. String labSection = "4.6";
  121. printSection(labSection);
  122. // calculate whole years' old to date
  123. Calendar today = Calendar.getInstance();
  124. System.out.println("Today:\t" + today.getTime());
  125. Calendar dob1 = Calendar.getInstance();
  126. dob1.set(1990, 1, 1);
  127. System.out.println(String.format(
  128. "DOB 1:\t%s (difference:\t%d years)",
  129. dob1.getTime(),
  130. yearDifference(today, dob1)));
  131. Calendar dob2 = Calendar.getInstance();
  132. dob2.set(1994, 12, 22);
  133. System.out.println(String.format(
  134. "DOB 2:\t%s (difference:\t%d years)",
  135. dob2.getTime(),
  136. yearDifference(today, dob2)));
  137. }
  138. public static boolean isLeap(int year) {
  139. if (year % 4 != 0) {
  140. return false;
  141. } else {
  142. if (year % 100 == 0) {
  143. if (year % 400 == 0) {
  144. return true;
  145. } else {
  146. return false;
  147. }
  148. }
  149. return true;
  150. }
  151. }
  152. public static int monthLen(String month, int year) {
  153. if (month == "feb") {
  154. if (isLeap(year)) {
  155. return 29;
  156. } else {
  157. return 28;
  158. }
  159. } else if (
  160. (month == "apr") ||
  161. (month == "jun") ||
  162. (month == "sep") ||
  163. (month == "nov")) {
  164. return 30;
  165. } else {
  166. return 31;
  167. }
  168. }
  169. public static int yearDifference(Calendar date1, Calendar date2)
  170. {
  171. return (int) Math.abs(date1.get(Calendar.YEAR) -
  172. date2.get(Calendar.YEAR)
  173. );
  174. }
  175. }
  176. /**
  177. * Keyboard input
  178. */
  179. class Lab5 extends Lab {
  180. public Lab5() {
  181. super(5);
  182. new five1();
  183. }
  184. class five1 extends Exercise {
  185. /**
  186. * We will now look at how we can get user input from the keyboard. We will
  187. * gloss over some
  188. * of the details here, but give you just the information you need to start
  189. * getting input and
  190. * processing it.
  191. */
  192. public five1() {
  193. super(1);
  194. System.out.println(String.format("TBC"));
  195. // Scanner keyboard = new Scanner(System.in);
  196. // System.out.println("Please enter your name, followed by the return key?");
  197. // String userEntry = keyboard.nextLine();
  198. // System.out.println("Hello " + userEntry);
  199. // System.out.println(String.format("%s", keyboard));
  200. }
  201. }
  202. }
  203. /**
  204. * Loops
  205. */
  206. class Lab6 extends Lab {
  207. public Lab6() {
  208. super(6);
  209. new six1();
  210. System.out.println(String.format("%n"));
  211. new six3();
  212. new six6();
  213. new six7();
  214. new six8();
  215. new six9();
  216. new six5();
  217. }
  218. /**
  219. * Times tables
  220. */
  221. class six1 extends Exercise {
  222. public six1() {
  223. super(1);
  224. int testNum = 6;
  225. System.out.println(String.format("Times table for %d:", testNum));
  226. writeTimesTable(7);
  227. }
  228. }
  229. class six3 extends Exercise {
  230. public six3() {
  231. super(3);
  232. int testNum = 13; // statistically the most prime of all numbers
  233. System.out.println(String.format("Testing primes..."));
  234. System.out.println(String.format("%d prime? %s", testNum, isPrime(testNum)));
  235. System.out.println(String.format("%d prime? %s", 23, isPrime(23)));
  236. System.out.println(String.format("%d prime? %s", 27, isPrime(27)));
  237. System.out.println(String.format("%d prime? %s", 28, isPrime(28)));
  238. System.out.println(String.format("%d prime? %s", 299, isPrime(299)));
  239. System.out.println(String.format("Generating primes..."));
  240. generatePrimes(1024);
  241. System.out.println(String.format("Done!%n"));
  242. }
  243. }
  244. /**
  245. * Number guessing game
  246. * Random number between 0 and 99, user guesses and is told higher / lower / correct
  247. */
  248. class six5 extends Exercise {
  249. private Random random = new Random();
  250. public six5() {
  251. super(5);
  252. System.out.println(String.format("TODO: get stdin working to user can play"));
  253. numberGuessingGame();
  254. // System.out.println(String.format("Testing randomBetween..."));
  255. // int max = 100;
  256. // int min = 50;
  257. // for (int i=0; i<125; i++) {
  258. // System.out.printf("%d ", randomBetween(min, max));
  259. // }
  260. // System.out.println(String.format("done."));
  261. }
  262. public void numberGuessingGame() {
  263. final boolean SUPER_ADVANCED_AI = true;
  264. final int HIGHEST = 99;
  265. final int MAX_GUESSES = 10;
  266. int chosenNumber = random.nextInt(HIGHEST+1);
  267. int guess = random.nextInt(HIGHEST+1);
  268. // super advanced AI section
  269. int maxPossible = HIGHEST+1;
  270. int minPossible = 0;
  271. String guesses = "guess"; // for correct plurals
  272. System.out.printf("Guessing...\t");
  273. for (int i = 0; i < MAX_GUESSES; i++ ) {
  274. System.out.printf("%d", guess);
  275. if (guess == chosenNumber) {
  276. System.out.println(String.format("\nYou guessed right after %d %s! It was indeed %d",
  277. i+1, guesses, chosenNumber));
  278. return;
  279. }
  280. guesses = "guesses"; // didn't get it on the first try
  281. if (guess < chosenNumber) {
  282. System.out.printf("↑\t");
  283. if (guess > minPossible) { minPossible = guess; }
  284. } else {
  285. System.out.printf("↓\t");
  286. if (guess < maxPossible) {
  287. maxPossible = guess;
  288. }
  289. }
  290. // The better approach is to guess halfway between minPossible and maxPossible
  291. // but that's kinda boring and robotic
  292. if (SUPER_ADVANCED_AI) {
  293. guess = randomBetween(minPossible, maxPossible);
  294. }
  295. // TODO change the behaviour so it doesn't guess the same number in a row
  296. }
  297. System.out.println(String.format("\nThe answer was: %d. Better luck next time!", chosenNumber));
  298. }
  299. public int randomBetween(int min, int max) {
  300. if (min < 0) { min = 0; }
  301. if (max == 0) { return 0; }
  302. // System.out.printf(" random.nextInt(%d - %d) + %d ", max, min, min);
  303. return (random.nextInt(max - min) + min);
  304. }
  305. }
  306. /**
  307. * Produce a number triangle
  308. *
  309. * eg:
  310. * 1
  311. * 2 2
  312. * 3 3 3
  313. * 4 4 4 4
  314. */
  315. class six6 extends Exercise {
  316. public six6() {
  317. super(6);
  318. numberTriangle(1);
  319. numberTriangle(4);
  320. numberTriangle(8);
  321. numberTriangle(29);
  322. }
  323. }
  324. class six7 extends Exercise {
  325. public six7() {
  326. super(7);
  327. describeDD(4.2, 1.6);
  328. describeDD(47.42, 7.9);
  329. }
  330. /** Simple exposition of double division
  331. * @param num1 Dividend
  332. * @param num2 Divisor
  333. */
  334. public void describeDD(double num1, double num2) {
  335. System.out.println(String.format("Double division of %.2f by %.2f:\t", num1, num2));
  336. DoubleDivisionResult result = doubleDivision(num1, num2);
  337. System.out.println(String.format("Quotient: %d (ie %.2f ✕ %d = %.2f)\tRemainder: %.2f",
  338. result.getQuotient(),
  339. num2,
  340. result.getQuotient(),
  341. (num2 * result.getQuotient()),
  342. result.getRemainder()));
  343. }
  344. }
  345. /**
  346. * Exercise 8 - String pad with specified character
  347. */
  348. class six8 extends Exercise {
  349. public six8() {
  350. super(8);
  351. describeStringPadding("NoNeed", 4, '!');
  352. describeStringPadding("Simon", 10, '@');
  353. describeStringPadding("Zaphod Beeblebrox", 42, '?');
  354. // describeStringPadding("Unicode", 10, '🤯'); aww
  355. }
  356. /**
  357. * Print for display what we're padding and the result
  358. *
  359. * @param toPad The string to pad eg "Simon"
  360. * @param length Desired length
  361. * @param padChar Character to pad with
  362. */
  363. public void describeStringPadding(String toPad, int paddedLength, char padChar) {
  364. System.out.println(String.format("Padding '%s' to length %d using padding character: %s",
  365. toPad, paddedLength, padChar));
  366. System.out.println(stringLPad(toPad, paddedLength, padChar));
  367. }
  368. /**
  369. * (Left-)pad a string with the specific character
  370. *
  371. * @param toPad The string to pad eg "Simon"
  372. * @param length Desired length
  373. * @param padChar Character to pad with
  374. * @return The padded result
  375. */
  376. public static String stringLPad(String toPad, int paddedLength, char padChar) {
  377. // early out - return unmodified
  378. if (toPad.length() >= paddedLength) {
  379. return toPad;
  380. }
  381. // note that we could do this with String.repeat(), but since this is in the 'Loops'
  382. // part of the lab, we should probably do this with a loop
  383. // String paddedString = String.valueOf(padChar) + toPad;
  384. String paddedString = toPad;
  385. while (paddedString.length() < paddedLength) {
  386. paddedString = String.valueOf(padChar) + paddedString;
  387. }
  388. return paddedString;
  389. }
  390. }
  391. class six9 extends Exercise {
  392. private Random random = new Random(); // initialise once
  393. // see https://stackoverflow.com/a/35277291, to pick a random member of an enum, first convert it to an array
  394. private Throw[] throwsArray = Throw.values(); // can't call it 'throws' for obvious reasons
  395. final Throw randomThrow() {
  396. return throwsArray[random.nextInt(throwsArray.length)];
  397. }
  398. public six9() {
  399. super(9);
  400. System.out.println(String.format("TODO: Take input when we have stdin working"));
  401. Throw player1 = Throw.ROCK; // "Good ol' rock, nothing beats that"
  402. Throw player2 = randomThrow();
  403. playRockPaperScissors(player1, player2);
  404. player2 = randomThrow();
  405. playRockPaperScissors(player1, player2);
  406. player2 = randomThrow();
  407. playRockPaperScissors(player1, player2);
  408. }
  409. }
  410. public void playRockPaperScissors (Throw player1, Throw player2) {
  411. // slight semantic overload with throwing an error but I think that's the term
  412. // for plays in RPS
  413. String result;
  414. // early out - TOASK why this doesn't work when it works in a REPL!!
  415. if (player1 == player2) {
  416. result = "a draw";
  417. } else {
  418. switch (player1) {
  419. case ROCK:
  420. if (player2 == Throw.SCISSORS) { result = "R>S Player 1 wins"; }
  421. else { result = "R<P Player 2 wins"; } // must be paper
  422. break;
  423. case PAPER:
  424. if (player2 == Throw.SCISSORS) { result = "P<S Player 2 wins"; }
  425. else { result = "P>R Player 1 wins"; } // must be rock
  426. break;
  427. case SCISSORS:
  428. if (player2 == Throw.ROCK) { result = "S<R Player 2 wins"; }
  429. else { result = "S>P Player 1 wins"; } // must be paper
  430. break;
  431. default:
  432. result = "undefined behaviour";
  433. break;
  434. }
  435. }
  436. writeRPSPlay(player1, player2, result);
  437. }
  438. public String getThrowName(Throw thrown) {
  439. // This could probably be done in the enum itself
  440. switch (thrown) {
  441. case ROCK: return six8.stringLPad("rock", 8, ' '); // pad to 'scissors' length so everything stays lined-up
  442. case PAPER: return six8.stringLPad("paper", 8, ' ');
  443. case SCISSORS: return "scissors";
  444. default: return "uh?";
  445. }
  446. }
  447. public void writeRPSPlay (Throw player1, Throw player2, String result) {
  448. System.out.printf("Player 1 throws... %s\t\t", getThrowName(player1));
  449. System.out.printf("Player 2 throws... %s\t\t", getThrowName(player2));
  450. System.out.println(String.format("The result is...\t%s", result));
  451. }
  452. enum Throw {
  453. ROCK,
  454. PAPER,
  455. SCISSORS
  456. }
  457. /* TOASK - is there a better way of returning multiple values in Java?
  458. à la python, ie: return (quotient, remainder)
  459. */
  460. /**
  461. * Wrapper class for returning results from double division
  462. */
  463. final class DoubleDivisionResult {
  464. private int quotient; // that's the number of times something goes into something else
  465. private double remainder; // that's the bit left over
  466. public DoubleDivisionResult(int quotient, double remainder) {
  467. this.quotient = quotient;
  468. this.remainder = remainder;
  469. }
  470. public int getQuotient() {
  471. return quotient;
  472. }
  473. public double getRemainder() {
  474. return remainder;
  475. }
  476. }
  477. /**
  478. * Perform 'double division'
  479. *
  480. * @param dividend Number to be divided
  481. * @param divisor Number to divide by
  482. * @return a {@link DoubleDivisionResult} with the (int) quotient and (double) remainder
  483. */
  484. public DoubleDivisionResult doubleDivision(double dividend, double divisor) {
  485. // example used is 4.2 and 1.6
  486. // should return 2 and 1.0
  487. final boolean DEBUG = false;
  488. double dQuotient = dividend / divisor;
  489. int iQuotient = (int)dQuotient;
  490. double remainder = dividend - (iQuotient * divisor);
  491. if (DEBUG) {
  492. System.out.println(String.format("float quotient: %.2f", dQuotient));
  493. System.out.println(String.format("int quotient: %d", iQuotient));
  494. // TOASK: is there a neater way to do this casting?
  495. }
  496. return new DoubleDivisionResult(iQuotient, remainder);
  497. }
  498. /**
  499. * @param num Size of triangle
  500. */
  501. public void numberTriangle(int num) {
  502. /* Observations:
  503. - for even-sized triangles, preceding number of spaces starts at n=rows and decrements
  504. - for even-sized triangles even numbers have odd spaces and vice versa
  505. TODO: handle multi-digit numbers
  506. */
  507. System.out.println(String.format(""));
  508. int spaces = num;
  509. for (int i = 1; i <= num; i++) {
  510. System.out.println(" ".repeat(spaces)
  511. + String.format("%s ", i).repeat(i)
  512. + " ".repeat(spaces-1)
  513. );
  514. spaces--;
  515. }
  516. System.out.println(String.format(""));
  517. }
  518. /**
  519. * @param num The number to write the times table for
  520. * @param limit How many multiples to show
  521. */
  522. public void writeTimesTable(int num, int limit) {
  523. for (int i = 0; i < (limit + 1); i++) {
  524. System.out.printf("%d\t", num * i);
  525. }
  526. }
  527. /* TOASK - overload example.
  528. Question: is there a better way of doing optional function parameters in java?
  529. */
  530. /**
  531. * Write times table for num (10 entries)
  532. * @param num Number to show times table for
  533. */
  534. public void writeTimesTable(int num) {
  535. int DEFAULT_LIMIT = 10;
  536. writeTimesTable(num, DEFAULT_LIMIT);
  537. }
  538. public void generatePrimes(int upperLimit) {
  539. // handle 2 as a special case
  540. System.out.println(String.format("2"));
  541. // for (int i = 3; i <= upperLimit; i += 2) {
  542. for (int i = 2; i <= upperLimit; i++) {
  543. // TODO: figure out smarter way of doing this, I'm sure primes must be at least 6 apart...
  544. // Something about 2n ± 1 ?
  545. // seive of Erasthotenes ..?
  546. if (isPrime(i)) {
  547. System.out.printf("%d\t", i);
  548. }
  549. }
  550. }
  551. /**
  552. * But is it prime?
  553. * @param num Integer to test for primality
  554. * @return if it's prime
  555. */
  556. public boolean isPrime(int num) {
  557. boolean DEBUG = false;
  558. if ((num == 2) || (num == 1)) {
  559. return true;
  560. }
  561. if (num % 2 == 0){
  562. return false;
  563. } else {
  564. int divisor = 3;
  565. double numSquareRoot = Math.sqrt((double)num);
  566. while (divisor <= numSquareRoot) {
  567. if (num % divisor == 0) {
  568. return false;
  569. }
  570. divisor += 2;
  571. if (DEBUG) {
  572. System.out.printf("%d\t", divisor);
  573. }
  574. }
  575. return true;
  576. }
  577. }
  578. }
  579. /**
  580. * String formatting
  581. *
  582. */
  583. class Lab7 extends Lab {
  584. public Lab7() {
  585. super(7);
  586. writeTimesTable(8.24579, 10);
  587. writeTimesTable(93.12279, 22);
  588. writeTimesTable(193.12279, 22);
  589. writeTimesTable(13.9, 122);
  590. }
  591. /**
  592. * @param num The number to write the times table for (0 <= num <= 99)
  593. * @param limit How many multiples to show (0 <= limit <= 99)
  594. */
  595. public void writeTimesTable(double num, int limit) {
  596. final double MINNUM = 0;
  597. final double MAXNUM = 99;
  598. final int MINLIMIT = 0;
  599. final int MAXLIMIT = 99;
  600. if ((num < MINNUM) || (num > MAXNUM)) {
  601. System.err.println(String.format("Please specify a number between %.2f and %.2f (supplied: %.2f)",
  602. MINNUM, MAXNUM, num));
  603. return;
  604. }
  605. if ((limit < MINLIMIT) || (limit > MAXLIMIT)) {
  606. System.err.println(String.format("Please specify a limit between %d and %d (supplied: %d)",
  607. MINLIMIT, MAXLIMIT, limit));
  608. return;
  609. }
  610. for (int i = 0; i < (limit + 1); i++) {
  611. // output specification:
  612. // ~~.~~~ x ~~ = ~~~~~.~~~
  613. System.out.printf("%2.3f x %02d = %5.3f%n", num, i, (num*i));
  614. }
  615. }
  616. }