-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
567 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
|
||
<PropertyGroup> | ||
<OutputType>Exe</OutputType> | ||
<TargetFramework>net8.0</TargetFramework> | ||
<ImplicitUsings>enable</ImplicitUsings> | ||
<Nullable>enable</Nullable> | ||
</PropertyGroup> | ||
|
||
</Project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
// Day 24 | ||
|
||
using System.Numerics; | ||
|
||
var sample = new MemoryStream(""" | ||
19, 13, 30 @ -2, 1, -2 | ||
18, 19, 22 @ -1, -1, -2 | ||
20, 25, 34 @ -2, -2, -4 | ||
12, 31, 28 @ -1, -2, -1 | ||
20, 19, 15 @ 1, -5, -3 | ||
"""u8.ToArray()); | ||
|
||
List<Hailstone> stones = [ ]; | ||
|
||
using var input = Console.IsInputRedirected ? Console.OpenStandardInput() : sample; | ||
using var reader = new StreamReader(input); | ||
while (!reader.EndOfStream) | ||
{ | ||
stones.Add(Hailstone.Parse(reader.ReadLine()!)); | ||
} | ||
|
||
var min = float.Parse(args[0]); | ||
var max = float.Parse(args[1]); | ||
var useZ = bool.Parse(args[2]); | ||
|
||
// Find where the vectors intercept on X&Y (use args 7 27 false) | ||
var part1 = stones.SelectMany(stone => | ||
stones | ||
.Skip(stones.IndexOf(stone) + 1) | ||
.Select(other => | ||
( | ||
A: stone.Position, | ||
AV: stone.Vector, | ||
B: other.Position, | ||
BV: other.Vector, | ||
Intersect: FindIntersection( | ||
stone.Position with { Z = 0 }, | ||
stone.Vector with { Z = 0 }, | ||
other.Position with { Z = 0 }, | ||
other.Vector with { Z = 0 }))) | ||
.Where(result => result.Intersect.HasValue) | ||
.Where(result => result.Intersect.Value.X >= min && result.Intersect.Value.X <= max) | ||
.Where(result => result.Intersect.Value.Y >= min && result.Intersect.Value.Y <= max) | ||
.Where(result => !useZ || (result.Intersect.Value.Z >= min && result.Intersect.Value.Z <= max)) | ||
.Where(result => | ||
{ | ||
switch (result.AV.X) | ||
{ | ||
// Make sure the movement was FORWARD in time and not BACKWARD | ||
case < 0 when !(result.Intersect.Value.X <= result.A.X): | ||
case > 0 when !(result.Intersect.Value.X >= result.A.X): | ||
return false; | ||
} | ||
|
||
switch (result.BV.X) | ||
{ | ||
case < 0 when !(result.Intersect.Value.X <= result.B.X): | ||
case > 0 when !(result.Intersect.Value.X >= result.B.X): | ||
return false; | ||
} | ||
|
||
return true; | ||
}) | ||
.Select(result => result) | ||
).ToArray(); | ||
|
||
Console.WriteLine($"Part 1 : {part1.Length}"); | ||
|
||
return; | ||
|
||
Vector3? FindIntersection(Vector3 point1, Vector3 vector1, Vector3 point2, Vector3 vector2) | ||
{ | ||
var cross = Vector3.Cross(vector1, vector2); | ||
var denominator = cross.GetMagnitude() * cross.GetMagnitude(); | ||
if (denominator == 0) | ||
{ | ||
return null; | ||
} | ||
|
||
var p = point2 - point1; | ||
var t1 = Vector3.Dot(Vector3.Cross(p, vector2), cross) / denominator; | ||
var t2 = Vector3.Dot(Vector3.Cross(p, vector1), cross) / denominator; | ||
|
||
var intersection = point1 + vector1 * t1; | ||
return intersection; | ||
} | ||
|
||
internal class Hailstone(Vector3 position, Vector3 vector) | ||
{ | ||
private static readonly char[] separators = { ',', '@' }; | ||
|
||
public Vector3 Position => position; | ||
|
||
public Vector3 Vector => vector; | ||
|
||
public static Hailstone Parse(string line) | ||
{ | ||
var parts = line | ||
.Split(separators, StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries) | ||
.Select(float.Parse) | ||
.ToArray(); | ||
|
||
return new Hailstone( | ||
new Vector3(parts[0], parts[1], parts[2]), | ||
new Vector3(parts[3], parts[4], parts[5])); | ||
} | ||
} | ||
|
||
internal static class Vector3Extensions | ||
{ | ||
public static float GetMagnitude(this Vector3 input) => | ||
MathF.Sqrt(input.X * input.X + input.Y * input.Y + input.Z * input.Z); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
```text | ||
``` | ||
|
||
## Part One | ||
|
||
At one point I'm positive I knew the formula for vector algebra that this required. I certainly couldn't remember it though. I had to Google/Bing/Copilot my way to the algorithm and then figure out how to bend it so that I could get my answer. | ||
|
||
## Part Two | ||
|
||
Yeah no clue how to do this (yet). Looked at a couple of other solves on GitHub and it looks like they're all using prepackaged libraries to do the work. Not sure how I feel about that. | ||
|
||
----- | ||
|
||
--- Day 24: Never Tell Me The Odds --- | ||
|
||
It seems like something is going wrong with the snow-making process. Instead of forming snow, the water that's been absorbed into the air seems to be forming hail! | ||
|
||
Maybe there's something you can do to break up the hailstones? | ||
|
||
Due to strong, probably-magical winds, the hailstones are all flying through the air in perfectly linear trajectories. You make a note of each hailstone's **position** and **velocity** (your puzzle input). For example: | ||
|
||
```text | ||
19, 13, 30 @ -2, 1, -2 | ||
18, 19, 22 @ -1, -1, -2 | ||
20, 25, 34 @ -2, -2, -4 | ||
12, 31, 28 @ -1, -2, -1 | ||
20, 19, 15 @ 1, -5, -3 | ||
``` | ||
|
||
Each line of text corresponds to the position and velocity of a single hailstone. The positions indicate where the hailstones are **right now** (at time `0`). The velocities are constant and indicate exactly how far each hailstone will move in **one nanosecond.** | ||
|
||
Each line of text uses the format `px py pz @ vx vy vz`. For instance, the hailstone specified by `20, 19, 15 @ 1, -5, -3` has initial X position `20`, Y position `19`, Z position `15`, X velocity `1`, Y velocity `-5`, and Z velocity `-3`. After one nanosecond, the hailstone would be at `21, 14, 12`. | ||
|
||
Perhaps you won't have to do anything. How likely are the hailstones to collide with each other and smash into tiny ice crystals? | ||
|
||
To estimate this, consider only the X and Y axes; **ignore the Z axis**. Looking **forward in time**, how many of the hailstones' **paths** will intersect within a test area? (The hailstones themselves don't have to collide, just test for intersections between the paths they will trace.) | ||
|
||
In this example, look for intersections that happen with an X and Y position each at least `7` and at most `27`; in your actual data, you'll need to check a much larger test area. Comparing all pairs of hailstones' future paths produces the following results: | ||
|
||
```text | ||
Hailstone A: 19, 13, 30 @ -2, 1, -2 | ||
Hailstone B: 18, 19, 22 @ -1, -1, -2 | ||
Hailstones' paths will cross inside the test area (at x=14.333, y=15.333). | ||
Hailstone A: 19, 13, 30 @ -2, 1, -2 | ||
Hailstone B: 20, 25, 34 @ -2, -2, -4 | ||
Hailstones' paths will cross inside the test area (at x=11.667, y=16.667). | ||
Hailstone A: 19, 13, 30 @ -2, 1, -2 | ||
Hailstone B: 12, 31, 28 @ -1, -2, -1 | ||
Hailstones' paths will cross outside the test area (at x=6.2, y=19.4). | ||
Hailstone A: 19, 13, 30 @ -2, 1, -2 | ||
Hailstone B: 20, 19, 15 @ 1, -5, -3 | ||
Hailstones' paths crossed in the past for hailstone A. | ||
Hailstone A: 18, 19, 22 @ -1, -1, -2 | ||
Hailstone B: 20, 25, 34 @ -2, -2, -4 | ||
Hailstones' paths are parallel; they never intersect. | ||
Hailstone A: 18, 19, 22 @ -1, -1, -2 | ||
Hailstone B: 12, 31, 28 @ -1, -2, -1 | ||
Hailstones' paths will cross outside the test area (at x=-6, y=-5). | ||
Hailstone A: 18, 19, 22 @ -1, -1, -2 | ||
Hailstone B: 20, 19, 15 @ 1, -5, -3 | ||
Hailstones' paths crossed in the past for both hailstones. | ||
Hailstone A: 20, 25, 34 @ -2, -2, -4 | ||
Hailstone B: 12, 31, 28 @ -1, -2, -1 | ||
Hailstones' paths will cross outside the test area (at x=-2, y=3). | ||
Hailstone A: 20, 25, 34 @ -2, -2, -4 | ||
Hailstone B: 20, 19, 15 @ 1, -5, -3 | ||
Hailstones' paths crossed in the past for hailstone B. | ||
Hailstone A: 12, 31, 28 @ -1, -2, -1 | ||
Hailstone B: 20, 19, 15 @ 1, -5, -3 | ||
Hailstones' paths crossed in the past for both hailstones. | ||
``` | ||
|
||
So, in this example, `2` hailstones' future paths cross inside the boundaries of the test area. | ||
|
||
However, you'll need to search a much larger test area if you want to see if any hailstones might collide. Look for intersections that happen with an X and Y position each at least `200000000000000` and at most `400000000000000`. Disregard the Z axis entirely. | ||
|
||
Considering only the X and Y axes, check all pairs of hailstones' future paths for intersections. **How many of these intersections occur within the test area?** | ||
|
||
Your puzzle answer was `11246`. | ||
|
||
The first half of this puzzle is complete! It provides one gold star: * | ||
|
||
--- Part Two --- | ||
|
||
Upon further analysis, it doesn't seem like **any** hailstones will naturally collide. It's up to you to fix that! | ||
|
||
You find a rock on the ground nearby. While it seems extremely unlikely, if you throw it just right, you should be able to **hit every hailstone in a single throw!** | ||
|
||
You can use the probably-magical winds to reach **any integer position** you like and to propel the rock at **any integer velocity**. Now **including the Z axis** in your calculations, if you throw the rock at time `0`, where do you need to be so that the rock **perfectly collides with every hailstone?** Due to probably-magical inertia, the rock won't slow down or change direction when it collides with a hailstone. | ||
|
||
In the example above, you can achieve this by moving to position `24, 13, 10` and throwing the rock at velocity `-3, 1, 2`. If you do this, you will hit every hailstone as follows: | ||
|
||
```text | ||
Hailstone: 19, 13, 30 @ -2, 1, -2 | ||
Collision time: 5 | ||
Collision position: 9, 18, 20 | ||
Hailstone: 18, 19, 22 @ -1, -1, -2 | ||
Collision time: 3 | ||
Collision position: 15, 16, 16 | ||
Hailstone: 20, 25, 34 @ -2, -2, -4 | ||
Collision time: 4 | ||
Collision position: 12, 17, 18 | ||
Hailstone: 12, 31, 28 @ -1, -2, -1 | ||
Collision time: 6 | ||
Collision position: 6, 19, 22 | ||
Hailstone: 20, 19, 15 @ 1, -5, -3 | ||
Collision time: 1 | ||
Collision position: 21, 14, 12 | ||
``` | ||
|
||
Above, each hailstone is identified by its initial position and its velocity. Then, the time and position of that hailstone's collision with your rock are given. | ||
|
||
After 1 nanosecond, the rock has **exactly the same position** as one of the hailstones, obliterating it into ice dust! Another hailstone is smashed to bits two nanoseconds after that. After a total of 6 nanoseconds, all of the hailstones have been destroyed. | ||
|
||
So, at time `0`, the rock needs to be at X position `24`, Y position `13`, and Z position `10`. Adding these three coordinates together produces `47`. (Don't add any coordinates from the rock's velocity.) | ||
|
||
Determine the exact position and velocity the rock needs to have at time `0` so that it perfectly collides with every hailstone. **What do you get if you add up the X, Y, and Z coordinates of that initial position?** | ||
|
||
Answer: (still unsolved :cry::cry::cry:) | ||
|
||
Although it hasn't changed, you can still get your puzzle input. | ||
|
||
You can also [Share] this puzzle. |
Oops, something went wrong.