changeset 26:8db386034a68

day 20
author Jordi Gutiérrez Hermoso <jordigh@octave.org>
date Thu, 21 Dec 2017 03:37:31 -0500
parents 836d284fff87
children 8bfcc543f85f
files 2017/day20.d
diffstat 1 files changed, 86 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
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);
+}