Skip to content

Commit

Permalink
Day 24
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkAD88 committed Dec 25, 2023
1 parent 75dacea commit e6b925b
Show file tree
Hide file tree
Showing 5 changed files with 567 additions and 0 deletions.
10 changes: 10 additions & 0 deletions 2023/24/NeverTellMeTheOdds.csproj
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>
113 changes: 113 additions & 0 deletions 2023/24/Program.cs
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);
}
137 changes: 137 additions & 0 deletions 2023/24/README.md
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.
Loading

0 comments on commit e6b925b

Please sign in to comment.