From 200abbb81514e84dab01967aadd39bc425d0bd22 Mon Sep 17 00:00:00 2001 From: Christopher Bohn <bohn@unl.edu> Date: Wed, 30 Nov 2022 20:14:13 -0600 Subject: [PATCH] getting ready for 2022 Advent of Code --- 2022/README.md | 4 + 2022/pom.xml | 25 +++++ .../java/edu/unl/cse/bohn/ImportData.java | 91 +++++++++++++++++++ 2022/src/main/java/edu/unl/cse/bohn/Main.java | 49 ++++++++++ .../main/java/edu/unl/cse/bohn/Puzzle.java | 28 ++++++ 2022/src/main/java/edu/unl/cse/bohn/year2021 | 1 + 2022/src/main/resources/apikeys.TEMPLATE | 3 + scaffolding/ImportData.java | 91 +++++++++++++++++++ scaffolding/Main.java | 49 ++++++++++ scaffolding/Puzzle.java | 28 ++++++ 10 files changed, 369 insertions(+) create mode 100644 2022/README.md create mode 100644 2022/pom.xml create mode 100644 2022/src/main/java/edu/unl/cse/bohn/ImportData.java create mode 100644 2022/src/main/java/edu/unl/cse/bohn/Main.java create mode 100644 2022/src/main/java/edu/unl/cse/bohn/Puzzle.java create mode 120000 2022/src/main/java/edu/unl/cse/bohn/year2021 create mode 100644 2022/src/main/resources/apikeys.TEMPLATE create mode 100644 scaffolding/ImportData.java create mode 100644 scaffolding/Main.java create mode 100644 scaffolding/Puzzle.java diff --git a/2022/README.md b/2022/README.md new file mode 100644 index 0000000..03da0a2 --- /dev/null +++ b/2022/README.md @@ -0,0 +1,4 @@ +# 2022 Advent of Code Solutions + +## Day 1 + diff --git a/2022/pom.xml b/2022/pom.xml new file mode 100644 index 0000000..22efcff --- /dev/null +++ b/2022/pom.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>edu.unl.cse.bohn</groupId> + <artifactId>AdventOfCoding</artifactId> + <version>1.0-SNAPSHOT</version> + + <properties> + <maven.compiler.source>17</maven.compiler.source> + <maven.compiler.target>17</maven.compiler.target> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <dependencies> + <dependency> + <groupId>com.googlecode.json-simple</groupId> + <artifactId>json-simple</artifactId> + <version>1.1.1</version> + </dependency> + </dependencies> + +</project> \ No newline at end of file diff --git a/2022/src/main/java/edu/unl/cse/bohn/ImportData.java b/2022/src/main/java/edu/unl/cse/bohn/ImportData.java new file mode 100644 index 0000000..e472acd --- /dev/null +++ b/2022/src/main/java/edu/unl/cse/bohn/ImportData.java @@ -0,0 +1,91 @@ +package edu.unl.cse.bohn; + +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLConnection; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; + +public class ImportData { + + public static final String FILENAME = "apikeys.json"; + + protected final String protocol; + protected final String host; + protected final String path; + protected final String apiKey; + + @SuppressWarnings("unused") + public static List<String> readFile(String filename) throws IOException { + List<String> data = new LinkedList<>(); + BufferedReader bufferedReader; + bufferedReader = new BufferedReader(new FileReader(filename)); + while (bufferedReader.ready()) { + data.add(bufferedReader.readLine()); + } + return data; + } + + public ImportData(String apiKeyName, int year, int day) { + String apiKey; + protocol = "https"; + host = "adventofcode.com"; + path = "/" + year + "/day/" + day + "/input"; + try { + apiKey = getApiKey(apiKeyName); + } catch (IOException ioException) { + System.err.println("Could not retrieve API key: " + ioException.getMessage()); + apiKey = null; + } + this.apiKey = apiKey; + } + + protected String getApiKey(String apiKeyName) throws IOException { + JSONObject apiKeyJson; + try (InputStreamReader inputStreamReader = new InputStreamReader( + Objects.requireNonNull(ImportData.class.getClassLoader().getResourceAsStream(FILENAME)))) { + apiKeyJson = (JSONObject)new JSONParser().parse(inputStreamReader); + } catch (NullPointerException nullPointerException) { + FileNotFoundException newException = new FileNotFoundException("File " + FILENAME + " not found."); + newException.initCause(nullPointerException); + throw newException; + } catch (ParseException parseException) { + throw new IOException("Error while parsing file " + FILENAME + ".", parseException); + } + if (!apiKeyJson.containsKey(apiKeyName)) { + System.err.println("WARNING! Could not locate API key named " + apiKeyName + " in file " + FILENAME + "."); + } + String apiKey = apiKeyJson.get(apiKeyName).toString(); + if (apiKey.equals("")) { + System.err.println("WARNING! API key named " + apiKeyName + " in file " + FILENAME + " is blank."); + } + return apiKey; + } + + public List<String> importData() throws IOException { + List<String> data = new LinkedList<>(); + BufferedReader bufferedReader; + try { + URLConnection connection = new URI(protocol, host, path, null).toURL().openConnection(); + connection.setRequestProperty("Cookie", apiKey); + bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + } catch (URISyntaxException | MalformedURLException originalException) { + throw new IOException("Could not retrieve usable data from " + host + ".", originalException); + } + while (bufferedReader.ready()) { + data.add(bufferedReader.readLine()); + } + return data; + } +} diff --git a/2022/src/main/java/edu/unl/cse/bohn/Main.java b/2022/src/main/java/edu/unl/cse/bohn/Main.java new file mode 100644 index 0000000..875e4b5 --- /dev/null +++ b/2022/src/main/java/edu/unl/cse/bohn/Main.java @@ -0,0 +1,49 @@ +package edu.unl.cse.bohn; + +import java.lang.reflect.InvocationTargetException; +import java.util.Calendar; +import java.util.Scanner; + +public class Main { + public static final String defaultApiKey = "aoc"; + + private static String getUserInput(String prompt, String defaultValue, Scanner scanner) { + System.out.print(prompt + " [" + defaultValue + "]: "); + String userInput = scanner.nextLine(); + return userInput.equals("") ? defaultValue : userInput; + } + + public static void main(String... arguments) { + Scanner scanner = new Scanner(System.in); + String apiKey = getUserInput("Enter API key", defaultApiKey, scanner); + Calendar calendar = Calendar.getInstance(); + int year = Integer.parseInt(getUserInput("Enter puzzle year", + Integer.toString(calendar.get(Calendar.YEAR)), scanner)); + int day = Integer.parseInt(getUserInput("Enter puzzle day", + Integer.toString(calendar.get(Calendar.DAY_OF_MONTH)), scanner)); + boolean useProductionData = getUserInput("Use sample data (Y/N)?", "Y", scanner).toUpperCase().charAt(0) != 'Y'; + scanner.close(); + ImportData dataSource = new ImportData(apiKey, year, day); + String className = Main.class.getPackageName() + ".year" + year + ".Day" + day; + Puzzle puzzle = null; + try { + puzzle = (Puzzle)Class.forName(className).getConstructors()[0].newInstance(useProductionData); + } catch (ClassNotFoundException classNotFoundException) { + System.err.println("Could not find class " + className); + System.exit(1); + } catch (InstantiationException ignored) { + System.err.println(className + " is an abstract class."); + System.exit(1); + } catch (IllegalAccessException ignored) { + System.err.println("The requested constructor for " + className + " is inaccessible."); + System.exit(1); + } catch (InvocationTargetException invocationTargetException) { + System.err.println("The constructor for " + className + " threw an exception."); + System.err.println(invocationTargetException.getMessage()); + Throwable originalException = invocationTargetException.getCause(); + System.err.println("Caused by: " + originalException); + System.exit(1); + } + puzzle.solvePuzzle(dataSource); + } +} diff --git a/2022/src/main/java/edu/unl/cse/bohn/Puzzle.java b/2022/src/main/java/edu/unl/cse/bohn/Puzzle.java new file mode 100644 index 0000000..100704c --- /dev/null +++ b/2022/src/main/java/edu/unl/cse/bohn/Puzzle.java @@ -0,0 +1,28 @@ +package edu.unl.cse.bohn; + +import java.io.IOException; +import java.util.List; + +public abstract class Puzzle { + protected String sampleData = ""; + protected boolean isProductionReady; + + public Puzzle(boolean isProductionReady) { + this.isProductionReady = isProductionReady; + } + + public abstract long computePart1(List<String> data); + public abstract long computePart2(List<String> data); + + public void solvePuzzle(ImportData dataSource) { + List<String> data = null; + try { + data = isProductionReady ? dataSource.importData() : List.of(sampleData.split(System.lineSeparator())); + } catch (IOException ioException) { + System.err.println("Could not retrieve data: " + ioException); + System.exit(1); + } + System.out.println("Part 1: " + computePart1(data)); + System.out.println("Part 2: " + computePart2(data)); + } +} diff --git a/2022/src/main/java/edu/unl/cse/bohn/year2021 b/2022/src/main/java/edu/unl/cse/bohn/year2021 new file mode 120000 index 0000000..9eb349c --- /dev/null +++ b/2022/src/main/java/edu/unl/cse/bohn/year2021 @@ -0,0 +1 @@ +../../../../../../../../2021/src/main/java/edu/unl/cse/bohn/year2021 \ No newline at end of file diff --git a/2022/src/main/resources/apikeys.TEMPLATE b/2022/src/main/resources/apikeys.TEMPLATE new file mode 100644 index 0000000..13923fa --- /dev/null +++ b/2022/src/main/resources/apikeys.TEMPLATE @@ -0,0 +1,3 @@ +{ + "aoc": "" +} diff --git a/scaffolding/ImportData.java b/scaffolding/ImportData.java new file mode 100644 index 0000000..e472acd --- /dev/null +++ b/scaffolding/ImportData.java @@ -0,0 +1,91 @@ +package edu.unl.cse.bohn; + +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; +import org.json.simple.parser.ParseException; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLConnection; +import java.util.LinkedList; +import java.util.List; +import java.util.Objects; + +public class ImportData { + + public static final String FILENAME = "apikeys.json"; + + protected final String protocol; + protected final String host; + protected final String path; + protected final String apiKey; + + @SuppressWarnings("unused") + public static List<String> readFile(String filename) throws IOException { + List<String> data = new LinkedList<>(); + BufferedReader bufferedReader; + bufferedReader = new BufferedReader(new FileReader(filename)); + while (bufferedReader.ready()) { + data.add(bufferedReader.readLine()); + } + return data; + } + + public ImportData(String apiKeyName, int year, int day) { + String apiKey; + protocol = "https"; + host = "adventofcode.com"; + path = "/" + year + "/day/" + day + "/input"; + try { + apiKey = getApiKey(apiKeyName); + } catch (IOException ioException) { + System.err.println("Could not retrieve API key: " + ioException.getMessage()); + apiKey = null; + } + this.apiKey = apiKey; + } + + protected String getApiKey(String apiKeyName) throws IOException { + JSONObject apiKeyJson; + try (InputStreamReader inputStreamReader = new InputStreamReader( + Objects.requireNonNull(ImportData.class.getClassLoader().getResourceAsStream(FILENAME)))) { + apiKeyJson = (JSONObject)new JSONParser().parse(inputStreamReader); + } catch (NullPointerException nullPointerException) { + FileNotFoundException newException = new FileNotFoundException("File " + FILENAME + " not found."); + newException.initCause(nullPointerException); + throw newException; + } catch (ParseException parseException) { + throw new IOException("Error while parsing file " + FILENAME + ".", parseException); + } + if (!apiKeyJson.containsKey(apiKeyName)) { + System.err.println("WARNING! Could not locate API key named " + apiKeyName + " in file " + FILENAME + "."); + } + String apiKey = apiKeyJson.get(apiKeyName).toString(); + if (apiKey.equals("")) { + System.err.println("WARNING! API key named " + apiKeyName + " in file " + FILENAME + " is blank."); + } + return apiKey; + } + + public List<String> importData() throws IOException { + List<String> data = new LinkedList<>(); + BufferedReader bufferedReader; + try { + URLConnection connection = new URI(protocol, host, path, null).toURL().openConnection(); + connection.setRequestProperty("Cookie", apiKey); + bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream())); + } catch (URISyntaxException | MalformedURLException originalException) { + throw new IOException("Could not retrieve usable data from " + host + ".", originalException); + } + while (bufferedReader.ready()) { + data.add(bufferedReader.readLine()); + } + return data; + } +} diff --git a/scaffolding/Main.java b/scaffolding/Main.java new file mode 100644 index 0000000..875e4b5 --- /dev/null +++ b/scaffolding/Main.java @@ -0,0 +1,49 @@ +package edu.unl.cse.bohn; + +import java.lang.reflect.InvocationTargetException; +import java.util.Calendar; +import java.util.Scanner; + +public class Main { + public static final String defaultApiKey = "aoc"; + + private static String getUserInput(String prompt, String defaultValue, Scanner scanner) { + System.out.print(prompt + " [" + defaultValue + "]: "); + String userInput = scanner.nextLine(); + return userInput.equals("") ? defaultValue : userInput; + } + + public static void main(String... arguments) { + Scanner scanner = new Scanner(System.in); + String apiKey = getUserInput("Enter API key", defaultApiKey, scanner); + Calendar calendar = Calendar.getInstance(); + int year = Integer.parseInt(getUserInput("Enter puzzle year", + Integer.toString(calendar.get(Calendar.YEAR)), scanner)); + int day = Integer.parseInt(getUserInput("Enter puzzle day", + Integer.toString(calendar.get(Calendar.DAY_OF_MONTH)), scanner)); + boolean useProductionData = getUserInput("Use sample data (Y/N)?", "Y", scanner).toUpperCase().charAt(0) != 'Y'; + scanner.close(); + ImportData dataSource = new ImportData(apiKey, year, day); + String className = Main.class.getPackageName() + ".year" + year + ".Day" + day; + Puzzle puzzle = null; + try { + puzzle = (Puzzle)Class.forName(className).getConstructors()[0].newInstance(useProductionData); + } catch (ClassNotFoundException classNotFoundException) { + System.err.println("Could not find class " + className); + System.exit(1); + } catch (InstantiationException ignored) { + System.err.println(className + " is an abstract class."); + System.exit(1); + } catch (IllegalAccessException ignored) { + System.err.println("The requested constructor for " + className + " is inaccessible."); + System.exit(1); + } catch (InvocationTargetException invocationTargetException) { + System.err.println("The constructor for " + className + " threw an exception."); + System.err.println(invocationTargetException.getMessage()); + Throwable originalException = invocationTargetException.getCause(); + System.err.println("Caused by: " + originalException); + System.exit(1); + } + puzzle.solvePuzzle(dataSource); + } +} diff --git a/scaffolding/Puzzle.java b/scaffolding/Puzzle.java new file mode 100644 index 0000000..100704c --- /dev/null +++ b/scaffolding/Puzzle.java @@ -0,0 +1,28 @@ +package edu.unl.cse.bohn; + +import java.io.IOException; +import java.util.List; + +public abstract class Puzzle { + protected String sampleData = ""; + protected boolean isProductionReady; + + public Puzzle(boolean isProductionReady) { + this.isProductionReady = isProductionReady; + } + + public abstract long computePart1(List<String> data); + public abstract long computePart2(List<String> data); + + public void solvePuzzle(ImportData dataSource) { + List<String> data = null; + try { + data = isProductionReady ? dataSource.importData() : List.of(sampleData.split(System.lineSeparator())); + } catch (IOException ioException) { + System.err.println("Could not retrieve data: " + ioException); + System.exit(1); + } + System.out.println("Part 1: " + computePart1(data)); + System.out.println("Part 2: " + computePart2(data)); + } +} -- GitLab