diff --git a/01-intro-to-java/snippets/AdmissionTestProblems.java b/01-intro-to-java/snippets/AdmissionTestProblems.java new file mode 100644 index 00000000..e847bb36 --- /dev/null +++ b/01-intro-to-java/snippets/AdmissionTestProblems.java @@ -0,0 +1,72 @@ +public class AdmissionTestProblems { + + // An online text processing service needs a feature that compresses strings to save space + // and reduce transmission time – you're the developer assigned to this task. + // Implement a function that performs a basic string compression using the counts + // of repeated characters. For example, the string "aabcccccaaa" would become "a2b1c5a3". + public static String compressString(String input) { + if (input == null || input.length() <= 1) { + return input; + } + + StringBuilder compressed = new StringBuilder(); + int count = 1; // Initialize the count of matching characters + + for (int i = 1; i < input.length(); i++) { + if (input.charAt(i) == input.charAt(i - 1)) { + count++; // Increment the count if the current character matches the previous one + } else { + // Append the character and its count to the compressed string + compressed.append(input.charAt(i - 1)).append(count); + count = 1; // Reset count for the new character + } + } + + // Append the last character and its count + compressed.append(input.charAt(input.length() - 1)).append(count); + + // Check if the compressed string is actually shorter than the original string + String compressedString = compressed.toString(); + return compressedString.length() < input.length() ? compressedString : input; + } + + // Create two versions of a function that, for a given integer N >= 0, + // calculates a real number: the sum + // 1 + 1/2 + 1/4 + 1/8 + ... + 1/2^N + // One of the versions should use recursion, the other – iteration. + public static double sumIter(int n) { + double result = 0.0; + int denominator = 1; + for (int i = 0; i <= n; i++) { + result += 1.0 / denominator; + denominator *= 2; + } + return result; + } + + public static double sumRec(int n) { + if (n == 0) { + return 1.0; + } else { + return 1.0 / Math.pow(2, n) + sumRec(n - 1); + } + } + + public static double sumRecNoPow(int n) { + return sumRecCalc(n, 1.0, 2); + } + + private static double sumRecCalc(int n, double sum, int denominator) { + if (n == 0) { + return sum; + } else { + return sumRecCalc(n - 1, sum += 1.0 / denominator, denominator * 2); + } + } + + public static void main(String[] args) { + System.out.println(compressString("aabcccccaaa")); + System.out.println(sumIter(2)); // 1.75 + System.out.println(sumRec(3)); // 1.875 + } +} diff --git a/01-intro-to-java/snippets/IntroToJava.java b/01-intro-to-java/snippets/IntroToJava.java new file mode 100644 index 00000000..693dfd05 --- /dev/null +++ b/01-intro-to-java/snippets/IntroToJava.java @@ -0,0 +1,173 @@ +import java.util.Arrays; +import java.util.Collections; + +public class IntroToJava { + + public static void exploreString() { + + // 1. string literals and the string pool + System.out.println("==============1=============="); + String literalOne = "FMI"; // goes to the string pool + String literalTwo = "FMI"; // "FMI" is present in the String pool -> literalTwo will refer to the same + // object + + System.out.println(literalOne == literalTwo); // true + + String newString = new String("FMI"); // new String object in the heap + + System.out.println(literalOne == newString); // false, literalOne refers to an object in the string pools, + // newString refers to an object in the heap + System.out.println(literalOne.equals(newString)); // true: string content is the same + + String intern = newString.intern(); // String "interning" will add the string in the pool and return a reference + // to it + System.out.println(literalOne == newString); // false, newString is not reassigned + System.out.println(literalOne == intern); // true + + // 2. string concatenation and splitting + System.out.println("==============2=============="); + int year = 2024; + String message = "Current year is "; + message += year + "."; // Strings are immutable so this will create a new String object and some + // garbage + + String[] words = message.split(" "); // {"Current", "year", "is", "2024."} + System.out.println(words); // Will not print a human-readable representation. Instead it will print + // something like [Ljava.lang.String;@1dbd16a6 + System.out.println(Arrays.toString(words)); // "[Current, year, is, 2024.]" + + // 3. string iteration and conversion String -> char array + System.out.println("==============3=============="); + String example = "Example"; + char secondChar = example.charAt(1); // 'x'. Note that Strings are not char arrays, i.e. you cannot do e.g. + // example[1]; + System.out.println("Second char is: " + secondChar); + + char[] chars = example.toCharArray(); // convert a String to char array + + System.out.println("_BEGIN_ITERATION_"); + for (int i = 0; i < chars.length; i++) { // iterate the char array with standard for-loop + System.out.println(chars[i]); + } + System.out.println("_END_ITERATION_"); + + System.out.println("_BEGIN_ITERATION_"); + for (char current : chars) { // the same as above but with for-each loop -> recommended because it's shorter + System.out.println(current); + } + System.out.println("_END_ITERATION_"); + + // 4. conversion char array -> String + System.out.println("==============4=============="); + String backToStr0 = chars.toString(); // WRONG! Note that chars.toString() does not work as you may expect + String backToStr1 = String.valueOf(chars); // Right way! + String backToStr2 = Arrays.toString(chars); // Encloses char elements in brackets and adds ',' between them + + System.out.println(backToStr0 + " : " + backToStr1 + " : " + backToStr2); + + // 5. String manipulation + System.out.println("==============5=============="); + String lower = "WHatEveR".toLowerCase(); // "whatever" + String upper = "WHatEveR".toUpperCase(); // "WHATEVER" + String reverse = new StringBuilder(lower).reverse().toString(); // "revetahw" + + System.out.println(lower + " : " + upper + " : " + reverse); + + String replaced = "cut".replace('c', 'p'); // "put" + String substring = "Anaconda".substring(2, 6); // "acon" + boolean containsCo = substring.contains("co"); // true + boolean startsWithB = substring.startsWith("b"); // false + boolean endsWithOn = substring.endsWith("on"); // true + int indexOfN = "Coconut".indexOf("n"); // 4 + int length = "Coconut".length(); // 7 (note that the length is a method, not a field) + + String strippedWhiteSpaces = " some whitespaces we want to strip ".strip(); // "some whitespaces we want to + // strip" + String indentedText = "Indent this".indent(4); // " Indent this" -> indents the text by appending spaces in + // front + + // 6. More String comparisons + System.out.println("==============6=============="); + boolean isEmpty = "".isEmpty(); // true + boolean isNotEmpty = !" ".isEmpty(); // true + boolean isBlank = " ".isBlank(); // true + boolean equalIgnoringCapitalization = "Java".equalsIgnoreCase("jAVA"); // true + + // 7. Emojis + System.out.println("I am from \uD83C\uDDE7\uD83C\uDDEC"); + + System.out.println((Character.toChars(9203))); + System.out.println(Character.isEmoji(9203)); + } + + public static void exploreStringBuilder() { + + // We use StringBuilder when we expect the string to be manipulated + // e.g. in loops: + StringBuilder oddNumbers = new StringBuilder(); + for (int i = 0; i < 20; i++) { + if (i % 2 != 0) { + oddNumbers.append(i).append(" "); + } + } + System.out.println(oddNumbers); // "1 3 5 7 9 11 13 15 17 19 " + + // or in something like this: + StringBuilder word = new StringBuilder("racecar"); + boolean isPalindrome = word.equals(word.reverse()); // true + + // As the following concatenation is in the same statement, + // the compiler will optimize this and use StringBuilder instead + String feelings = "I " + "<3 " + "Java"; + } + + public static void exploreArrays() { + + int[] array; // just declaration - the array is not created, no memory is allocated + array = new int[5]; // initialization - now we have {0, 0, 0, 0, 0} + + String[] stringArray = {"apple", "banana", "cherry"}; // string array with 3 elements is declared and + // initialized + char[] charArray = new char[] {'a', 'b'}; // such initialization is also valid + int length = stringArray.length; // 3 (note that the length is a field, not a method) + + long[][] longMatrix = new long[10][10]; // 10x10 array initialized + double[][] doubleMatrix = new double[100][]; // array with 100 rows initialized, but all rows still + // uninitialized + + for (int i = 0; i < 100; i++) { + doubleMatrix[i] = + new double[10]; // array now initialized. Note that rows need not be of the same length - called jagged (or ragged) array + } + + int[] intArray = {1, 6, 7, 3}; + Arrays.sort(intArray); // { 1, 3, 6, 7 } + String[] animals = {"cat", "dog", "bird"}; + Arrays.sort(animals, Collections.reverseOrder()); // { "dog", "cat", "bird" } + + for (String animal : animals) { + System.out.println(animal); + } + + int index = Arrays.binarySearch(intArray, 7); // 3 + + int[] copy = Arrays.copyOf(intArray, intArray.length); + boolean areEqual = Arrays.equals(intArray, copy); // true + + System.out.println(Arrays.toString(copy)); + + // As we know, arrays are objects and need to be compared with "equals()". + // However, two (and more) dimensional arrays are arrays of objects + // and Java has a special method for comparing them: + char[][] currentBoard = {{'X', 'O', 'X'}, {'X', 'O', 'O'}, {'X', 'X', 'O'}}; + char[][] winBoard = {{'X', 'O', 'X'}, {'X', 'O', 'O'}, {'X', 'X', 'O'}}; + boolean isWinning = Arrays.deepEquals(currentBoard, winBoard); // true + } + + public static void main(String[] args) { + exploreString(); + exploreStringBuilder(); + exploreArrays(); + } + +} diff --git a/01-intro-to-java/snippets/SwitchExamples.java b/01-intro-to-java/snippets/SwitchExamples.java new file mode 100644 index 00000000..74404ec8 --- /dev/null +++ b/01-intro-to-java/snippets/SwitchExamples.java @@ -0,0 +1,76 @@ +import java.util.Arrays; + +public class SwitchExamples { + + public static void main(String[] args) { + String foodForToday = "RAMEN"; + System.out.println(oldSwitchFoodGrader(foodForToday)); + System.out.println(java15FoodGrader(foodForToday)); + + System.out.println(switchPatternMatchingStringConvert("Hello")); + System.out.println(switchPatternMatchingStringConvert(25)); + System.out.println(switchPatternMatchingStringConvert(new char[] {'a', 'b', 'c'})); + + switchPatternMatchingPrimitiveSelector(); + } + + private static String oldSwitchFoodGrader(String food) { + String grade; + switch (food) { + case "PIZZA": + grade = "NICE!"; + break; + case "RAMEN": + grade = "OOOH FANCY!"; + break; + case "SNAILS": + grade = "ARE YOU OUT OF YOUR MIND?!?"; + break; + default: + grade = "IF YOU REALLY WANT TO..."; + } + + return grade; + } + + private static String java15FoodGrader(String food) { + var grade = switch (food) { + case "PIZZA" -> "NICE!"; + case "RAMEN" -> "OOOH FANCY!"; + case "SNAILS" -> "ARE YOU OUT OF YOUR MIND?!?"; + default -> "IF YOU REALLY WANT TO..."; + }; + + return grade; + } + + // Preview feature since JDK 17, finalized with JDK 21 + private static String switchPatternMatchingStringConvert(Object inputObject) { + return switch (inputObject) { + case char[] charArray -> Arrays.toString(charArray); + case Integer i -> "" + i; + case String _ -> + "Are you really trying to convert a string to a string?"; // Unnamed variable - we won't use it + // but instead scold the programmer. + // Note: feature previewed in JDK 21 + // and finalized in JDK 22 + case null -> "It's a null reference"; // able to handle null references + default -> "It is none of the known data types"; + }; + } + + // Primitive types in switch selectors: a JDK 23 preview feature + private static void switchPatternMatchingPrimitiveSelector() { + double value = 3.14; + switch (value) { + case byte b -> System.out.println(value + " instanceof byte: " + b); + case short s -> System.out.println(value + " instanceof short: " + s); + case char c -> System.out.println(value + " instanceof char: " + c); + case int i -> System.out.println(value + " instanceof int: " + i); + case long l -> System.out.println(value + " instanceof long: " + l); + case float f -> System.out.println(value + " instanceof float: " + f); + case double d -> System.out.println(value + " instanceof double: " + d); + } + } + +} diff --git a/01-intro-to-java/snippets/UnnamedClassesExample.java b/01-intro-to-java/snippets/UnnamedClassesExample.java new file mode 100644 index 00000000..962bf39e --- /dev/null +++ b/01-intro-to-java/snippets/UnnamedClassesExample.java @@ -0,0 +1,9 @@ +// NOTE: This is possible thanks to preview language features in Java 21 and 23. + +// No class declaration is required +// Java keywords public and static are no longer required for main +// Main method argument args is optional +// The static methods of java.io.IO such as println() are automatically imported +void main() { + println("Hello, World!"); +}