Advertisement
Guest User

Advent of Code: Day 3

a guest
Dec 28th, 2019
781
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import * as fs from "fs";
  2.  
  3. interface Point {
  4.   x: number;
  5.   y: number;
  6. }
  7.  
  8. class Vector {
  9.   public readonly p: Point;
  10.   public readonly q: Point;
  11.  
  12.   private readonly max_x: number;
  13.   private readonly min_x: number;
  14.   private readonly max_y: number;
  15.   private readonly min_y: number;
  16.  
  17.   public constructor(p: Point, q: Point) {
  18.     this.p = p;
  19.     this.q = q;
  20.  
  21.     this.max_x = Math.max(this.p.x, this.q.x);
  22.     this.min_x = Math.min(this.p.x, this.q.x);
  23.     this.max_y = Math.max(this.p.y, this.q.y);
  24.     this.min_y = Math.min(this.p.y, this.q.y);
  25.   }
  26.  
  27.   public get A(): number {
  28.     return this.q.y - this.p.y;
  29.   }
  30.  
  31.   public get B(): number {
  32.     return this.q.x - this.p.x;
  33.   }
  34.  
  35.   public get C(): number {
  36.     return this.A * this.p.x + this.B * this.p.y;
  37.   }
  38.  
  39.   public get length(): number {
  40.     return this.max_x - this.min_x + this.max_y - this.min_y;
  41.   }
  42.  
  43.   public hasPoint(point: Point): boolean {
  44.     if (point.x < this.min_x || point.x > this.max_x || point.y < this.min_y || point.y > this.max_y) {
  45.       return false;
  46.     }
  47.  
  48.     return true;
  49.   }
  50.  
  51.   public static getIntersectionPoint(v1: Vector, v2: Vector): Point {
  52.     const denominator: number = v1.A * v2.B - v2.A * v1.B;
  53.  
  54.     if (denominator === 0) {
  55.       return null;
  56.     }
  57.  
  58.     const x: number = (v2.B * v1.C - v1.B * v2.C) / denominator;
  59.     const y: number = (v1.A * v2.C - v2.A * v1.C) / denominator;
  60.  
  61.     return {x: x, y: y} as Point;
  62.   }
  63. }
  64.  
  65. const getDistance = (p: Point, q: Point): number => {
  66.   return Math.abs(p.x - q.x) + Math.abs(p.y - q.y);
  67. };
  68.  
  69. const getVectors = (currentPoint: Point, changes: string[]): Vector[] => {
  70.   const vectors: Vector[] = [];
  71.  
  72.   for (let i: number = 0; i < changes.length; i++) {
  73.     const change: string = changes[i];
  74.     const direction: string = change.slice(0, 1);
  75.     const magnitude: number = Number(change.slice(1));
  76.     const targetPoint: Point = {...currentPoint};
  77.  
  78.     switch (direction) {
  79.       case "U":
  80.         targetPoint.y += magnitude;
  81.         break;
  82.       case "D":
  83.         targetPoint.y -= magnitude;
  84.         break;
  85.       case "L":
  86.         targetPoint.x -= magnitude;
  87.         break;
  88.       case "R":
  89.         targetPoint.x += magnitude;
  90.         break;
  91.     }
  92.  
  93.     vectors.push(new Vector({...currentPoint}, targetPoint));
  94.  
  95.     currentPoint = targetPoint;
  96.   }
  97.  
  98.   return vectors;
  99. };
  100.  
  101. const input: string = fs.readFileSync("./assets/wires.txt", "utf8");
  102.  
  103. console.time("exec");
  104. const point0: Point = {x: 0, y: 0} as Point;
  105.  
  106. // convert the input into vectors
  107. const instructions: string[][] = input.split("\n").slice(0, -1).map((path: string) => path.split(","));
  108. const wire1: Vector[] = getVectors({...point0}, instructions[0]);
  109. const wire2: Vector[] = getVectors({...point0}, instructions[1]);
  110.  
  111. let shortestDistance: number;
  112. let shortestPath: number;
  113.  
  114. for (let i: number = 0; i < wire1.length; i++) {
  115.   const v1: Vector = wire1[i];
  116.  
  117.   for (let j: number = 0; j < wire2.length; j++) {
  118.     const v2: Vector = wire2[j];
  119.     const ip: Point = Vector.getIntersectionPoint(v1, v2);
  120.  
  121.     if (ip && v1.hasPoint(ip) && v2.hasPoint(ip)) {
  122.       const distance: number = getDistance(point0, ip);
  123.  
  124.       // ignore intersection at origin
  125.       if (distance === 0) {
  126.         continue;
  127.       }
  128.  
  129.       if (!shortestDistance) {
  130.         const wire1Length: number = wire1.slice(0, i).reduce((sum: number, v: Vector) => sum += v.length, 0);
  131.         const wire2Length: number = wire2.slice(0, j).reduce((sum: number, v: Vector) => sum += v.length, 0);
  132.  
  133.         shortestPath = wire1Length + wire2Length + getDistance(v1.p, ip) + getDistance(v2.p, ip);
  134.         shortestDistance = distance;
  135.       } else if (distance < shortestDistance) {
  136.         shortestDistance = distance;
  137.       }
  138.     }
  139.   }
  140. }
  141. console.timeEnd("exec");
  142.  
  143. console.log("distance to closest intersection", shortestDistance);
  144. console.log("steps to first intersection", shortestPath);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement