-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDay13.cs
109 lines (92 loc) · 3.45 KB
/
Day13.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
using Aoc2024Net.Utilities;
using System.Text.RegularExpressions;
namespace Aoc2024Net.Days
{
internal sealed class Day13 : Day
{
private record Rule(
Coordinate ButtonAShift,
Coordinate ButtonBShift,
Coordinate PrizeLocation);
public override object? SolvePart1() =>
Solve(false);
public override object? SolvePart2() =>
Solve(true);
private long? Solve(bool useBigLocations)
{
var rules = InputData
.GetInputLinesGroups()
.Select(g =>
{
var buttonAMatch = Regex.Match(g[0], @"Button A\: X\+(\d+), Y\+(\d+)");
var buttonBMatch = Regex.Match(g[1], @"Button B\: X\+(\d+), Y\+(\d+)");
var prizeMatch = Regex.Match(g[2], @"Prize\: X\=(\d+), Y\=(\d+)");
return new Rule(
new Coordinate(
buttonAMatch.GetInt32Group(1),
buttonAMatch.GetInt32Group(2)),
new Coordinate(
buttonBMatch.GetInt32Group(1),
buttonBMatch.GetInt32Group(2)),
new Coordinate(
(useBigLocations ? 10000000000000 : 0) + prizeMatch.GetInt32Group(1),
(useBigLocations ? 10000000000000 : 0) + prizeMatch.GetInt32Group(2)));
})
.ToArray();
return rules
.Select(CalculateMinWinCost)
.Where(cost => cost != null)
.Sum();
}
private static long? CalculateMinWinCost(Rule rule)
{
// We have the equations system:
//
// aX* x +bX * y = lX
// aY* x +bY * y = lY
//
// x - A-button clicks count
// y - B-button clicks count
//
// Let's solve it by summin both equations
// to eliminate x first and found y
var xyLcm = LeastCommonMultiple(rule.ButtonAShift.X, rule.ButtonAShift.Y);
var xFactor = xyLcm / rule.ButtonAShift.X;
var yFactor = xyLcm / rule.ButtonAShift.Y;
var bX = rule.ButtonBShift.X * xFactor;
var bY = -rule.ButtonBShift.Y * yFactor;
var lX = rule.PrizeLocation.X * xFactor;
var lY = -rule.PrizeLocation.Y * yFactor;
var y = (lX + lY) / (bX + bY);
var x = (rule.PrizeLocation.X - (rule.ButtonBShift.X * y)) / rule.ButtonAShift.X;
if (rule.ButtonAShift.X * x + rule.ButtonBShift.X * y != rule.PrizeLocation.X ||
rule.ButtonAShift.Y * x + rule.ButtonBShift.Y * y != rule.PrizeLocation.Y)
return null;
return x * 3 + y;
}
// https://stackoverflow.com/a/13569863/2975589
public static long LeastCommonMultiple(long a, long b)
{
long num1, num2;
if (a > b)
{
num1 = a;
num2 = b;
}
else
{
num1 = b;
num2 = a;
}
for (var i = 1; i < num2; i++)
{
var mult = num1 * i;
if (mult % num2 == 0)
{
return mult;
}
}
return num1 * num2;
}
}
}