# HG changeset patch # User Jordi GutiƩrrez Hermoso # Date 1513845451 18000 # Node ID 8db386034a68dcb71f7b86beef8c52c7bc457ee1 # Parent 836d284fff87e444466385bdfa6118fadbb22644 day 20 diff --git a/2017/day20.d b/2017/day20.d new file mode 100644 --- /dev/null +++ b/2017/day20.d @@ -0,0 +1,86 @@ +import std.stdio; +import std.string: split; +import std.conv: to; +import std.algorithm: map, filter, minElement, sum, any; +import std.array: array; +import std.math: sqrt; +import std.range: enumerate; + +struct particle { + double[3] pos; + double[3] vel; + double[3] acc; +} + +auto parseLine(string line) { + auto p = line.split(", ").map!( + x => x[3..$-1].split(",").map!(to!double).array.to!(double[3]) + ); + particle res = {p[0], p[1], p[2]}; + return res; +} + +auto norm(double[3] v) { + return v[].map!(x => x*x).sum.sqrt; +} + +auto unit(particle p) { + auto + pos = p.pos, + vel = p.vel, + acc = p.acc; + pos[] /= pos.norm; + vel[] /= vel.norm; + acc[] /= acc.norm; + particle u = {pos, vel, acc}; + return u; +} + +auto slowestParticle(particle[] particles) { + // This should use minIndex, from later Phobos + auto norms = particles.map!(p => p.acc.norm); + auto min = norms.minElement; + return norms.enumerate.filter!(x => x[1] == min).front[0]; +} + +void evolve(ref particle p) { + p.vel[] += p.acc[]; + p.pos[] += p.vel[]; +} + +void collide(ref particle[] particles) { + int[double[3]] counter; + foreach(p; particles) { + counter[p.pos] = counter.get(p.pos, 0) + 1; + } + particles = particles.filter!(p => counter[p.pos] == 1).array; +} + +bool canCollide(particle[] particles) { + return particles.map!(unit).any!( + function(particle p) { + // Check if the position, velocity, and acceleration fail to be + // mostly collinear + double[3] diff1 = p.pos, diff2 = p.vel; + diff1[] -= p.vel[]; + diff2[] -= p.acc[]; + return norm(diff1) > 0.001 || norm(diff2) > 0.001; + } + ); +} + +auto evolve(particle[] particles) { + while(particles.canCollide) { + collide(particles); + foreach(ref particle; particles) { + evolve(particle); + } + } + return particles.length; +} + +void main(string[] args) { + auto particles = File(args[1]).byLineCopy.map!(parseLine).array; + writeln(particles.slowestParticle); + writeln(particles.evolve); +}