Skip to content

Commit

Permalink
Merge pull request #14 from MartinZikmund/feature/aoc2024-day13
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinZikmund authored Dec 13, 2024
2 parents 2e0d648 + 84569ee commit 2a9dd37
Show file tree
Hide file tree
Showing 3 changed files with 214 additions and 0 deletions.
99 changes: 99 additions & 0 deletions src/AdventOfCode.Puzzles/2024/13/Part1/Part1.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using AdventOfCode.Puzzles.Tools;

namespace AdventOfCode.Puzzles._2024._13.Part1;

public partial class Part1 : IPuzzleSolution
{
public Task<string> SolveAsync(StreamReader inputReader)
{
long total = 0;
while (TryReadClawMachine(inputReader, out var clawMachine))
{
var price = SolveClawMachine(clawMachine);
if (price > 0)
{
total += price;
}
}

return Task.FromResult(total.ToString());
}

private long SolveClawMachine(ClawMachine clawMachine)
{
var buttonA = clawMachine.ButtonA;
var buttonB = clawMachine.ButtonB;
var prize = clawMachine.Prize;

// a*ax + b*bx = prizeX
// a*ay + b*by = prizeY
// a = (prizeX - b*bx) / ax
// ((prizeX - b*bx) / ax) * ay + b*by = prizeY
// ((prizeX / ax) - (b*bx / ax)) * ay + b*by = prizeY
// (prizeX / ax) * ay - (b*bx / ax) * ay + b*by = prizeY
// - (b * bx / ax) * ay + b * by = prizeY - (prizeX / ax) * ay
// b * by - (b* bx / ax) * ay = prizeY - (prizeX / ax) * ay
// b * (by - (bx / ax) * ay) = prizeY - (prizeX / ax) * ay
// b = (prizeY - (prizeX / ax) * ay) / (by - (bx / ax) * ay)

var prizeX = (double)prize.X;
var prizeY = (double)prize.Y;
var buttonAX = (double)buttonA.X;
var buttonAY = (double)buttonA.Y;
var buttonBX = (double)buttonB.X;
var buttonBY = (double)buttonB.Y;

long b = (long)Math.Round((prizeY - (prizeX / buttonAX) * buttonAY) / (buttonBY - (buttonBX / buttonAX) * buttonAY));
long a = (long)Math.Round((prizeX - b * buttonBX) / buttonAX);

var actualX = a * buttonAX + b * buttonBX;
var actualY = a * buttonAY + b * buttonBY;
if (actualX == prize.X && actualY == prize.Y && a >= 0 && b >= 0)
{
return a * 3 + b;
}

return -1;
}

private bool TryReadClawMachine(StreamReader reader, out ClawMachine clawMachine)
{
clawMachine = default;
var line = reader.ReadLine();
if (line == null)
{
return false;
}

if (string.IsNullOrWhiteSpace(line))
{
line = reader.ReadLine();
}

var buttonALine = line;
var buttonBLine = reader.ReadLine();
var prizeLine = reader.ReadLine();

var parts = buttonALine.Split(":")[1].Split(',');
var buttonAX = int.Parse(parts[0].Trim().Substring(2));
var buttonAY = int.Parse(parts[1].Trim().Substring(2));

parts = buttonBLine.Split(":")[1].Split(',');
var buttonBX = int.Parse(parts[0].Trim().Substring(2));
var buttonBY = int.Parse(parts[1].Trim().Substring(2));

parts = prizeLine.Split(":")[1].Split(',');
var prizeX = int.Parse(parts[0].Trim().Substring(2));
var prizeY = int.Parse(parts[1].Trim().Substring(2));

clawMachine = new ClawMachine(
(buttonAX, buttonAY),
(buttonBX, buttonBY),
(prizeX, prizeY)
);

return true;
}

public record ClawMachine(Point ButtonA, Point ButtonB, Point Prize);
}
100 changes: 100 additions & 0 deletions src/AdventOfCode.Puzzles/2024/13/Part2/Part2.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
using System.Diagnostics;
using AdventOfCode.Puzzles.Tools;

namespace AdventOfCode.Puzzles._2024._13.Part2;

public partial class Part2 : IPuzzleSolution
{
public Task<string> SolveAsync(StreamReader inputReader)
{
long total = 0;
while (TryReadClawMachine(inputReader, out var clawMachine))
{
var price = SolveClawMachine(clawMachine);
if (price > 0)
{
total += price;
}
}

return Task.FromResult(total.ToString());
}

private long SolveClawMachine(ClawMachine clawMachine)
{
var buttonA = clawMachine.ButtonA;
var buttonB = clawMachine.ButtonB;
var prize = clawMachine.Prize;

// a*ax + b*bx = prizeX
// a*ay + b*by = prizeY
// a = (prizeX - b*bx) / ax
// ((prizeX - b*bx) / ax) * ay + b*by = prizeY
// ((prizeX / ax) - (b*bx / ax)) * ay + b*by = prizeY
// (prizeX / ax) * ay - (b*bx / ax) * ay + b*by = prizeY
// - (b * bx / ax) * ay + b * by = prizeY - (prizeX / ax) * ay
// b * by - (b* bx / ax) * ay = prizeY - (prizeX / ax) * ay
// b * (by - (bx / ax) * ay) = prizeY - (prizeX / ax) * ay
// b = (prizeY - (prizeX / ax) * ay) / (by - (bx / ax) * ay)

var prizeX = 10000000000000 + (double)prize.X;
var prizeY = 10000000000000 + (double)prize.Y;
var buttonAX = (double)buttonA.X;
var buttonAY = (double)buttonA.Y;
var buttonBX = (double)buttonB.X;
var buttonBY = (double)buttonB.Y;

long b = (long)Math.Round((prizeY - (prizeX / buttonAX) * buttonAY) / (buttonBY - (buttonBX / buttonAX) * buttonAY));
long a = (long)Math.Round((prizeX - b * buttonBX) / buttonAX);

var actualX = a * buttonAX + b * buttonBX;
var actualY = a * buttonAY + b * buttonBY;
if (actualX == prizeX && actualY == prizeY && a >= 0 && b >= 0)
{
return a * 3 + b;
}

return -1;
}

private bool TryReadClawMachine(StreamReader reader, out ClawMachine clawMachine)
{
clawMachine = default;
var line = reader.ReadLine();
if (line == null)
{
return false;
}

if (string.IsNullOrWhiteSpace(line))
{
line = reader.ReadLine();
}

var buttonALine = line;
var buttonBLine = reader.ReadLine();
var prizeLine = reader.ReadLine();

var parts = buttonALine.Split(":")[1].Split(',');
var buttonAX = int.Parse(parts[0].Trim().Substring(2));
var buttonAY = int.Parse(parts[1].Trim().Substring(2));

parts = buttonBLine.Split(":")[1].Split(',');
var buttonBX = int.Parse(parts[0].Trim().Substring(2));
var buttonBY = int.Parse(parts[1].Trim().Substring(2));

parts = prizeLine.Split(":")[1].Split(',');
var prizeX = int.Parse(parts[0].Trim().Substring(2));
var prizeY = int.Parse(parts[1].Trim().Substring(2));

clawMachine = new ClawMachine(
(buttonAX, buttonAY),
(buttonBX, buttonBY),
(prizeX, prizeY)
);

return true;
}

public record ClawMachine(Point ButtonA, Point ButtonB, Point Prize);
}
15 changes: 15 additions & 0 deletions src/AdventOfCode.Puzzles/2024/13/TestData.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
Button A: X+94, Y+34
Button B: X+22, Y+67
Prize: X=8400, Y=5400

Button A: X+26, Y+66
Button B: X+67, Y+21
Prize: X=12748, Y=12176

Button A: X+17, Y+86
Button B: X+84, Y+37
Prize: X=7870, Y=6450

Button A: X+69, Y+23
Button B: X+27, Y+71
Prize: X=18641, Y=10279

0 comments on commit 2a9dd37

Please sign in to comment.