feat: solve part 2
This commit is contained in:
@@ -10,12 +10,31 @@ public class MapTests
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TestData.CountTurnsTestData), MemberType = typeof(TestData))]
|
||||
[MemberData(nameof(TestData.CountStepsTestData), MemberType = typeof(TestData))]
|
||||
public void CountStepsToZ_WhenGivenMap_ItShouldReturnNumberOfSteps(string[] input, int expected)
|
||||
{
|
||||
Map.Parse(input).CountStepsToZ().Should().Be(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(TestData.CountStepsToAllZNodesData), MemberType = typeof(TestData))]
|
||||
public void CountStepsToAllZNodes_WhenGivenMap_ItShouldReturnNumberOfSteps(string[] input, long expected)
|
||||
{
|
||||
Map.Parse(input).CountStepsToAllZNodes().Should().Be(expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindPrimeFactors_WhenGivenNumber_ItShouldReturnPrimeFactors()
|
||||
{
|
||||
new Map([], []).FindPrimeFactors(11911).Should().BeEquivalentTo([43, 277]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FindLeastCommonMultiple_WhenGivenNumbers_ItShouldReturnLeastCommonMultiple()
|
||||
{
|
||||
new Map([], []).FindLeastCommonMultiple([16343, 11911, 20221, 21883, 13019, 19667]).Should().Be(13524038372771);
|
||||
}
|
||||
|
||||
public static class TestData
|
||||
{
|
||||
private static readonly string[] MapInput =
|
||||
@@ -31,7 +50,9 @@ public class MapTests
|
||||
"ZZZ = (ZZZ, ZZZ)",
|
||||
];
|
||||
|
||||
public static IEnumerable<object[]> CountTurnsTestData =>
|
||||
private static readonly string[] Input = File.ReadAllLines("INPUT.txt");
|
||||
|
||||
public static IEnumerable<object[]> CountStepsTestData =>
|
||||
new List<object[]>
|
||||
{
|
||||
new object[]
|
||||
@@ -41,11 +62,38 @@ public class MapTests
|
||||
},
|
||||
new object[]
|
||||
{
|
||||
File.ReadAllLines("INPUT.txt"),
|
||||
Input,
|
||||
13019
|
||||
}
|
||||
};
|
||||
|
||||
public static IEnumerable<object[]> CountStepsToAllZNodesData =>
|
||||
new List<object[]>
|
||||
{
|
||||
new object[]
|
||||
{
|
||||
new string[]
|
||||
{
|
||||
"LR",
|
||||
"",
|
||||
"11A = (11B, XXX)",
|
||||
"11B = (XXX, 11Z)",
|
||||
"11Z = (11B, XXX)",
|
||||
"22A = (22B, XXX)",
|
||||
"22B = (22C, 22C)",
|
||||
"22C = (22Z, 22Z)",
|
||||
"22Z = (22B, 22B)",
|
||||
"XXX = (XXX, XXX)",
|
||||
},
|
||||
6
|
||||
},
|
||||
new object[]
|
||||
{
|
||||
Input,
|
||||
13524038372771
|
||||
}
|
||||
};
|
||||
|
||||
public static IEnumerable<object[]> ParseMapTestData =>
|
||||
new List<object[]>
|
||||
{
|
||||
|
||||
@@ -18,18 +18,22 @@ public class Program
|
||||
return -2;
|
||||
}
|
||||
|
||||
var isPart2 = args.Length > 1 && args[1] == "part2";
|
||||
var input = await File.ReadAllLinesAsync(args[0]);
|
||||
|
||||
var stopwatch = new Stopwatch();
|
||||
stopwatch.Start();
|
||||
|
||||
var result = Map.Parse(input).CountStepsToZ();
|
||||
var map = Map.Parse(input);
|
||||
var result = isPart2
|
||||
? map.CountStepsToAllZNodes()
|
||||
: map.CountStepsToZ();
|
||||
|
||||
stopwatch.Stop();
|
||||
|
||||
Console.WriteLine($"The number of steps to Z is {result}. ({stopwatch.ElapsedMilliseconds}ms)");
|
||||
Console.WriteLine($"The number of steps is {result}. ({stopwatch.ElapsedMilliseconds}ms)");
|
||||
|
||||
return result;
|
||||
return (int)result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +74,91 @@ public class Map(
|
||||
|
||||
return steps;
|
||||
}
|
||||
|
||||
// This method finds the prime factors of a given number.
|
||||
// It takes an integer 'number' as input and returns a list of prime factors.
|
||||
|
||||
public List<long> FindPrimeFactors(long number)
|
||||
{
|
||||
var factors = new List<long>();
|
||||
|
||||
// Start with the smallest prime number, 2.
|
||||
var divisor = 2;
|
||||
|
||||
// Continue until the number is reduced to 2 or less.
|
||||
while (number >= 2)
|
||||
{
|
||||
// If the number is divisible by the current divisor,
|
||||
if (number % divisor == 0)
|
||||
{
|
||||
// Add the divisor to the list of factors.
|
||||
factors.Add(divisor);
|
||||
// Divide the number by the divisor to reduce it.
|
||||
number /= divisor;
|
||||
}
|
||||
else
|
||||
{
|
||||
// If the number is not divisible by the current divisor, increment the divisor.
|
||||
divisor++;
|
||||
}
|
||||
}
|
||||
|
||||
return factors;
|
||||
}
|
||||
|
||||
public long FindLeastCommonMultiple(List<long> numbers)
|
||||
{
|
||||
var primeFactors = numbers.Select(FindPrimeFactors).ToList();
|
||||
|
||||
var uniquePrimeFactors = primeFactors
|
||||
.SelectMany(pf => pf)
|
||||
.Distinct()
|
||||
.ToList();
|
||||
|
||||
var maxPrimeFactors = uniquePrimeFactors
|
||||
.Select(upf => primeFactors.Max(pf => pf.Count(f => f == upf)))
|
||||
.ToList();
|
||||
|
||||
var result = uniquePrimeFactors
|
||||
.Zip(maxPrimeFactors)
|
||||
.Aggregate(
|
||||
(long)1,
|
||||
(acc, b) =>
|
||||
// b.First is the prime factor
|
||||
// b.Second is the number of times it occurs
|
||||
acc * (long)Math.Pow(b.First, b.Second)
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public long CountStepsToAllZNodes()
|
||||
{
|
||||
var startNodes = Nodes.Where(n => n.Current.EndsWith('A')).ToList();
|
||||
var nodeSteps = new List<long>();
|
||||
|
||||
foreach (var startNode in startNodes)
|
||||
{
|
||||
var current = startNode;
|
||||
var steps = 0;
|
||||
|
||||
while (current.Current.EndsWith('Z') is false)
|
||||
{
|
||||
var next = Turns[steps % Turns.Count] switch
|
||||
{
|
||||
'R' => current.Right,
|
||||
'L' => current.Left,
|
||||
_ => throw new Exception("Invalid turn")
|
||||
};
|
||||
current = Nodes.First(n => n.Current == next);
|
||||
steps++;
|
||||
}
|
||||
|
||||
nodeSteps.Add(steps);
|
||||
}
|
||||
|
||||
return FindLeastCommonMultiple(nodeSteps);
|
||||
}
|
||||
}
|
||||
|
||||
public class Node(
|
||||
|
||||
Reference in New Issue
Block a user