1
0
www.mikescher.com/www/statics/aoc/2019/12_solution-2.ts

155 lines
3.1 KiB
TypeScript

namespace AdventOfCode2019_12_2
{
const DAY = 12;
const PROBLEM = 2;
export async function run()
{
let input = await AdventOfCode.getInput(DAY);
if (input == null) return;
let moons = input
.trim()
.split(new RegExp('\r?\n'))
.map(p => p.replace(new RegExp('[<>\\sxyz=]', 'g'), ""))
.map(p => p.split(",").map(p => parseInt(p)))
.map(p => new Moon(p[0], p[1], p[2]));
let cycletimes = [];
for(let dim=0; dim<3; dim++)
{
let moons1d = moons.map(m => Moon1D.createFromMoon(m, dim));
const cycle = getCycleTime(moons1d);
AdventOfCode.outputConsole(`CycleTime Dim[${dim}] ==> ${cycle}`);
cycletimes.push(cycle);
}
const totalctime = lcm(cycletimes)
AdventOfCode.output(DAY, PROBLEM, totalctime.toString());
}
function lcm(v: number[]) // least common multiple
{
return v.map(p => BigInt(p)).reduce((a,b) => lcm2(a,b));
}
function lcm2(a: bigint, b: bigint): bigint // least common multiple
{
return (a*b)/gcd2(a,b);
}
function gcd(v: bigint[]): bigint
{
return v.reduce((a,b) => gcd2(a,b));
}
function gcd2(x: bigint, y: bigint): bigint
{
x = (x<0) ? (-x) : (x);
y = (y<0) ? (-y) : (y);
while(y) { var t = y; y = x % y; x = t; }
return x;
}
function getCycleTime(moons: Moon1D[]): number
{
const orig = moons.map(m => m.clone());
for(let time=0;; time++)
{
step(moons)
if (eq(orig, moons)) return time+1;
}
}
function eq(a: Moon1D[], b: Moon1D[]): boolean
{
for(let i=0; i<a.length; i++)
{
if (a[i].pos != b[i].pos) return false;
if (a[i].vel != b[i].vel) return false;
}
return true;
}
function step(moons: Moon1D[])
{
for(let i1=0; i1<moons.length; i1++)
for(let i2=i1+1; i2<moons.length; i2++)
{
if (moons[i1].pos<moons[i2].pos) { moons[i1].vel++; moons[i2].vel--; }
if (moons[i1].pos>moons[i2].pos) { moons[i1].vel--; moons[i2].vel++; }
}
for(let i=0; i<moons.length; i++)
{
moons[i].pos += moons[i].vel;
}
}
class Moon1D
{
pos: number;
vel: number;
constructor(p: number, v:number)
{
this.pos=p;
this.vel=v;
}
static createFromMoon(m: Moon, idx: number): Moon1D
{
if (idx == 0) { return new Moon1D(m.x, m.dx); }
if (idx == 1) { return new Moon1D(m.y, m.dy); }
if (idx == 2) { return new Moon1D(m.z, m.dz); }
throw "Invalid index";
}
public clone(): Moon1D
{
return new Moon1D(this.pos, this.vel);
}
}
class Moon
{
x: number;
y: number;
z: number;
dx: number = 0;
dy: number = 0;
dz: number = 0;
constructor(x: number, y: number, z: number)
{
this.x=x;
this.y=y;
this.z=z;
}
public toString(): string {
return `pos=<x=${this.x}, y=${this.y}, z=${this.z}>, vel=<x=${this.dx}, y=${this.dy}, z=${this.dz}> [pot=${this.getPotEnergy()}|kin=${this.getKinEnergy()}] => ${this.getEnergy()}`;
}
public getPotEnergy(): number {
return Math.abs(this.x)+Math.abs(this.y)+Math.abs(this.z);
}
public getKinEnergy(): number {
return Math.abs(this.dx)+Math.abs(this.dy)+Math.abs(this.dz);
}
public getEnergy(): number {
return this.getPotEnergy() * this.getKinEnergy();
}
}
}