|
@@ -1,5 +1,40 @@
|
|
|
-import { LoadInput } from "../common.ts";
|
|
|
-import * as util from "util";
|
|
|
+import { Inspect, LoadInput } from "../common.ts";
|
|
|
+
|
|
|
+/* Directions */
|
|
|
+const Directions = {
|
|
|
+ NORTH: {
|
|
|
+ X: 0,
|
|
|
+ Y: -1,
|
|
|
+ },
|
|
|
+ SOUTH: {
|
|
|
+ X: 0,
|
|
|
+ Y: 1,
|
|
|
+ },
|
|
|
+ EAST: {
|
|
|
+ X: 1,
|
|
|
+ Y: 0,
|
|
|
+ },
|
|
|
+ WEST: {
|
|
|
+ X: -1,
|
|
|
+ Y: 0,
|
|
|
+ },
|
|
|
+ NORTH_EAST: {
|
|
|
+ X: 1,
|
|
|
+ Y: -1,
|
|
|
+ },
|
|
|
+ NORTH_WEST: {
|
|
|
+ X: -1,
|
|
|
+ Y: -1,
|
|
|
+ },
|
|
|
+ SOUTH_EAST: {
|
|
|
+ X: 1,
|
|
|
+ Y: 1,
|
|
|
+ },
|
|
|
+ SOUTH_WEST: {
|
|
|
+ X: -1,
|
|
|
+ Y: 1,
|
|
|
+ },
|
|
|
+}
|
|
|
|
|
|
const tests = [
|
|
|
"467..114..",
|
|
@@ -14,11 +49,16 @@ const tests = [
|
|
|
".664.598..",
|
|
|
];
|
|
|
|
|
|
+// Build the find
|
|
|
const testMap = BuildSchematicsMap(tests);
|
|
|
+// Find all possible parts
|
|
|
let testParts = ParseSchematics(testMap);
|
|
|
-testParts = ValidateEngineParts(testParts);
|
|
|
+// Validate those parts
|
|
|
+testParts = ValidateEngineParts(testParts, testMap);
|
|
|
|
|
|
-console.log(util.inspect(testParts, { breakLength: Infinity, depth: 256, colors: true }));
|
|
|
+// Get out output
|
|
|
+const sumOfPartNumbers = testParts.reduce((accumulator, part) => accumulator += part.PartNumber, 0);
|
|
|
+console.log(`The sum of part numbers is: ${sumOfPartNumbers}`);
|
|
|
|
|
|
/**
|
|
|
* Parse the schematics to find all possible Engine Parts
|
|
@@ -88,11 +128,76 @@ function ParseSchematics(schematicsMap: string[][]): EnginePart[] {
|
|
|
* symbol other than `.`.
|
|
|
*
|
|
|
* @param {EnginePart[]} potentialParts All potential Engine Parts
|
|
|
+ * @param {string[][]} schematicsMap A 2D grid of characters making up a schematic
|
|
|
* @returns {EnginePart[]} A filtered list of all valid Engine Parts
|
|
|
*/
|
|
|
-function ValidateEngineParts(potentialParts: EnginePart[]): EnginePart[] {
|
|
|
+function ValidateEngineParts(potentialParts: EnginePart[], schematicsMap: string[][]): EnginePart[] {
|
|
|
+ const validParts: EnginePart[] = [];
|
|
|
+
|
|
|
+ for (const part of potentialParts) {
|
|
|
+ for (const point of part.Coordinates) {
|
|
|
+ if (BordersASymbol(point, schematicsMap)) {
|
|
|
+ validParts.push(part);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return validParts;
|
|
|
+}
|
|
|
|
|
|
- return [];
|
|
|
+/**
|
|
|
+ * Check if a point on the schematics map borders a symbol
|
|
|
+ *
|
|
|
+ * A symbol is any character other than a digit or a period.
|
|
|
+ *
|
|
|
+ * @param point A point on the schematics map
|
|
|
+ * @param schematicsMap A 2D grid of characters making up a schematic
|
|
|
+ * @returns {boolean} Whether the point borders a symbol or not
|
|
|
+ */
|
|
|
+function BordersASymbol(point: Vector2, schematicsMap: string[][]): boolean {
|
|
|
+ // Initialize all border chars as NOPs
|
|
|
+ let northernBorder = ".";
|
|
|
+ let easternBorder = ".";
|
|
|
+ let southernBorder = ".";
|
|
|
+ let westernBorder = ".";
|
|
|
+ let northEastBorder = ".";
|
|
|
+ let northWestBorder = ".";
|
|
|
+ let southEastBorder = ".";
|
|
|
+ let southWestBorder = ".";
|
|
|
+ // Check what borders exist
|
|
|
+ const northExists = !!schematicsMap[point.Y + Directions.NORTH.Y];
|
|
|
+ const southExists = !!schematicsMap[point.Y + Directions.SOUTH.Y];
|
|
|
+ const eastExists = !!schematicsMap[point.Y][point.X + Directions.EAST.X];
|
|
|
+ const westExists = !!schematicsMap[point.Y][point.X + Directions.WEST.X];
|
|
|
+ // Find the border chars
|
|
|
+ if(northExists) {
|
|
|
+ northernBorder = schematicsMap[point.Y + Directions.NORTH.Y][point.X + Directions.NORTH.X];
|
|
|
+ if(eastExists) {
|
|
|
+ northEastBorder = schematicsMap[point.Y + Directions.NORTH_EAST.Y][point.X + Directions.NORTH_EAST.X];
|
|
|
+ }
|
|
|
+ if(westExists) {
|
|
|
+ northWestBorder = schematicsMap[point.Y + Directions.NORTH_WEST.Y][point.X + Directions.NORTH_WEST.X];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if(southExists) {
|
|
|
+ southernBorder = schematicsMap[point.Y + Directions.SOUTH.Y][point.X + Directions.SOUTH.X];
|
|
|
+ if(eastExists) {
|
|
|
+ southEastBorder = schematicsMap[point.Y + Directions.SOUTH_EAST.Y][point.X + Directions.SOUTH_EAST.X];
|
|
|
+ }
|
|
|
+ if(westExists) {
|
|
|
+ southWestBorder = schematicsMap[point.Y + Directions.SOUTH_WEST.Y][point.X + Directions.SOUTH_WEST.X];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (eastExists) {
|
|
|
+ easternBorder = schematicsMap[point.Y + Directions.EAST.Y][point.X + Directions.EAST.X];
|
|
|
+ }
|
|
|
+ if (westExists) {
|
|
|
+ westernBorder = schematicsMap[point.Y + Directions.WEST.Y][point.X + Directions.WEST.X];
|
|
|
+ }
|
|
|
+ // Combine all bordering characters into one long string
|
|
|
+ const allBorders = northernBorder + easternBorder + southernBorder + westernBorder + northEastBorder + northWestBorder + southEastBorder + southWestBorder;
|
|
|
+
|
|
|
+ return /[^0-9\.]/.test(allBorders);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -127,4 +232,4 @@ type SchematicsSymbol = {
|
|
|
type Vector2 = {
|
|
|
X: number,
|
|
|
Y: number,
|
|
|
-};
|
|
|
+};
|