Mercurial > hg > aoc
comparison 2017/day20/app.d @ 33:bc652fa0a645
Move all solutions to per-day subdirs
author | Jordi Gutiérrez Hermoso <jordigh@octave.org> |
---|---|
date | Tue, 09 Jan 2018 21:50:37 -0500 |
parents | 2017/day20.d@8db386034a68 |
children |
comparison
equal
deleted
inserted
replaced
32:763c88851b91 | 33:bc652fa0a645 |
---|---|
1 import std.stdio; | |
2 import std.string: split; | |
3 import std.conv: to; | |
4 import std.algorithm: map, filter, minElement, sum, any; | |
5 import std.array: array; | |
6 import std.math: sqrt; | |
7 import std.range: enumerate; | |
8 | |
9 struct particle { | |
10 double[3] pos; | |
11 double[3] vel; | |
12 double[3] acc; | |
13 } | |
14 | |
15 auto parseLine(string line) { | |
16 auto p = line.split(", ").map!( | |
17 x => x[3..$-1].split(",").map!(to!double).array.to!(double[3]) | |
18 ); | |
19 particle res = {p[0], p[1], p[2]}; | |
20 return res; | |
21 } | |
22 | |
23 auto norm(double[3] v) { | |
24 return v[].map!(x => x*x).sum.sqrt; | |
25 } | |
26 | |
27 auto unit(particle p) { | |
28 auto | |
29 pos = p.pos, | |
30 vel = p.vel, | |
31 acc = p.acc; | |
32 pos[] /= pos.norm; | |
33 vel[] /= vel.norm; | |
34 acc[] /= acc.norm; | |
35 particle u = {pos, vel, acc}; | |
36 return u; | |
37 } | |
38 | |
39 auto slowestParticle(particle[] particles) { | |
40 // This should use minIndex, from later Phobos | |
41 auto norms = particles.map!(p => p.acc.norm); | |
42 auto min = norms.minElement; | |
43 return norms.enumerate.filter!(x => x[1] == min).front[0]; | |
44 } | |
45 | |
46 void evolve(ref particle p) { | |
47 p.vel[] += p.acc[]; | |
48 p.pos[] += p.vel[]; | |
49 } | |
50 | |
51 void collide(ref particle[] particles) { | |
52 int[double[3]] counter; | |
53 foreach(p; particles) { | |
54 counter[p.pos] = counter.get(p.pos, 0) + 1; | |
55 } | |
56 particles = particles.filter!(p => counter[p.pos] == 1).array; | |
57 } | |
58 | |
59 bool canCollide(particle[] particles) { | |
60 return particles.map!(unit).any!( | |
61 function(particle p) { | |
62 // Check if the position, velocity, and acceleration fail to be | |
63 // mostly collinear | |
64 double[3] diff1 = p.pos, diff2 = p.vel; | |
65 diff1[] -= p.vel[]; | |
66 diff2[] -= p.acc[]; | |
67 return norm(diff1) > 0.001 || norm(diff2) > 0.001; | |
68 } | |
69 ); | |
70 } | |
71 | |
72 auto evolve(particle[] particles) { | |
73 while(particles.canCollide) { | |
74 collide(particles); | |
75 foreach(ref particle; particles) { | |
76 evolve(particle); | |
77 } | |
78 } | |
79 return particles.length; | |
80 } | |
81 | |
82 void main(string[] args) { | |
83 auto particles = File(args[1]).byLineCopy.map!(parseLine).array; | |
84 writeln(particles.slowestParticle); | |
85 writeln(particles.evolve); | |
86 } |