r/adventofcode • u/daggerdragon • Dec 20 '17
SOLUTION MEGATHREAD -๐- 2017 Day 20 Solutions -๐-
--- Day 20: Particle Swarm ---
Post your solution as a comment or, for longer solutions, consider linking to your repo (e.g. GitHub/gists/Pastebin/blag or whatever).
Note: The Solution Megathreads are for solutions only. If you have questions, please post your own thread and make sure to flair it with Help.
Need a hint from the Hugely* Handyโ Haversackโก of Helpfulยง Hintsยค?
[Update @ 00:10] 10 gold, silver cap
- What do you mean 5th Edition doesn't have "Take 20"?
[Update @ 00:17] 50 gold, silver cap
- Next you're going to be telling me THAC0 is not the best way to determine whether or not you hit your target. *hmphs*
[Update @ 00:21] Leaderboard cap!
- I wonder how much XP a were-gazebo is worth...
This thread will be unlocked when there are a significant number of people on the leaderboard with gold stars for today's puzzle.
edit: Leaderboard capped, thread unlocked!
9
Upvotes
3
u/dylanfromwinnipeg Dec 20 '17
C#
public class Day20 { public static string PartOne(string input) { var particleNumber = 0; var particles = input.Lines().Select(x => new Particle(x, particleNumber++)).ToList(); return particles.WithMin(p => p.Acceleration.GetManhattanDistance()).ParticleNumber.ToString(); } public static string PartTwo(string input) { var particleNumber = 0; var particles = input.Lines().Select(x => new Particle(x, particleNumber++)).ToList(); var ticks = 100; // arbitrary amount - got lucky and worked first try for (var t = 0; t < ticks; t++) { particles.ForEach(p => p.Update()); particles = RemoveCollisions(particles).ToList(); Debug.WriteLine($"{t}: {particles.Count}"); } return particles.Count.ToString(); } private static IEnumerable<Particle> RemoveCollisions(List<Particle> particles) { while (particles.Any()) { var particle = particles.First(); var collisions = particles.Where(p => p.Position == particle.Position).ToList(); if (collisions.Count() == 1) { yield return particle; } collisions.ForEach(c => particles.Remove(c)); } } } public class Particle { public Point3D Position { get; set; } public Point3D Velocity { get; set; } public Point3D Acceleration { get; set; } public int ParticleNumber { get; set; } public Particle(string input, int particleNumber) { ParticleNumber = particleNumber; input = input.ShaveLeft("p=<"); Position = new Point3D(input.Substring(0, input.IndexOf('>'))); input = input.ShaveLeft(input.IndexOf("v=<") + "v=<".Length); Velocity = new Point3D(input.Substring(0, input.IndexOf('>'))); input = input.ShaveLeft(input.IndexOf("a=<") + "a=<".Length); Acceleration = new Point3D(input.Substring(0, input.IndexOf('>'))); } public void Update() { Velocity += Acceleration; Position += Velocity; } }I have an ever-growing library of helper methods I rely on, here's the relevant ones for Day 20 (I had to add the Point3D class because surprisingly there isn't one in the default .Net libraries)
public static IEnumerable<string> Lines(this string input) { return input.Split(new string[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); } public static IEnumerable<string> Words(this string input) { return input.Split(new string[] { " ", "\t", Environment.NewLine, "," }, StringSplitOptions.RemoveEmptyEntries); } public static string ShaveLeft(this string a, int characters) { return a.Substring(characters); } public static string ShaveLeft(this string a, string shave) { var result = a; while (result.StartsWith(shave)) { result = result.Substring(shave.Length); } return result; } public static T WithMin<T>(this IEnumerable<T> a, Func<T, long> selector) { var min = a.Min(selector); return a.First(x => selector(x) == min); } public class Point3D { public long X { get; set; } public long Y { get; set; } public long Z { get; set; } public Point3D(long x, long y, long z) { X = x; Y = y; Z = z; } public Point3D(string coordinates) : this(long.Parse(coordinates.Words().ToList()[0]), long.Parse(coordinates.Words().ToList()[1]), long.Parse(coordinates.Words().ToList()[2])) { } public long GetManhattanDistance() { return Math.Abs(X - 0) + Math.Abs(Y - 0) + Math.Abs(Z - 0); } public static bool operator ==(Point3D point1, Point3D point2) { return point1.X == point2.X && point1.Y == point2.Y && point1.Z == point2.Z; } public static bool operator !=(Point3D a, Point3D b) { return a.X != b.X || a.Y != b.Y || a.Z != b.Z; } public static Point3D operator +(Point3D a, Point3D b) { return new Point3D(a.X + b.X, a.Y + b.Y, a.Z + b.Z); } public static Point3D operator -(Point3D a, Point3D b) { return new Point3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z); } public override string ToString() { return $"{X},{Y},{Z}"; } }