java-refresher

Some quick exercises and small projects to help refresh my Java programming knowledge and skills.
git clone https://git.jaderune.net/jbauer/java-refresher
Log | Files | Refs | README | LICENSE

commit 1ddf3370da21d565c6d63f7a9e401d0bfea77fae
parent 0ee588a595285446c83fa822f69b2823aa824315
Author: Jake Bauer <jbauer@paritybit.ca>
Date:   Thu, 18 May 2023 21:54:59 -0400

Improve on the AoC Day 1 solution

Diffstat:
Aaoc-day1/README.md | 2++
Aaoc-day1/better/Elf.java | 7+++++++
Aaoc-day1/better/Main.java | 28++++++++++++++++++++++++++++
Aaoc-day1/better/README | 14++++++++++++++
Aaoc-day1/better/Solver.java | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rfile-operations/aoc-day1/input.txt -> aoc-day1/better/input.txt | 0
Aaoc-day1/worse/Main.java | 28++++++++++++++++++++++++++++
Aaoc-day1/worse/README | 3+++
Aaoc-day1/worse/Solver.java | 75+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Rfile-operations/aoc-day1/input.txt -> aoc-day1/worse/input.txt | 0
Dfile-operations/aoc-day1/Main.java | 22----------------------
Dfile-operations/aoc-day1/Solver.java | 76----------------------------------------------------------------------------
12 files changed, 222 insertions(+), 98 deletions(-)

diff --git a/aoc-day1/README.md b/aoc-day1/README.md @@ -0,0 +1,2 @@ +Practicing some simple Java programming by solving the [Day 1 +challenge](https://adventofcode.com/2022/day/1) from Advent of Code 2022. diff --git a/aoc-day1/better/Elf.java b/aoc-day1/better/Elf.java @@ -0,0 +1,7 @@ +public class Elf { + public int totalCalories; + + public void addCalories (int calories) { + this.totalCalories += calories; + } +} diff --git a/aoc-day1/better/Main.java b/aoc-day1/better/Main.java @@ -0,0 +1,28 @@ +// Using the Advent of Code 2022 Day 1 challenge as a practical example for +// reading and writing to a file. + +import java.util.Scanner; + +public class Main { + public static void main(String[] args) { + System.out.println("Advent of Code 2022, Day 1"); + + Scanner sc = new Scanner(System.in); + System.out.print("File containing input data: "); + String fileName = sc.nextLine(); + + Solver solver = new Solver(fileName); + + int result = solver.solvePartOne(); + long startTime = System.nanoTime(); + System.out.println("Part One: " + result); + long endTime = System.nanoTime(); + System.out.println("Took: " + Long.toString((endTime - startTime) / 1000) + " microseconds"); + + result = solver.solvePartTwo(); + startTime = System.nanoTime(); + System.out.println("Part Two: " + result); + endTime = System.nanoTime(); + System.out.println("Took: " + Long.toString((endTime - startTime) / 1000) + " microseconds"); + } +}; diff --git a/aoc-day1/better/README b/aoc-day1/better/README @@ -0,0 +1,14 @@ +This solution is much more in line with how Java programs are normally +written. The code looks a lot cleaner and more straightforward. Also, even +though the program uses more RAM to store all the Elf objects and their +totalCalories, it runs faster since it does less work overall. + +As measured using hyperfine(1): + +OLD: +Time (mean ± σ): 310.9 ms ± 145.8 ms +Range (min … max): 172.2 ms … 583.5 ms + +NEW: +Time (mean ± σ): 225.2 ms ± 85.5 ms +Range (min … max): 142.2 ms … 392.6 ms diff --git a/aoc-day1/better/Solver.java b/aoc-day1/better/Solver.java @@ -0,0 +1,65 @@ +import java.util.ArrayList; +import java.util.Scanner; +import java.util.Collections; +import java.io.*; + +public class Solver { + private ArrayList<Elf> elves; + + public Solver(String fn) { + elves = new ArrayList<Elf>(); + parseData(fn); + } + + // Fill the list of elves by reading the data in the file + // Finally, sort that list (in reverse order) based on Elf.totalCalories + private void parseData(String fileName) { + try { + File file = new File(fileName); + Scanner fileReader = new Scanner(file); + + Elf newElf = new Elf(); + elves.add(newElf); + + while (fileReader.hasNextLine()) { + String line = fileReader.nextLine(); + if (line.isEmpty()) { + newElf = new Elf(); + elves.add(newElf); + continue; + } + newElf.addCalories(Integer.parseInt(line)); + } + + fileReader.close(); + + Collections.sort(elves, (Elf e1, Elf e2) -> { + if (e1.totalCalories > e2.totalCalories) + return -1; + else if (e1.totalCalories == e2.totalCalories) + return 0; + else + return 1; + }); + } + catch (FileNotFoundException e) { + System.err.println("File " + fileName + " not found!"); + System.exit(1); + } + } + + // Find the number of calories carried by the elf carrying the most + // calories + public int solvePartOne() { + return this.elves.get(0).totalCalories; + } + + // Return the sum of the number of calories carried by the top three + // elves carrying the most calories + public int solvePartTwo() { + return this.elves.get(0).totalCalories + + this.elves.get(1).totalCalories + + this.elves.get(2).totalCalories; + } +} + diff --git a/file-operations/aoc-day1/input.txt b/aoc-day1/better/input.txt diff --git a/aoc-day1/worse/Main.java b/aoc-day1/worse/Main.java @@ -0,0 +1,28 @@ +// Using the Advent of Code 2022 Day 1 challenge as a practical example for +// reading and writing to a file. + +import java.util.Scanner; + +public class Main { + public static void main(String[] args) { + System.out.println("Advent of Code 2022, Day 1"); + + Scanner sc = new Scanner(System.in); + System.out.print("File containing input data: "); + String fileName = sc.nextLine(); + + Solver solver = new Solver(fileName); + + int result = solver.solvePartOne(); + long startTime = System.nanoTime(); + System.out.println("Part One: " + result); + long endTime = System.nanoTime(); + System.out.println("Took: " + Long.toString((endTime - startTime) / 1000) + " microseconds"); + + result = solver.solvePartTwo(); + startTime = System.nanoTime(); + System.out.println("Part Two: " + result); + endTime = System.nanoTime(); + System.out.println("Took: " + Long.toString((endTime - startTime) / 1000) + " microseconds"); + } +}; diff --git a/aoc-day1/worse/README b/aoc-day1/worse/README @@ -0,0 +1,3 @@ +This solution is not that great. It works, but it's also pretty much a copy of +my solution written in C. Check the aoc-day1/better directory for a more +"Java-like" solution. diff --git a/aoc-day1/worse/Solver.java b/aoc-day1/worse/Solver.java @@ -0,0 +1,75 @@ +import java.util.Scanner; +import java.io.*; + +public class Solver { + private String fileName; + + public Solver(String fn) { + fileName = fn; + } + + private Scanner openFile() { + try { + File file = new File(this.fileName); + Scanner sc = new Scanner(file); + return sc; + } + catch (FileNotFoundException e) { + System.err.println("File " + this.fileName + " not found!"); + System.exit(1); + } + return null; + } + + // This feels sloppy + private void arrayInsert(int[] array, int index, int value) { + for (int i = 2; i > index; i--) { + array[i] = array[i-1]; + } + array[index] = value; + } + + // Find the elf carrying the most calories + public int solvePartOne() { + Scanner fileReader = openFile(); + int mostCalories = 0; + int currentCalories = 0; + while (fileReader.hasNextLine()) { + String line = fileReader.nextLine(); + if (line.isEmpty()) { + if (currentCalories > mostCalories) { + mostCalories = currentCalories; + } + currentCalories = 0; + continue; + } + currentCalories += Integer.parseInt(line); + } + fileReader.close(); + return mostCalories; + } + + // Find the top three elves carrying the most calories + public int solvePartTwo() { + Scanner fileReader = openFile(); + int[] bestThree = { 0, 0, 0 }; + int currentCalories = 0; + while (fileReader.hasNextLine()) { + String line = fileReader.nextLine(); + if (line.isEmpty()) { + for (int i = 0; i < 3; i++) { + if (currentCalories > bestThree[i]) { + this.arrayInsert(bestThree, i, currentCalories); + break; + } + } + currentCalories = 0; + continue; + } + currentCalories += Integer.parseInt(line); + } + fileReader.close(); + return bestThree[0] + bestThree[1] + bestThree[2]; + } +} + diff --git a/file-operations/aoc-day1/input.txt b/aoc-day1/worse/input.txt diff --git a/file-operations/aoc-day1/Main.java b/file-operations/aoc-day1/Main.java @@ -1,22 +0,0 @@ -// Using the Advent of Code 2022 Day 1 challenge as a practical example for -// reading and writing to a file. - -import java.util.Scanner; - -public class Main { - public static void main(String[] args) { - System.out.println("Advent of Code 2022, Day 1"); - - Scanner sc = new Scanner(System.in); - System.out.print("File containing input data: "); - String fileName = sc.nextLine(); - - Solver solver = new Solver(fileName); - - int result = solver.solvePartOne(); - System.out.println("Part One: " + result); - - result = solver.solvePartTwo(); - System.out.println("Part Two: " + result); - } -}; diff --git a/file-operations/aoc-day1/Solver.java b/file-operations/aoc-day1/Solver.java @@ -1,76 +0,0 @@ -import java.util.Scanner; -import java.io.*; - -public class Solver { - String fileName; - - public Solver(String fn) { - fileName = fn; - } - - private Scanner openFile() { - try { - System.out.println("Opening " + this.fileName + "..."); - File file = new File(this.fileName); - Scanner sc = new Scanner(file); - return sc; - } - catch (FileNotFoundException e) { - System.err.println("File " + this.fileName + " not found!"); - System.exit(1); - } - return null; - } - - // This feels sloppy - private void arrayInsert(int[] array, int index, int value) { - for (int i = 2; i > index; i--) { - array[i] = array[i-1]; - } - array[index] = value; - } - - // Find the elf carrying the most calories - public int solvePartOne() { - Scanner fileReader = openFile(); - int mostCalories = 0; - int currentCalories = 0; - while (fileReader.hasNextLine()) { - String line = fileReader.nextLine(); - if (line.isEmpty()) { - if (currentCalories > mostCalories) { - mostCalories = currentCalories; - } - currentCalories = 0; - continue; - } - currentCalories += Integer.parseInt(line); - } - fileReader.close(); - return mostCalories; - } - - // Find the top three elves carrying the most calories - public int solvePartTwo() { - Scanner fileReader = openFile(); - int[] bestThree = { 0, 0, 0 }; - int currentCalories = 0; - while (fileReader.hasNextLine()) { - String line = fileReader.nextLine(); - if (line.isEmpty()) { - for (int i = 0; i < 3; i++) { - if (currentCalories > bestThree[i]) { - this.arrayInsert(bestThree, i, currentCalories); - break; - } - } - currentCalories = 0; - continue; - } - currentCalories += Integer.parseInt(line); - } - fileReader.close(); - return bestThree[0] + bestThree[1] + bestThree[2]; - } -} -