From a20d1f3d770090acb0439ab11c71b26c49594680 Mon Sep 17 00:00:00 2001 From: dmitry-mikhnenko Date: Sat, 1 Oct 2022 13:09:28 +0300 Subject: [PATCH 1/2] update git ignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 12f52a1..e6bcfa7 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,6 @@ hs_err_pid* .DS_STORE .metadata + +.idea +CCSPiJ/out/** From ee5e3749b6363b8c27ba1a71da60888ecefab93b Mon Sep 17 00:00:00 2001 From: dmitry-mikhnenko Date: Sun, 2 Oct 2022 04:52:05 +0300 Subject: [PATCH 2/2] refactor --- CCSPiJ/src/chapter1/CompressedGene.java | 140 +++++++++--------- .../{Fib1.java => Fib1StackOverflow.java} | 4 +- .../chapter1/{Fib2.java => Fib2Classic.java} | 27 ++-- .../src/chapter1/{Fib3.java => Fib3Memo.java} | 37 ++--- .../{Fib4.java => Fib4Iteration.java} | 20 ++- .../chapter1/{Fib5.java => Fib5Stream.java} | 39 +++-- CCSPiJ/src/utils/TimeWatch.java | 40 +++++ 7 files changed, 180 insertions(+), 127 deletions(-) rename CCSPiJ/src/chapter1/{Fib1.java => Fib1StackOverflow.java} (93%) rename CCSPiJ/src/chapter1/{Fib2.java => Fib2Classic.java} (65%) rename CCSPiJ/src/chapter1/{Fib3.java => Fib3Memo.java} (54%) rename CCSPiJ/src/chapter1/{Fib4.java => Fib4Iteration.java} (68%) rename CCSPiJ/src/chapter1/{Fib5.java => Fib5Stream.java} (52%) create mode 100644 CCSPiJ/src/utils/TimeWatch.java diff --git a/CCSPiJ/src/chapter1/CompressedGene.java b/CCSPiJ/src/chapter1/CompressedGene.java index 5c51ceb..e0de715 100644 --- a/CCSPiJ/src/chapter1/CompressedGene.java +++ b/CCSPiJ/src/chapter1/CompressedGene.java @@ -19,80 +19,78 @@ import java.util.BitSet; public class CompressedGene { - private BitSet bitSet; - private int length; - public CompressedGene(String gene) { - compress(gene); - } + private BitSet bitSet; + private int length; - private void compress(String gene) { - length = gene.length(); - // reserve enough capacity for all of the bits - bitSet = new BitSet(length * 2); - // convert to upper case for consistency - final String upperGene = gene.toUpperCase(); - // convert String to bit representation - for (int i = 0; i < length; i++) { - final int firstLocation = 2 * i; - final int secondLocation = 2 * i + 1; - switch (upperGene.charAt(i)) { - case 'A': // 00 are next two bits - bitSet.set(firstLocation, false); - bitSet.set(secondLocation, false); - break; - case 'C': // 01 are next two bits - bitSet.set(firstLocation, false); - bitSet.set(secondLocation, true); - break; - case 'G': // 10 are next two bits - bitSet.set(firstLocation, true); - bitSet.set(secondLocation, false); - break; - case 'T': // 11 are next two bits - bitSet.set(firstLocation, true); - bitSet.set(secondLocation, true); - break; - default: - throw new IllegalArgumentException("The provided gene String contains characters other than ACGT"); - } - } - } + public CompressedGene(String gene) { + compress(gene); + } - public String decompress() { - if (bitSet == null) { - return ""; - } - // create a mutable place for characters with right capacity - StringBuilder builder = new StringBuilder(length); - for (int i = 0; i < (length * 2); i += 2) { - final int firstBit = (bitSet.get(i) ? 1 : 0); - final int secondBit = (bitSet.get(i + 1) ? 1 : 0); - final int lastBits = firstBit << 1 | secondBit; - switch (lastBits) { - case 0b00: // 00 is 'A' - builder.append('A'); - break; - case 0b01: // 01 is 'C' - builder.append('C'); - break; - case 0b10: // 10 is 'G' - builder.append('G'); - break; - case 0b11: // 11 is 'T' - builder.append('T'); - break; - } - } - return builder.toString(); - } + private BitSet bitSet() { + return bitSet; + } - public static void main(String[] args) { - final String original = "TAGGGATTAACCGTTATATATATATAGCCATGGATCGATTATATAGGGATTAACCGTTATATATATATAGCCATGGATCGATTATA"; - CompressedGene compressed = new CompressedGene(original); - final String decompressed = compressed.decompress(); - System.out.println(decompressed); - System.out.println("original is the same as decompressed: " + original.equalsIgnoreCase(decompressed)); - } + private void compress(String gene) { + length = gene.length(); + // reserve enough capacity for all of the bits + bitSet = new BitSet(length * 2); + // convert to upper case for consistency + var upperGene = gene.toUpperCase(); + // convert String to bit representation + for (var i = 0; i < length; i++) { + var firstLocation = 2 * i; + var secondLocation = 2 * i + 1; + var charAt = upperGene.charAt(i); + switch (charAt) { + case 'A' -> { // 00 are next two bits + bitSet.set(firstLocation, false); + bitSet.set(secondLocation, false); + } + case 'C' -> { // 01 are next two bits + bitSet.set(firstLocation, false); + bitSet.set(secondLocation, true); + } + case 'G' -> { // 10 are next two bits + bitSet.set(firstLocation, true); + bitSet.set(secondLocation, false); + } + case 'T' -> { // 11 are next two bits + bitSet.set(firstLocation, true); + bitSet.set(secondLocation, true); + } + default -> throw new IllegalArgumentException("Illegal character other than ACGT, position: " + i + ", char: " + charAt); + } + } + } + public String decompress() { + if (bitSet == null) { + return ""; + } + // create a mutable place for characters with right capacity + var builder = new StringBuilder(length); + for (var i = 0; i < (length * 2); i += 2) { + var firstBit = (bitSet.get(i) ? 1 : 0); + var secondBit = (bitSet.get(i + 1) ? 1 : 0); + var lastBits = firstBit << 1 | secondBit; + switch (lastBits) { + case 0b00 -> builder.append('A'); // 00 is 'A' + case 0b01 -> builder.append('C'); // 01 is 'C' + case 0b10 -> builder.append('G'); // 10 is 'G' + case 0b11 -> builder.append('T'); // 11 is 'T' + default -> throw new IllegalArgumentException("Unknown last bits " + lastBits); + } + } + return builder.toString(); + } + + public static void main(String[] args) { + var original = "TABGGGATTAACCGTTATATATATATAGCCATGGATCGATTATATAGGGATTAACCGTTATATATATATAGCCATGGATCGATTATA"; + System.out.println(original.length()); + var compressed = new CompressedGene(original); + System.out.println(compressed.bitSet().length()); + var decompressed = compressed.decompress(); + System.out.println("Original is the same as decompressed: " + original.equals(decompressed)); + } } diff --git a/CCSPiJ/src/chapter1/Fib1.java b/CCSPiJ/src/chapter1/Fib1StackOverflow.java similarity index 93% rename from CCSPiJ/src/chapter1/Fib1.java rename to CCSPiJ/src/chapter1/Fib1StackOverflow.java index cac2fb8..af37d97 100644 --- a/CCSPiJ/src/chapter1/Fib1.java +++ b/CCSPiJ/src/chapter1/Fib1StackOverflow.java @@ -1,4 +1,4 @@ -// Fib1.java +// Fib1StackOverflow.java // From Classic Computer Science Problems in Java Chapter 1 // Copyright 2020 David Kopec // @@ -16,7 +16,7 @@ package chapter1; -public class Fib1 { +public class Fib1StackOverflow { // This method will cause a java.lang.StackOverflowError private static int fib1(int n) { diff --git a/CCSPiJ/src/chapter1/Fib2.java b/CCSPiJ/src/chapter1/Fib2Classic.java similarity index 65% rename from CCSPiJ/src/chapter1/Fib2.java rename to CCSPiJ/src/chapter1/Fib2Classic.java index a39206a..1ec0e04 100644 --- a/CCSPiJ/src/chapter1/Fib2.java +++ b/CCSPiJ/src/chapter1/Fib2Classic.java @@ -1,4 +1,4 @@ -// Fib2.java +// Fib2Classic.java // From Classic Computer Science Problems in Java Chapter 1 // Copyright 2020 David Kopec // @@ -16,16 +16,19 @@ package chapter1; -public class Fib2 { - private static int fib2(int n) { - if (n < 2) { - return n; - } - return fib2(n - 1) + fib2(n - 2); - } +import utils.TimeWatch; - public static void main(String[] args) { - System.out.println(fib2(5)); - System.out.println(fib2(10)); - } +public class Fib2Classic { + + private static int fib2(int n) { + if (n < 2) { + return n; + } + return fib2(n - 1) + fib2(n - 2); + } + + public static void main(String[] args) { + TimeWatch watch = TimeWatch.start(); + System.out.printf("result: %d, time: %ss%n", fib2(45), watch.format()); + } } diff --git a/CCSPiJ/src/chapter1/Fib3.java b/CCSPiJ/src/chapter1/Fib3Memo.java similarity index 54% rename from CCSPiJ/src/chapter1/Fib3.java rename to CCSPiJ/src/chapter1/Fib3Memo.java index cb12273..d4ab21a 100644 --- a/CCSPiJ/src/chapter1/Fib3.java +++ b/CCSPiJ/src/chapter1/Fib3Memo.java @@ -1,4 +1,4 @@ -// Fib3.java +// Fib3Memo.java // From Classic Computer Science Problems in Java Chapter 1 // Copyright 2020 David Kopec // @@ -18,26 +18,27 @@ import java.util.HashMap; import java.util.Map; +import utils.TimeWatch; @SuppressWarnings("boxing") -public class Fib3 { +public class Fib3Memo { - // Map.of() was introduced in Java 9 but returns - // an immutable Map - // This creates a map with 0->0 and 1->1 - // Which represent our base cases - static Map memo = new HashMap<>(Map.of(0, 0, 1, 1)); + // Map.of() was introduced in Java 9 but returns + // an immutable Map + // This creates a map with 0->0 and 1->1 + // Which represent our base cases + static Map memo = new HashMap<>(Map.of(0, 0L, 1, 1L)); - private static int fib3(int n) { - if (!memo.containsKey(n)) { - // memoization step - memo.put(n, fib3(n - 1) + fib3(n - 2)); - } - return memo.get(n); - } + private static long fib3(int n) { + if (!memo.containsKey(n)) { + // memoization step + memo.put(n, fib3(n - 1) + fib3(n - 2)); + } + return memo.get(n); + } - public static void main(String[] args) { - System.out.println(fib3(5)); - System.out.println(fib3(40)); - } + public static void main(String[] args) { + var watch = TimeWatch.start(); + System.out.printf("result: %d, time: %s%n", fib3(100), watch.format()); + } } diff --git a/CCSPiJ/src/chapter1/Fib4.java b/CCSPiJ/src/chapter1/Fib4Iteration.java similarity index 68% rename from CCSPiJ/src/chapter1/Fib4.java rename to CCSPiJ/src/chapter1/Fib4Iteration.java index 77bdb90..4551081 100644 --- a/CCSPiJ/src/chapter1/Fib4.java +++ b/CCSPiJ/src/chapter1/Fib4Iteration.java @@ -1,4 +1,4 @@ -// Fib4.java +// Fib4Iteration.java // From Classic Computer Science Problems in Java Chapter 1 // Copyright 2020 David Kopec // @@ -16,12 +16,16 @@ package chapter1; -public class Fib4 { +import java.util.Locale; +import utils.TimeWatch; - private static int fib4(int n) { - int last = 0, next = 1; // fib(0), fib(1) - for (int i = 0; i < n; i++) { - int oldLast = last; +public class Fib4Iteration { + + private static long fib4(int n) { + var last = 0L; // fib(0) + var next = 1L; // fib(1) + for (var i = 0; i < n; i++) { + var oldLast = last; last = next; next = oldLast + next; } @@ -29,7 +33,7 @@ private static int fib4(int n) { } public static void main(String[] args) { - System.out.println(fib4(5)); - System.out.println(fib4(40)); + TimeWatch watch = TimeWatch.start(); + System.out.printf("result: %d, time: %s%n", fib4(100), watch.format()); } } diff --git a/CCSPiJ/src/chapter1/Fib5.java b/CCSPiJ/src/chapter1/Fib5Stream.java similarity index 52% rename from CCSPiJ/src/chapter1/Fib5.java rename to CCSPiJ/src/chapter1/Fib5Stream.java index b5a0dd8..9c50958 100644 --- a/CCSPiJ/src/chapter1/Fib5.java +++ b/CCSPiJ/src/chapter1/Fib5Stream.java @@ -1,4 +1,4 @@ -// Fib5.java +// Fib5Stream.java // From Classic Computer Science Problems in Java Chapter 1 // Copyright 2020 David Kopec // @@ -16,22 +16,29 @@ package chapter1; -import java.util.stream.IntStream; +import java.util.stream.LongStream; +import utils.TimeWatch; -public class Fib5 { - private int last = 0, next = 1; // fib(0), fib(1) +public class Fib5Stream { - public IntStream stream() { - return IntStream.generate(() -> { - int oldLast = last; - last = next; - next = oldLast + next; - return oldLast; - }); - } + private long last = 0; + private long next = 1; // fib(0), fib(1) - public static void main(String[] args) { - Fib5 fib5 = new Fib5(); - fib5.stream().limit(41).forEachOrdered(System.out::println); - } + public LongStream stream() { + return LongStream.generate(this::fib5); + } + + private long fib5() { + var oldLast = last; + last = next; + next = oldLast + next; + return oldLast; + } + + public static void main(String[] args) { + var watch = TimeWatch.start(); + Fib5Stream fib5Stream = new Fib5Stream(); + fib5Stream.stream().limit(50).forEachOrdered(System.out::println); + System.out.println(watch.format()); + } } diff --git a/CCSPiJ/src/utils/TimeWatch.java b/CCSPiJ/src/utils/TimeWatch.java new file mode 100644 index 0000000..e7b1415 --- /dev/null +++ b/CCSPiJ/src/utils/TimeWatch.java @@ -0,0 +1,40 @@ +package utils; + +import java.util.concurrent.TimeUnit; + +public final class TimeWatch { + + private long starts; + + private TimeWatch() { + reset(); + } + + public static TimeWatch start() { + return new TimeWatch(); + } + + public TimeWatch reset() { + starts = System.currentTimeMillis(); + return this; + } + + public long time() { + long ends = System.currentTimeMillis(); + return ends - starts; + } + + public long time(TimeUnit unit) { + return unit.convert(time(), TimeUnit.MILLISECONDS); + } + + public String format() { + return format(time()); + } + + public String format(long interval) { + final long sec = interval / 1000; + final long ms = interval % 1000; + return String.format("%d.%03ds", sec, ms); + } +}