feat: solved day 11 part 1 and part 2
This commit is contained in:
@@ -3,6 +3,54 @@
|
|||||||
public class ObserverTests
|
public class ObserverTests
|
||||||
{
|
{
|
||||||
private static readonly string[] ExampleInput = ["125", "17"];
|
private static readonly string[] ExampleInput = ["125", "17"];
|
||||||
|
|
||||||
|
private async Task<string> GetPuzzleInput()
|
||||||
|
{
|
||||||
|
return await File.ReadAllTextAsync(Path.Combine(AppContext.BaseDirectory, "INPUT.txt"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Blink_WhenCalledWithPuzzleInputAnd25Times_ItShouldReturnCorrectNumberOfStones()
|
||||||
|
{
|
||||||
|
var input = await GetPuzzleInput();
|
||||||
|
var stones = input
|
||||||
|
.Split(" ", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
||||||
|
.Select(Stone.From)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var observer = Observer.Of(stones);
|
||||||
|
|
||||||
|
var result = observer.Blink(25);
|
||||||
|
|
||||||
|
await Assert.That(result).IsEqualTo(191690);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Blink_WhenCalledWithPuzzleInputAnd75Times_ItShouldReturnCorrectNumberOfStones()
|
||||||
|
{
|
||||||
|
var input = await GetPuzzleInput();
|
||||||
|
var stones = input
|
||||||
|
.Split(" ", StringSplitOptions.TrimEntries | StringSplitOptions.RemoveEmptyEntries)
|
||||||
|
.Select(Stone.From)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var observer = Observer.Of(stones);
|
||||||
|
|
||||||
|
var result = observer.Blink(75);
|
||||||
|
|
||||||
|
await Assert.That(result).IsEqualTo(228651922369703);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public async Task Blink_WhenCalledWithExampleInputAnd25Times_ItShouldReturnCorrectNumberOfStones()
|
||||||
|
{
|
||||||
|
var stones = ExampleInput.Select(Stone.From).ToList();
|
||||||
|
var observer = Observer.Of(stones);
|
||||||
|
|
||||||
|
var result = observer.Blink(25);
|
||||||
|
|
||||||
|
await Assert.That(result).IsEqualTo(55312);
|
||||||
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
[MethodDataSource(nameof(BlinkTestCases))]
|
[MethodDataSource(nameof(BlinkTestCases))]
|
||||||
@@ -12,14 +60,20 @@ public class ObserverTests
|
|||||||
var observer = Observer.Of(stones);
|
var observer = Observer.Of(stones);
|
||||||
|
|
||||||
var result = observer.Blink(testCase.NumberOfBlinks);
|
var result = observer.Blink(testCase.NumberOfBlinks);
|
||||||
|
|
||||||
await Assert.That(result).IsEqualTo(testCase.ExpectedLineOfStones);
|
await Assert.That(result).IsEqualTo(testCase.ExpectedNumberOfStones);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IEnumerable<Func<BlinkTestCase>> BlinkTestCases()
|
public static IEnumerable<Func<BlinkTestCase>> BlinkTestCases()
|
||||||
{
|
{
|
||||||
yield return () => new(ExampleInput, 0, "125 17");
|
yield return () => new(ExampleInput, 0, 2);
|
||||||
|
yield return () => new(ExampleInput, 1, 3);
|
||||||
|
yield return () => new(ExampleInput, 2, 4);
|
||||||
|
yield return () => new(ExampleInput, 3, 5);
|
||||||
|
yield return () => new(ExampleInput, 4, 9);
|
||||||
|
yield return () => new(ExampleInput, 5, 13);
|
||||||
|
yield return () => new(ExampleInput, 6, 22);
|
||||||
}
|
}
|
||||||
|
|
||||||
public record BlinkTestCase(string[] Stones, int NumberOfBlinks, string ExpectedLineOfStones);
|
public record BlinkTestCase(string[] Stones, int NumberOfBlinks, long ExpectedNumberOfStones);
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
namespace PlutonianPebbles;
|
||||||
|
|
||||||
|
class Observer
|
||||||
|
{
|
||||||
|
private readonly List<Stone> _stones;
|
||||||
|
|
||||||
|
private Observer(List<Stone> stones)
|
||||||
|
{
|
||||||
|
_stones = stones;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Observer Of(List<Stone> stones) => new(stones);
|
||||||
|
|
||||||
|
public long Blink(int times)
|
||||||
|
{
|
||||||
|
var stoneCounts = _stones.GroupBy(s => s)
|
||||||
|
.ToDictionary(g => g.Key, g => (long)g.Count());
|
||||||
|
|
||||||
|
for (var blinks = 0; blinks < times; blinks++)
|
||||||
|
{
|
||||||
|
var nextCounts = new Dictionary<Stone, long>();
|
||||||
|
|
||||||
|
foreach (var (stone, count) in stoneCounts)
|
||||||
|
{
|
||||||
|
var transformed = stone.Transform();
|
||||||
|
|
||||||
|
foreach (var result in transformed)
|
||||||
|
{
|
||||||
|
if (nextCounts.ContainsKey(result))
|
||||||
|
{
|
||||||
|
nextCounts[result] += count;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
nextCounts[result] = count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stoneCounts = nextCounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
return stoneCounts.Values.Sum();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
using PlutonianPebbles;
|
||||||
|
|
||||||
if (args.Length is 0)
|
if (args.Length is 0)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Please provide a path to the input file.");
|
Console.WriteLine("Please provide a path to the input file.");
|
||||||
@@ -25,69 +27,9 @@ var stones = input
|
|||||||
|
|
||||||
var observer = Observer.Of(stones);
|
var observer = Observer.Of(stones);
|
||||||
|
|
||||||
var result = observer.Blink(25);
|
var times = isPart2 ? 75 : 25;
|
||||||
|
|
||||||
|
var result = observer.Blink(times);
|
||||||
|
|
||||||
stopwatch.Stop();
|
stopwatch.Stop();
|
||||||
Console.WriteLine($". ({stopwatch.ElapsedMilliseconds}ms)");
|
Console.WriteLine($"The number of stones is {result}. ({stopwatch.ElapsedMilliseconds}ms)");
|
||||||
|
|
||||||
class Observer
|
|
||||||
{
|
|
||||||
private readonly List<Stone> _stones;
|
|
||||||
|
|
||||||
private Observer(List<Stone> stones)
|
|
||||||
{
|
|
||||||
_stones = stones;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Observer Of(List<Stone> stones) => new(stones);
|
|
||||||
|
|
||||||
public string Blink(int times)
|
|
||||||
{
|
|
||||||
if (times < 1)
|
|
||||||
{
|
|
||||||
return string.Join(" ", _stones);
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
record Stone
|
|
||||||
{
|
|
||||||
private readonly string _engravedValue;
|
|
||||||
|
|
||||||
private Stone(string engravedValue)
|
|
||||||
{
|
|
||||||
_engravedValue = engravedValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Stone From(string engraving) => new(engraving);
|
|
||||||
|
|
||||||
public List<Stone> Transform()
|
|
||||||
{
|
|
||||||
if (_engravedValue is "0")
|
|
||||||
{
|
|
||||||
return [new Stone("1")];
|
|
||||||
}
|
|
||||||
|
|
||||||
var hasOddNumberOfDigits = _engravedValue.Length % 2 is not 0;
|
|
||||||
|
|
||||||
if (hasOddNumberOfDigits)
|
|
||||||
{
|
|
||||||
var engravedNumber = int.Parse(_engravedValue);
|
|
||||||
var newEngravedValue = engravedNumber * 2024;
|
|
||||||
return [new(newEngravedValue.ToString())];
|
|
||||||
}
|
|
||||||
|
|
||||||
var middleIndex = _engravedValue.Length / 2;
|
|
||||||
var leftDigits = _engravedValue[..middleIndex].TrimStart('0');
|
|
||||||
var rightDigits = _engravedValue[middleIndex..].TrimStart('0');
|
|
||||||
|
|
||||||
return [new(leftDigits), new(rightDigits)];
|
|
||||||
}
|
|
||||||
|
|
||||||
public override string ToString()
|
|
||||||
{
|
|
||||||
return _engravedValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
namespace PlutonianPebbles;
|
||||||
|
|
||||||
|
record Stone
|
||||||
|
{
|
||||||
|
private readonly string _engravedValue;
|
||||||
|
|
||||||
|
private Stone(string engravedValue)
|
||||||
|
{
|
||||||
|
_engravedValue = engravedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Stone From(string engraving) => new(engraving);
|
||||||
|
|
||||||
|
public List<Stone> Transform()
|
||||||
|
{
|
||||||
|
if (_engravedValue is "0")
|
||||||
|
{
|
||||||
|
return [new Stone("1")];
|
||||||
|
}
|
||||||
|
|
||||||
|
var hasOddNumberOfDigits = _engravedValue.Length % 2 is not 0;
|
||||||
|
|
||||||
|
if (hasOddNumberOfDigits)
|
||||||
|
{
|
||||||
|
var engravedNumber = long.Parse(_engravedValue);
|
||||||
|
var newEngravedValue = engravedNumber * 2024;
|
||||||
|
return [new(newEngravedValue.ToString())];
|
||||||
|
}
|
||||||
|
|
||||||
|
var middleIndex = _engravedValue.Length / 2;
|
||||||
|
var leftDigits = long.Parse(_engravedValue[..middleIndex]);
|
||||||
|
var rightDigits = long.Parse(_engravedValue[middleIndex..]);
|
||||||
|
|
||||||
|
return [new(leftDigits.ToString()), new(rightDigits.ToString())];
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return _engravedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -54,3 +54,4 @@ dotnet build
|
|||||||
| 08 | [Problem](./08/PROBLEM.md) | [Solution](./08/ResonantCollinearity/) | Without some help from chat I don't know where I'd be...to be fair the description kind of mislead me. |
|
| 08 | [Problem](./08/PROBLEM.md) | [Solution](./08/ResonantCollinearity/) | Without some help from chat I don't know where I'd be...to be fair the description kind of mislead me. |
|
||||||
| 09 | [Problem](./09/PROBLEM.md) | [Solution](./09/DiskFragmenter/) | Doing things with indexes is error prone. |
|
| 09 | [Problem](./09/PROBLEM.md) | [Solution](./09/DiskFragmenter/) | Doing things with indexes is error prone. |
|
||||||
| 10 | [Problem](./10/PROBLEM.md) | [Solution](./10/HoofIt/) | I recognized the solution for this based on pattern from last year. Solved using BFS. |
|
| 10 | [Problem](./10/PROBLEM.md) | [Solution](./10/HoofIt/) | I recognized the solution for this based on pattern from last year. Solved using BFS. |
|
||||||
|
| 11 | [Problem](./11/PROBLEM.md) | [Solution](./11/PlutonianPebbles/) | Dictionary > List |
|
||||||
|
|||||||
Reference in New Issue
Block a user