-
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
1 parent
78fc251
commit f7275f3
Showing
3 changed files
with
222 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,147 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Linq; | ||
using System.Text; | ||
using AdventOfCode.Utilities; | ||
|
||
namespace AdventOfCode | ||
{ | ||
/// <summary> | ||
/// Solver for Day 14 | ||
/// </summary> | ||
public class Day14 | ||
{ | ||
public int Part1(string[] input, int width, int height) | ||
{ | ||
ICollection<Robot> bots = Parse(input); | ||
|
||
for (int i = 0; i < 100; i++) | ||
{ | ||
MoveBots(bots, width, height); | ||
} | ||
|
||
int q1 = 0; | ||
int q2 = 0; | ||
int q3 = 0; | ||
int q4 = 0; | ||
int midX = width / 2; | ||
int midY = height / 2; | ||
|
||
foreach (Robot bot in bots) | ||
{ | ||
if (bot.Position.X < midX) | ||
{ | ||
if (bot.Position.Y < midY) | ||
{ | ||
q1++; | ||
} | ||
else if (bot.Position.Y > midY) | ||
{ | ||
q2++; | ||
} | ||
} | ||
else if (bot.Position.X > midX) | ||
{ | ||
if (bot.Position.Y < midY) | ||
{ | ||
q3++; | ||
} | ||
else if (bot.Position.Y > midY) | ||
{ | ||
q4++; | ||
} | ||
} | ||
} | ||
|
||
return q1 * q2 * q3 * q4; | ||
} | ||
|
||
public int Part2(string[] input, int width, int height) | ||
{ | ||
ICollection<Robot> bots = Parse(input); | ||
|
||
int i = 0; | ||
|
||
while (true) | ||
{ | ||
i++; | ||
|
||
MoveBots(bots, width, height); | ||
|
||
var positions = bots.Select(b => b.Position).ToHashSet(); | ||
|
||
// there's a 32x34 'frame' around the image with the top corner at 40,47 which I found empirically the first time :D | ||
if (positions.Count(p => p.X == 40) == 34 && positions.Count(p => p.Y == 47) == 32) | ||
{ | ||
Print(i, positions, width, height); | ||
return i; | ||
} | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Parse the input | ||
/// </summary> | ||
/// <param name="input">Input</param> | ||
/// <returns>Parsed robots</returns> | ||
private static ICollection<Robot> Parse(string[] input) => input.Select(line => line.Numbers<int>()) | ||
.Select(n => new Robot | ||
{ | ||
Position = (n[0], n[1]), | ||
Vector = (n[2], n[3]) | ||
}) | ||
.ToArray(); | ||
|
||
/// <summary> | ||
/// Move all the bots - this mutates the given collection in-place | ||
/// </summary> | ||
/// <param name="bots">Bots</param> | ||
/// <param name="width">Grid width</param> | ||
/// <param name="height">Grid height</param> | ||
private static void MoveBots(ICollection<Robot> bots, int width, int height) | ||
{ | ||
foreach (Robot bot in bots) | ||
{ | ||
bot.Position = ((bot.Position.X + bot.Vector.X + width) % width, | ||
(bot.Position.Y + bot.Vector.Y + height) % height); | ||
} | ||
} | ||
|
||
/// <summary> | ||
/// Print the grid and indicate where all the bots are | ||
/// </summary> | ||
/// <param name="i">Number of moves to get to this point</param> | ||
/// <param name="bots">Bot positions</param> | ||
/// <param name="width">Grid width</param> | ||
/// <param name="height">Grid height</param> | ||
private static void Print(int i, ISet<Point2D> bots, int width, int height) | ||
{ | ||
if (!Debugger.IsAttached) | ||
{ | ||
return; | ||
} | ||
|
||
StringBuilder s = new StringBuilder(width * height + height * Environment.NewLine.Length); | ||
|
||
for (int y = 0; y < height; y++) | ||
{ | ||
for (int x = 0; x < width; x++) | ||
{ | ||
s.Append(bots.Contains((x, y)) ? '#' : '.'); | ||
} | ||
|
||
s.AppendLine(); | ||
} | ||
|
||
Debug.WriteLine($"Step {i}"); | ||
Debug.WriteLine(s.ToString()); | ||
} | ||
|
||
private class Robot | ||
{ | ||
public Point2D Position { get; set; } | ||
public Point2D Vector { get; init; } | ||
} | ||
} | ||
} |
Binary file not shown.
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,75 @@ | ||
using System.IO; | ||
using Xunit; | ||
using Xunit.Abstractions; | ||
|
||
namespace AdventOfCode.Tests | ||
{ | ||
public class Day14Tests | ||
{ | ||
private readonly ITestOutputHelper output; | ||
private readonly Day14 solver; | ||
|
||
public Day14Tests(ITestOutputHelper output) | ||
{ | ||
this.output = output; | ||
this.solver = new Day14(); | ||
} | ||
|
||
private static string[] GetRealInput() | ||
{ | ||
string[] input = File.ReadAllLines("inputs/day14.txt"); | ||
return input; | ||
} | ||
|
||
private static string[] GetSampleInput() | ||
{ | ||
return new string[] | ||
{ | ||
"p=0,4 v=3,-3", | ||
"p=6,3 v=-1,-3", | ||
"p=10,3 v=-1,2", | ||
"p=2,0 v=2,-1", | ||
"p=0,0 v=1,3", | ||
"p=3,0 v=-2,-2", | ||
"p=7,6 v=-1,-3", | ||
"p=3,0 v=-1,-2", | ||
"p=9,3 v=2,3", | ||
"p=7,3 v=-1,2", | ||
"p=2,4 v=2,-3", | ||
"p=9,5 v=-3,-3", | ||
}; | ||
} | ||
|
||
[Fact] | ||
public void Part1_SampleInput_ProducesCorrectResponse() | ||
{ | ||
var expected = 12; | ||
|
||
var result = solver.Part1(GetSampleInput(), 11, 7); | ||
|
||
Assert.Equal(expected, result); | ||
} | ||
|
||
[Fact] | ||
public void Part1_RealInput_ProducesCorrectResponse() | ||
{ | ||
var expected = 211692000; | ||
|
||
var result = solver.Part1(GetRealInput(), 101, 103); | ||
output.WriteLine($"Day 14 - Part 1 - {result}"); | ||
|
||
Assert.Equal(expected, result); | ||
} | ||
|
||
[Fact] | ||
public void Part2_RealInput_ProducesCorrectResponse() | ||
{ | ||
var expected = 6587; | ||
|
||
var result = solver.Part2(GetRealInput(), 101, 103); | ||
output.WriteLine($"Day 14 - Part 2 - {result}"); | ||
|
||
Assert.Equal(expected, result); | ||
} | ||
} | ||
} |